hls.js 1.6.0-rc.1.0.canary.11073 → 1.6.0-rc.1.0.canary.11076
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hls.d.mts +1 -0
- package/dist/hls.d.ts +1 -0
- package/dist/hls.js +101 -21
- package/dist/hls.js.d.ts +1 -0
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +101 -21
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +108 -21
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +108 -21
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +2 -2
- package/src/config.ts +2 -0
- package/src/controller/base-playlist-controller.ts +24 -0
- package/src/loader/m3u8-parser.ts +62 -7
- package/src/loader/playlist-loader.ts +19 -15
- package/src/utils/level-helper.ts +37 -1
package/dist/hls.mjs
CHANGED
@@ -402,7 +402,7 @@ function enableLogs(debugConfig, context, id) {
|
|
402
402
|
// Some browsers don't allow to use bind on console object anyway
|
403
403
|
// fallback to default if needed
|
404
404
|
try {
|
405
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-rc.1.0.canary.
|
405
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-rc.1.0.canary.11076"}`);
|
406
406
|
} catch (e) {
|
407
407
|
/* log fn threw an exception. All logger methods are no-ops. */
|
408
408
|
return createLogger();
|
@@ -6915,7 +6915,7 @@ const LEVEL_PLAYLIST_REGEX_FAST = new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*
|
|
6915
6915
|
// segment URI, group 3 => the URI (note newline is not eaten)
|
6916
6916
|
/#.*/.source // All other non-segment oriented tags will match with all groups empty
|
6917
6917
|
].join('|'), 'g');
|
6918
|
-
const LEVEL_PLAYLIST_REGEX_SLOW = new RegExp([/#
|
6918
|
+
const LEVEL_PLAYLIST_REGEX_SLOW = new RegExp([/#EXT-X-(PROGRAM-DATE-TIME|BYTERANGE|DATERANGE|DEFINE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/.source, /#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\d+)/.source, /#EXT-X-(DISCONTINUITY|ENDLIST|GAP|INDEPENDENT-SEGMENTS)/.source, /(#)([^:]*):(.*)/.source, /(#)(.*)(?:.*)\r?\n?/.source].join('|'));
|
6919
6919
|
class M3U8Parser {
|
6920
6920
|
static findGroup(groups, mediaGroupId) {
|
6921
6921
|
for (let i = 0; i < groups.length; i++) {
|
@@ -7110,6 +7110,7 @@ class M3U8Parser {
|
|
7110
7110
|
return results;
|
7111
7111
|
}
|
7112
7112
|
static parseLevelPlaylist(string, baseurl, id, type, levelUrlId, multivariantVariableList) {
|
7113
|
+
var _LEVEL_PLAYLIST_REGEX;
|
7113
7114
|
const base = {
|
7114
7115
|
url: baseurl
|
7115
7116
|
};
|
@@ -7131,9 +7132,14 @@ class M3U8Parser {
|
|
7131
7132
|
let firstPdtIndex = -1;
|
7132
7133
|
let createNextFrag = false;
|
7133
7134
|
let nextByteRange = null;
|
7135
|
+
let serverControlAttrs;
|
7134
7136
|
LEVEL_PLAYLIST_REGEX_FAST.lastIndex = 0;
|
7135
7137
|
level.m3u8 = string;
|
7136
7138
|
level.hasVariableRefs = hasVariableReferences(string) ;
|
7139
|
+
if (((_LEVEL_PLAYLIST_REGEX = LEVEL_PLAYLIST_REGEX_FAST.exec(string)) == null ? void 0 : _LEVEL_PLAYLIST_REGEX[0]) !== '#EXTM3U') {
|
7140
|
+
level.playlistParsingError = new Error('Missing format identifier #EXTM3U');
|
7141
|
+
return level;
|
7142
|
+
}
|
7137
7143
|
while ((result = LEVEL_PLAYLIST_REGEX_FAST.exec(string)) !== null) {
|
7138
7144
|
if (createNextFrag) {
|
7139
7145
|
createNextFrag = false;
|
@@ -7222,15 +7228,23 @@ class M3U8Parser {
|
|
7222
7228
|
}
|
7223
7229
|
break;
|
7224
7230
|
case 'PLAYLIST-TYPE':
|
7231
|
+
if (level.type) {
|
7232
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7233
|
+
}
|
7225
7234
|
level.type = value1.toUpperCase();
|
7226
7235
|
break;
|
7227
7236
|
case 'MEDIA-SEQUENCE':
|
7237
|
+
if (level.startSN !== 0) {
|
7238
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7239
|
+
} else if (fragments.length > 0) {
|
7240
|
+
assignMustAppearBeforeSegmentsError(level, tag, result);
|
7241
|
+
}
|
7228
7242
|
currentSN = level.startSN = parseInt(value1);
|
7229
7243
|
break;
|
7230
7244
|
case 'SKIP':
|
7231
7245
|
{
|
7232
7246
|
if (level.skippedSegments) {
|
7233
|
-
level
|
7247
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7234
7248
|
}
|
7235
7249
|
const skipAttrs = new AttrList(value1, level);
|
7236
7250
|
const skippedSegments = skipAttrs.decimalInteger('SKIPPED-SEGMENTS');
|
@@ -7249,15 +7263,23 @@ class M3U8Parser {
|
|
7249
7263
|
break;
|
7250
7264
|
}
|
7251
7265
|
case 'TARGETDURATION':
|
7266
|
+
if (level.targetduration !== 0) {
|
7267
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7268
|
+
}
|
7252
7269
|
level.targetduration = Math.max(parseInt(value1), 1);
|
7253
7270
|
break;
|
7254
7271
|
case 'VERSION':
|
7272
|
+
if (level.version !== null) {
|
7273
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7274
|
+
}
|
7255
7275
|
level.version = parseInt(value1);
|
7256
7276
|
break;
|
7257
7277
|
case 'INDEPENDENT-SEGMENTS':
|
7258
|
-
case 'EXTM3U':
|
7259
7278
|
break;
|
7260
7279
|
case 'ENDLIST':
|
7280
|
+
if (!level.live) {
|
7281
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7282
|
+
}
|
7261
7283
|
level.live = false;
|
7262
7284
|
break;
|
7263
7285
|
case '#':
|
@@ -7309,6 +7331,11 @@ class M3U8Parser {
|
|
7309
7331
|
break;
|
7310
7332
|
}
|
7311
7333
|
case 'DISCONTINUITY-SEQUENCE':
|
7334
|
+
if (level.startCC !== 0) {
|
7335
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7336
|
+
} else if (fragments.length > 0) {
|
7337
|
+
assignMustAppearBeforeSegmentsError(level, tag, result);
|
7338
|
+
}
|
7312
7339
|
level.startCC = discontinuityCounter = parseInt(value1);
|
7313
7340
|
break;
|
7314
7341
|
case 'KEY':
|
@@ -7367,7 +7394,10 @@ class M3U8Parser {
|
|
7367
7394
|
}
|
7368
7395
|
case 'SERVER-CONTROL':
|
7369
7396
|
{
|
7370
|
-
|
7397
|
+
if (serverControlAttrs) {
|
7398
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7399
|
+
}
|
7400
|
+
serverControlAttrs = new AttrList(value1);
|
7371
7401
|
level.canBlockReload = serverControlAttrs.bool('CAN-BLOCK-RELOAD');
|
7372
7402
|
level.canSkipUntil = serverControlAttrs.optionalFloat('CAN-SKIP-UNTIL', 0);
|
7373
7403
|
level.canSkipDateRanges = level.canSkipUntil > 0 && serverControlAttrs.bool('CAN-SKIP-DATERANGES');
|
@@ -7377,6 +7407,9 @@ class M3U8Parser {
|
|
7377
7407
|
}
|
7378
7408
|
case 'PART-INF':
|
7379
7409
|
{
|
7410
|
+
if (level.partTarget) {
|
7411
|
+
assignMultipleMediaPlaylistTagOccuranceError(level, tag, result);
|
7412
|
+
}
|
7380
7413
|
const partInfAttrs = new AttrList(value1);
|
7381
7414
|
level.partTarget = partInfAttrs.decimalFloatingPoint('PART-TARGET');
|
7382
7415
|
break;
|
@@ -7428,6 +7461,9 @@ class M3U8Parser {
|
|
7428
7461
|
setFragLevelKeys(frag, levelkeys, level);
|
7429
7462
|
}
|
7430
7463
|
}
|
7464
|
+
if (!level.targetduration) {
|
7465
|
+
level.playlistParsingError = new Error(`#EXT-X-TARGETDURATION is required`);
|
7466
|
+
}
|
7431
7467
|
const fragmentLength = fragments.length;
|
7432
7468
|
const firstFragment = fragments[0];
|
7433
7469
|
const lastFragment = fragments[fragmentLength - 1];
|
@@ -7605,6 +7641,12 @@ function setFragLevelKeys(frag, levelkeys, level) {
|
|
7605
7641
|
encryptedFragments.push(frag);
|
7606
7642
|
}
|
7607
7643
|
}
|
7644
|
+
function assignMultipleMediaPlaylistTagOccuranceError(level, tag, result) {
|
7645
|
+
level.playlistParsingError = new Error(`#EXT-X-${tag} must not appear more than once (${result[0]})`);
|
7646
|
+
}
|
7647
|
+
function assignMustAppearBeforeSegmentsError(level, tag, result) {
|
7648
|
+
level.playlistParsingError = new Error(`#EXT-X-${tag} must appear before the first Media Segment (${result[0]})`);
|
7649
|
+
}
|
7608
7650
|
|
7609
7651
|
function updateFromToPTS(fragFrom, fragTo) {
|
7610
7652
|
const fragToPTS = fragTo.startPTS;
|
@@ -7892,9 +7934,24 @@ function mapFragmentIntersection(oldDetails, newDetails, intersectionFn) {
|
|
7892
7934
|
}
|
7893
7935
|
if (oldFrag && newFrag) {
|
7894
7936
|
intersectionFn(oldFrag, newFrag, i, newFrags);
|
7937
|
+
if (oldFrag.url && oldFrag.url !== newFrag.url) {
|
7938
|
+
newDetails.playlistParsingError = getSequenceError(`media sequence mismatch ${newFrag.sn}:`, oldDetails, newDetails, oldFrag, newFrag);
|
7939
|
+
return;
|
7940
|
+
} else if (oldFrag.cc !== newFrag.cc) {
|
7941
|
+
newDetails.playlistParsingError = getSequenceError(`discontinuity sequence mismatch (${oldFrag.cc}!=${newFrag.cc})`, oldDetails, newDetails, oldFrag, newFrag);
|
7942
|
+
return;
|
7943
|
+
}
|
7895
7944
|
}
|
7896
7945
|
}
|
7897
7946
|
}
|
7947
|
+
function getSequenceError(message, oldDetails, newDetails, oldFrag, newFrag) {
|
7948
|
+
return new Error(`${message} ${newFrag.url}
|
7949
|
+
Playlist starting @${oldDetails.startSN}
|
7950
|
+
${oldDetails.m3u8}
|
7951
|
+
|
7952
|
+
Playlist starting @${newDetails.startSN}
|
7953
|
+
${newDetails.m3u8}`);
|
7954
|
+
}
|
7898
7955
|
function adjustSliding(oldDetails, newDetails, matchingStableVariantOrRendition = true) {
|
7899
7956
|
const delta = newDetails.startSN + newDetails.skippedSegments - oldDetails.startSN;
|
7900
7957
|
const oldFragments = oldDetails.fragments;
|
@@ -10001,7 +10058,7 @@ function requireEventemitter3 () {
|
|
10001
10058
|
var eventemitter3Exports = requireEventemitter3();
|
10002
10059
|
var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
|
10003
10060
|
|
10004
|
-
const version = "1.6.0-rc.1.0.canary.
|
10061
|
+
const version = "1.6.0-rc.1.0.canary.11076";
|
10005
10062
|
|
10006
10063
|
// ensure the worker ends up in the bundle
|
10007
10064
|
// If the worker should not be included this gets aliased to empty.js
|
@@ -17192,6 +17249,31 @@ class BasePlaylistController extends Logger {
|
|
17192
17249
|
// Merge live playlists to adjust fragment starts and fill in delta playlist skipped segments
|
17193
17250
|
if (previousDetails && details.fragments.length > 0) {
|
17194
17251
|
mergeDetails(previousDetails, details);
|
17252
|
+
const error = details.playlistParsingError;
|
17253
|
+
if (error) {
|
17254
|
+
this.warn(error);
|
17255
|
+
const hls = this.hls;
|
17256
|
+
if (!hls.config.ignorePlaylistParsingErrors) {
|
17257
|
+
var _details$fragments$;
|
17258
|
+
const {
|
17259
|
+
networkDetails
|
17260
|
+
} = data;
|
17261
|
+
hls.trigger(Events.ERROR, {
|
17262
|
+
type: ErrorTypes.NETWORK_ERROR,
|
17263
|
+
details: ErrorDetails.LEVEL_PARSING_ERROR,
|
17264
|
+
fatal: false,
|
17265
|
+
url: details.url,
|
17266
|
+
error,
|
17267
|
+
reason: error.message,
|
17268
|
+
level: data.level || undefined,
|
17269
|
+
parent: (_details$fragments$ = details.fragments[0]) == null ? void 0 : _details$fragments$.type,
|
17270
|
+
networkDetails,
|
17271
|
+
stats
|
17272
|
+
});
|
17273
|
+
return;
|
17274
|
+
}
|
17275
|
+
details.playlistParsingError = null;
|
17276
|
+
}
|
17195
17277
|
}
|
17196
17278
|
if (details.requestScheduled === -1) {
|
17197
17279
|
details.requestScheduled = stats.loading.start;
|
@@ -29695,6 +29777,7 @@ const hlsDefaultConfig = _objectSpread2(_objectSpread2({
|
|
29695
29777
|
// used by fps-controller
|
29696
29778
|
appendErrorMaxRetry: 3,
|
29697
29779
|
// used by buffer-controller
|
29780
|
+
ignorePlaylistParsingErrors: false,
|
29698
29781
|
loader: XhrLoader,
|
29699
29782
|
// loader: FetchLoader,
|
29700
29783
|
fLoader: undefined,
|
@@ -33791,21 +33874,25 @@ class PlaylistLoader {
|
|
33791
33874
|
}
|
33792
33875
|
const error = levelDetails.playlistParsingError;
|
33793
33876
|
if (error) {
|
33794
|
-
hls.
|
33795
|
-
|
33796
|
-
|
33797
|
-
|
33798
|
-
|
33799
|
-
|
33800
|
-
|
33801
|
-
|
33802
|
-
|
33803
|
-
|
33804
|
-
|
33805
|
-
|
33806
|
-
|
33807
|
-
|
33808
|
-
|
33877
|
+
this.hls.logger.warn(error);
|
33878
|
+
if (!hls.config.ignorePlaylistParsingErrors) {
|
33879
|
+
hls.trigger(Events.ERROR, {
|
33880
|
+
type: ErrorTypes.NETWORK_ERROR,
|
33881
|
+
details: ErrorDetails.LEVEL_PARSING_ERROR,
|
33882
|
+
fatal: false,
|
33883
|
+
url,
|
33884
|
+
error,
|
33885
|
+
reason: error.message,
|
33886
|
+
response,
|
33887
|
+
context,
|
33888
|
+
level: levelIndex,
|
33889
|
+
parent,
|
33890
|
+
networkDetails,
|
33891
|
+
stats
|
33892
|
+
});
|
33893
|
+
return;
|
33894
|
+
}
|
33895
|
+
levelDetails.playlistParsingError = null;
|
33809
33896
|
}
|
33810
33897
|
if (levelDetails.live && loader) {
|
33811
33898
|
if (loader.getCacheAge) {
|