diff --git a/src/loader/m3u8-parser.ts b/src/loader/m3u8-parser.ts index ae61a616c26..8300d799093 100644 --- a/src/loader/m3u8-parser.ts +++ b/src/loader/m3u8-parser.ts @@ -61,6 +61,10 @@ const LEVEL_PLAYLIST_REGEX_SLOW = new RegExp( const MP4_REGEX_SUFFIX = /\.(mp4|m4s|m4v|m4a)$/i; +function isMP4Url(url: string): boolean { + return MP4_REGEX_SUFFIX.test(URLToolkit.parseURL(url)?.path ?? ''); +} + export default class M3U8Parser { static findGroup( groups: Array, @@ -511,8 +515,8 @@ export default class M3U8Parser { // if the fragments are TS or MP4, except if we download them :/ // but this is to be able to handle SIDX. if ( - level.fragments.every((frag) => - MP4_REGEX_SUFFIX.test(frag.relurl as string) + level.fragments.every( + (frag) => frag.relurl && isMP4Url(frag.relurl) ) ) { logger.warn( diff --git a/tests/unit/loader/playlist-loader.js b/tests/unit/loader/playlist-loader.js index 34f12b09b48..c1b06603035 100644 --- a/tests/unit/loader/playlist-loader.js +++ b/tests/unit/loader/playlist-loader.js @@ -344,6 +344,23 @@ http://proxy-62.dailymotion.com/sec(3ae40f708f79ca9471f52b86da76a3a8)/video/107/ ); }); + it('handles a missing init segment for mp4 segment urls', function () { + const level = `#EXTM3U +#EXT-X-VERSION:3 +#EXT-X-PLAYLIST-TYPE:VOD +#EXT-X-TARGETDURATION:14 +#EXTINF:11.360, +/something.mp4?abc +#EXT-X-ENDLIST`; + const result = M3U8Parser.parseLevelPlaylist( + level, + 'http://example.invalid/playlist.m3u8', + 0 + ); + expect(result.initSegment).to.be.ok; + expect(result.initSegment.relurl).to.equal('/something.mp4?abc'); + }); + it('parse level with single char fragment URI', function () { const level = `#EXTM3U #EXT-X-ALLOW-CACHE:NO