Skip to content

Commit 903f463

Browse files
committed
Fix "Missing format identifier #EXTM3U" playlist parsing errors
Fixes #7531
1 parent 35f919d commit 903f463

File tree

3 files changed

+27
-41
lines changed

3 files changed

+27
-41
lines changed

src/loader/m3u8-parser.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,10 @@ export default class M3U8Parser {
119119
const levelsWithKnownCodecs: LevelParsed[] = [];
120120

121121
MASTER_PLAYLIST_REGEX.lastIndex = 0;
122-
122+
if (!string.startsWith('#EXTM3U')) {
123+
parsed.playlistParsingError = new Error('no EXTM3U delimiter');
124+
return parsed;
125+
}
123126
let result: RegExpExecArray | null;
124127
while ((result = MASTER_PLAYLIST_REGEX.exec(string)) != null) {
125128
if (result[1]) {
@@ -710,9 +713,7 @@ export default class M3U8Parser {
710713
}
711714
}
712715
if (!level.targetduration) {
713-
level.playlistParsingError = new Error(
714-
`#EXT-X-TARGETDURATION is required`,
715-
);
716+
level.playlistParsingError = new Error(`Missing Target Duration`);
716717
}
717718
const fragmentLength = fragments.length;
718719
const firstFragment = fragments[0];

src/loader/playlist-loader.ts

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -345,18 +345,6 @@ class PlaylistLoader implements NetworkComponentAPI {
345345

346346
const string = response.data as string;
347347

348-
// Validate if it is an M3U8 at all
349-
if (string.indexOf('#EXTM3U') !== 0) {
350-
this.handleManifestParsingError(
351-
response,
352-
context,
353-
new Error('no EXTM3U delimiter'),
354-
networkDetails || null,
355-
stats,
356-
);
357-
return;
358-
}
359-
360348
stats.parsing.start = performance.now();
361349
if (
362350
M3U8Parser.isMediaPlaylist(string) ||
@@ -734,29 +722,6 @@ class PlaylistLoader implements NetworkComponentAPI {
734722
typeof context.level === 'number' && parent === PlaylistLevelType.MAIN
735723
? (level as number)
736724
: undefined;
737-
if (!levelDetails.fragments.length) {
738-
const error = (levelDetails.playlistParsingError = new Error(
739-
'No Segments found in Playlist',
740-
));
741-
hls.trigger(Events.ERROR, {
742-
type: ErrorTypes.NETWORK_ERROR,
743-
details: ErrorDetails.LEVEL_EMPTY_ERROR,
744-
fatal: false,
745-
url,
746-
error,
747-
reason: error.message,
748-
response,
749-
context,
750-
level: levelIndex,
751-
parent,
752-
networkDetails,
753-
stats,
754-
});
755-
return;
756-
}
757-
if (!levelDetails.targetduration) {
758-
levelDetails.playlistParsingError = new Error('Missing Target Duration');
759-
}
760725
const error = levelDetails.playlistParsingError;
761726
if (error) {
762727
this.hls.logger.warn(`${error} ${levelDetails.url}`);
@@ -779,6 +744,26 @@ class PlaylistLoader implements NetworkComponentAPI {
779744
}
780745
levelDetails.playlistParsingError = null;
781746
}
747+
if (!levelDetails.fragments.length) {
748+
const error = (levelDetails.playlistParsingError = new Error(
749+
'No Segments found in Playlist',
750+
));
751+
hls.trigger(Events.ERROR, {
752+
type: ErrorTypes.NETWORK_ERROR,
753+
details: ErrorDetails.LEVEL_EMPTY_ERROR,
754+
fatal: false,
755+
url,
756+
error,
757+
reason: error.message,
758+
response,
759+
context,
760+
level: levelIndex,
761+
parent,
762+
networkDetails,
763+
stats,
764+
});
765+
return;
766+
}
782767

783768
if (levelDetails.live && loader) {
784769
if (loader.getCacheAge) {

tests/unit/loader/m3u8-parser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ describe('M3U8Parser', function () {
1919
);
2020
expect(result.levels).to.deep.equal([]);
2121
expect(result.sessionData).to.equal(null);
22-
expectPlaylistParsingError(result, 'no levels found in manifest');
22+
expectPlaylistParsingError(result, 'no EXTM3U delimiter');
2323
});
2424

2525
it('manifest with broken syntax returns empty array', function () {
26-
const manifest = `#EXTXSTREAMINF:PROGRAM-ID=1,BANDWIDTH=836280,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=848x360,NAME="480"
26+
const manifest = `#EXTM3U#EXTXSTREAMINF:PROGRAM-ID=1,BANDWIDTH=836280,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=848x360,NAME="480"
2727
http://proxy-62.dailymotion.com/sec(3ae40f708f79ca9471f52b86da76a3a8)/video/107/282/158282701_mp4_h264_aac_hq.m3u8#cell=core`;
2828
const result = M3U8Parser.parseMasterPlaylist(
2929
manifest,

0 commit comments

Comments
 (0)