kuu / hls-parser

A simple library to read/write HLS playlists
MIT License
130 stars 49 forks source link

HLS parser fails to parse 'hello, world' m3u8 & m3u files #30

Closed cmacq2 closed 5 years ago

cmacq2 commented 6 years ago

The hls-parser is somewhat opinionated about constructs which turn up in 'real world' scenario's, such as the BipBop hello world HLS stream. To demonstrate:

/*
 * videojs-contrib-hls project suggests the following 'Hello, world' type HLS example:
 * https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8
 *
 * It's essentially the NTSC test signal with a few tracks of varying qualities,
 * a few audio tracks, subtitles and so on
 *
 * Note the main tracks are loops of the test signal to get to a 30min duration.
 *
 * ...
 *
 * hls-parser *should* be able to parse & stringify this
 */

const fetch = require('node-fetch');
const HLSParser = require('hls-parser');

// test the master playlist
/*
 * It fails because, it turns out subtitles *can* be forced
 */
const masterPlaylist = fetch('https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8')
    .then(response => response.text())
    .then(HLSParser.parse)
    .then(HLSParser.stringify)
    .then(() => console.log('Master playlist: PASS'))
    .catch(error => console.log('Master playlist: FAIL\n', error));

// test the gear1 variant referenced from the master playlist
/*
 * It fails becasue it is a loop of a segment and hls-parser is opinionated about this
 * ... similarly it does not like re-used keys/IVs in sequences such as IV_A, IV_B, IV_A (which is admittedly strange but still 'valid')
 */
const gear1 = fetch('https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/gear1/prog_index.m3u8')
    .then(response => response.text())
    .then(HLSParser.parse)
    .then(HLSParser.stringify)
    .then(() => console.log('Gear1 channel playlist: PASS'))
    .catch(error => console.log('Gear1 channel playlist: FAIL\n', error));

I guess the question is: should hls-parser relax some of its assertions to cope with this?

kuu commented 6 years ago

@cmacq2 Thanks for sharing the real-world scenarios. I agree with the idea of relaxing assertions in those cases. I think we can simply disable any assertions unless a special environment variable is set. Here's the change:

https://github.com/kuu/hls-parser/commit/2c54adc138c5a1def267a9cc3cc397df0b41d8bb

Please tell me your opinion. Thanks

cmacq2 commented 6 years ago

This approach should sort of work, but I think it is not very obvious to the user of the library and a bit awkward to use. If possible it would be a lot nicer (and more in keeping with lots of other JavaScript libraries) if a developer could optionally pass an options property hash to parse() etc. Code using this convention would look like this:

const HLSParser = require('hls-parser');

const text = ... // obtain m3u text somehow

const parsed = HLSParser.parse(text, {strict: false});
kuu commented 5 years ago

The default behavior has changed and now the library does not throw unless {strictMode: true} is specified via HLS.setOptions() The change has already been published as hls-parser@0.3.0