hls.js 1.4.5 → 1.4.7
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.js +54 -46
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +11 -5
- 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 +13 -5
- 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 +60 -52
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +1 -1
- package/src/controller/base-stream-controller.ts +4 -0
- package/src/controller/error-controller.ts +5 -3
- package/src/controller/subtitle-stream-controller.ts +21 -20
- package/src/controller/timeline-controller.ts +23 -24
- package/src/utils/webvtt-parser.ts +8 -6
- package/src/utils/xhr-loader.ts +1 -0
package/dist/hls.mjs
CHANGED
|
@@ -402,7 +402,7 @@ function enableLogs(debugConfig, 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
|
-
exportedLogger.log(`Debug logs enabled for "${id}" in hls.js version ${"1.4.
|
|
405
|
+
exportedLogger.log(`Debug logs enabled for "${id}" in hls.js version ${"1.4.7"}`);
|
|
406
406
|
} catch (e) {
|
|
407
407
|
exportedLogger = fakeLogger;
|
|
408
408
|
}
|
|
@@ -5486,15 +5486,20 @@ class ErrorController {
|
|
|
5486
5486
|
var _data$frag, _data$context2;
|
|
5487
5487
|
// Search for next level to retry
|
|
5488
5488
|
let nextLevel = -1;
|
|
5489
|
-
const
|
|
5489
|
+
const {
|
|
5490
|
+
levels,
|
|
5491
|
+
loadLevel,
|
|
5492
|
+
minAutoLevel,
|
|
5493
|
+
maxAutoLevel
|
|
5494
|
+
} = hls;
|
|
5490
5495
|
const fragErrorType = (_data$frag = data.frag) == null ? void 0 : _data$frag.type;
|
|
5491
5496
|
const {
|
|
5492
5497
|
type: playlistErrorType,
|
|
5493
5498
|
groupId: playlistErrorGroupId
|
|
5494
5499
|
} = (_data$context2 = data.context) != null ? _data$context2 : {};
|
|
5495
5500
|
for (let i = levels.length; i--;) {
|
|
5496
|
-
const candidate = (i +
|
|
5497
|
-
if (candidate !==
|
|
5501
|
+
const candidate = (i + loadLevel) % levels.length;
|
|
5502
|
+
if (candidate !== loadLevel && candidate >= minAutoLevel && candidate <= maxAutoLevel && levels[candidate].loadError === 0) {
|
|
5498
5503
|
const levelCandidate = levels[candidate];
|
|
5499
5504
|
// Skip level switch if GAP tag is found in next level at same position
|
|
5500
5505
|
if (data.details === ErrorDetails.FRAG_GAP && data.frag) {
|
|
@@ -9334,6 +9339,8 @@ class BaseStreamController extends TaskLoop {
|
|
|
9334
9339
|
} else {
|
|
9335
9340
|
logger.warn(`${data.details} reached or exceeded max retry (${retryCount})`);
|
|
9336
9341
|
}
|
|
9342
|
+
} else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
|
|
9343
|
+
this.state = State.WAITING_LEVEL;
|
|
9337
9344
|
} else {
|
|
9338
9345
|
this.state = State.ERROR;
|
|
9339
9346
|
}
|
|
@@ -17600,16 +17607,7 @@ class SubtitleStreamController extends BaseStreamController {
|
|
|
17600
17607
|
endOffset
|
|
17601
17608
|
} = data;
|
|
17602
17609
|
if (startOffset === 0 && endOffset !== Number.POSITIVE_INFINITY) {
|
|
17603
|
-
const
|
|
17604
|
-
currentTrackId,
|
|
17605
|
-
levels
|
|
17606
|
-
} = this;
|
|
17607
|
-
if (!levels.length || !levels[currentTrackId] || !levels[currentTrackId].details) {
|
|
17608
|
-
return;
|
|
17609
|
-
}
|
|
17610
|
-
const trackDetails = levels[currentTrackId].details;
|
|
17611
|
-
const targetDuration = trackDetails.targetduration;
|
|
17612
|
-
const endOffsetSubtitles = endOffset - targetDuration;
|
|
17610
|
+
const endOffsetSubtitles = endOffset - 1;
|
|
17613
17611
|
if (endOffsetSubtitles <= 0) {
|
|
17614
17612
|
return;
|
|
17615
17613
|
}
|
|
@@ -17805,21 +17803,18 @@ class SubtitleStreamController extends BaseStreamController {
|
|
|
17805
17803
|
if (!levels.length || !track || !track.details) {
|
|
17806
17804
|
return;
|
|
17807
17805
|
}
|
|
17808
|
-
|
|
17809
|
-
// Expand range of subs loaded by one target-duration in either direction to make up for misaligned playlists
|
|
17810
|
-
const trackDetails = track.details;
|
|
17811
|
-
const targetDuration = trackDetails.targetduration;
|
|
17812
17806
|
const {
|
|
17813
17807
|
config
|
|
17814
17808
|
} = this;
|
|
17815
17809
|
const currentTime = this.getLoadPosition();
|
|
17816
|
-
const bufferedInfo = BufferHelper.bufferedInfo(this.tracksBuffered[this.currentTrackId] || [], currentTime
|
|
17810
|
+
const bufferedInfo = BufferHelper.bufferedInfo(this.tracksBuffered[this.currentTrackId] || [], currentTime, config.maxBufferHole);
|
|
17817
17811
|
const {
|
|
17818
17812
|
end: targetBufferTime,
|
|
17819
17813
|
len: bufferLen
|
|
17820
17814
|
} = bufferedInfo;
|
|
17821
17815
|
const mainBufferInfo = this.getFwdBufferInfo(this.media, PlaylistLevelType.MAIN);
|
|
17822
|
-
const
|
|
17816
|
+
const trackDetails = track.details;
|
|
17817
|
+
const maxBufLen = this.getMaxBufferLength(mainBufferInfo == null ? void 0 : mainBufferInfo.len) + trackDetails.levelTargetDuration;
|
|
17823
17818
|
if (bufferLen > maxBufLen) {
|
|
17824
17819
|
return;
|
|
17825
17820
|
}
|
|
@@ -17829,10 +17824,9 @@ class SubtitleStreamController extends BaseStreamController {
|
|
|
17829
17824
|
let foundFrag = null;
|
|
17830
17825
|
const fragPrevious = this.fragPrevious;
|
|
17831
17826
|
if (targetBufferTime < end) {
|
|
17832
|
-
const
|
|
17833
|
-
|
|
17834
|
-
|
|
17835
|
-
foundFrag = findFragmentByPTS(fragPrevious, fragments, Math.max(fragments[0].start, targetBufferTime), maxFragLookUpTolerance);
|
|
17827
|
+
const tolerance = config.maxFragLookUpTolerance;
|
|
17828
|
+
const lookupTolerance = targetBufferTime > end - tolerance ? 0 : tolerance;
|
|
17829
|
+
foundFrag = findFragmentByPTS(fragPrevious, fragments, Math.max(fragments[0].start, targetBufferTime), lookupTolerance);
|
|
17836
17830
|
if (!foundFrag && fragPrevious && fragPrevious.start < fragments[0].start) {
|
|
17837
17831
|
foundFrag = fragments[0];
|
|
17838
17832
|
}
|
|
@@ -17843,6 +17837,14 @@ class SubtitleStreamController extends BaseStreamController {
|
|
|
17843
17837
|
return;
|
|
17844
17838
|
}
|
|
17845
17839
|
foundFrag = this.mapToInitFragWhenRequired(foundFrag);
|
|
17840
|
+
if (foundFrag.sn !== 'initSegment') {
|
|
17841
|
+
// Load earlier fragment in same discontinuity to make up for misaligned playlists and cues that extend beyond end of segment
|
|
17842
|
+
const curSNIdx = foundFrag.sn - trackDetails.startSN;
|
|
17843
|
+
const prevFrag = fragments[curSNIdx - 1];
|
|
17844
|
+
if (prevFrag && prevFrag.cc === foundFrag.cc && this.fragmentTracker.getState(prevFrag) === FragmentState.NOT_LOADED) {
|
|
17845
|
+
foundFrag = prevFrag;
|
|
17846
|
+
}
|
|
17847
|
+
}
|
|
17846
17848
|
if (this.fragmentTracker.getState(foundFrag) === FragmentState.NOT_LOADED) {
|
|
17847
17849
|
// only load if fragment is not loaded
|
|
17848
17850
|
this.loadFragment(foundFrag, track, targetBufferTime);
|
|
@@ -21186,7 +21188,7 @@ function parseWebVTT(vttByteArray, initPTS, vttCCs, cc, timeOffset, callBack, er
|
|
|
21186
21188
|
// Uint8Array.prototype.reduce is not implemented in IE11
|
|
21187
21189
|
const vttLines = utf8ArrayToStr(new Uint8Array(vttByteArray)).trim().replace(LINEBREAKS, '\n').split('\n');
|
|
21188
21190
|
const cues = [];
|
|
21189
|
-
const init90kHz = toMpegTsClockFromTimescale(initPTS.baseTime, initPTS.timescale);
|
|
21191
|
+
const init90kHz = initPTS ? toMpegTsClockFromTimescale(initPTS.baseTime, initPTS.timescale) : 0;
|
|
21190
21192
|
let cueTime = '00:00.000';
|
|
21191
21193
|
let timestampMapMPEGTS = 0;
|
|
21192
21194
|
let timestampMapLOCAL = 0;
|
|
@@ -21210,6 +21212,10 @@ function parseWebVTT(vttByteArray, initPTS, vttCCs, cc, timeOffset, callBack, er
|
|
|
21210
21212
|
}
|
|
21211
21213
|
}
|
|
21212
21214
|
if (webVttMpegTsMapOffset) {
|
|
21215
|
+
if (!initPTS) {
|
|
21216
|
+
parsingError = new Error('Missing initPTS for VTT MPEGTS');
|
|
21217
|
+
return;
|
|
21218
|
+
}
|
|
21213
21219
|
// If we have MPEGTS, offset = presentation time + discontinuity offset
|
|
21214
21220
|
cueOffset = webVttMpegTsMapOffset - vttCCs.presentationOffset;
|
|
21215
21221
|
}
|
|
@@ -21705,7 +21711,7 @@ class TimelineController {
|
|
|
21705
21711
|
this.captionsTracks = {};
|
|
21706
21712
|
this.nonNativeCaptionsTracks = {};
|
|
21707
21713
|
this.textTracks = [];
|
|
21708
|
-
this.unparsedVttFrags =
|
|
21714
|
+
this.unparsedVttFrags = [];
|
|
21709
21715
|
this.initPTS = [];
|
|
21710
21716
|
if (this.cea608Parser1 && this.cea608Parser2) {
|
|
21711
21717
|
this.cea608Parser1.reset();
|
|
@@ -21849,26 +21855,9 @@ class TimelineController {
|
|
|
21849
21855
|
frag,
|
|
21850
21856
|
payload
|
|
21851
21857
|
} = data;
|
|
21852
|
-
const {
|
|
21853
|
-
initPTS,
|
|
21854
|
-
unparsedVttFrags
|
|
21855
|
-
} = this;
|
|
21856
21858
|
if (frag.type === PlaylistLevelType.SUBTITLE) {
|
|
21857
21859
|
// If fragment is subtitle type, parse as WebVTT.
|
|
21858
21860
|
if (payload.byteLength) {
|
|
21859
|
-
// We need an initial synchronisation PTS. Store fragments as long as none has arrived.
|
|
21860
|
-
if (!initPTS[frag.cc]) {
|
|
21861
|
-
unparsedVttFrags.push(data);
|
|
21862
|
-
if (initPTS.length) {
|
|
21863
|
-
// finish unsuccessfully, otherwise the subtitle-stream-controller could be blocked from loading new frags.
|
|
21864
|
-
this.hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
|
21865
|
-
success: false,
|
|
21866
|
-
frag,
|
|
21867
|
-
error: new Error('Missing initial subtitle PTS')
|
|
21868
|
-
});
|
|
21869
|
-
}
|
|
21870
|
-
return;
|
|
21871
|
-
}
|
|
21872
21861
|
const decryptData = frag.decryptdata;
|
|
21873
21862
|
// fragment after decryption has a stats object
|
|
21874
21863
|
const decrypted = ('stats' in data);
|
|
@@ -21887,7 +21876,7 @@ class TimelineController {
|
|
|
21887
21876
|
if (trackPlaylistMedia && trackPlaylistMedia.textCodec === IMSC1_CODEC) {
|
|
21888
21877
|
this._parseIMSC1(frag, payload);
|
|
21889
21878
|
} else {
|
|
21890
|
-
this._parseVTTs(
|
|
21879
|
+
this._parseVTTs(data);
|
|
21891
21880
|
}
|
|
21892
21881
|
}
|
|
21893
21882
|
} else {
|
|
@@ -21917,21 +21906,43 @@ class TimelineController {
|
|
|
21917
21906
|
});
|
|
21918
21907
|
});
|
|
21919
21908
|
}
|
|
21920
|
-
_parseVTTs(
|
|
21909
|
+
_parseVTTs(data) {
|
|
21921
21910
|
var _frag$initSegment;
|
|
21911
|
+
const {
|
|
21912
|
+
frag,
|
|
21913
|
+
payload
|
|
21914
|
+
} = data;
|
|
21915
|
+
// We need an initial synchronisation PTS. Store fragments as long as none has arrived
|
|
21916
|
+
const {
|
|
21917
|
+
initPTS,
|
|
21918
|
+
unparsedVttFrags
|
|
21919
|
+
} = this;
|
|
21920
|
+
const maxAvCC = initPTS.length - 1;
|
|
21921
|
+
if (!initPTS[frag.cc] && maxAvCC === -1) {
|
|
21922
|
+
unparsedVttFrags.push(data);
|
|
21923
|
+
return;
|
|
21924
|
+
}
|
|
21922
21925
|
const hls = this.hls;
|
|
21923
21926
|
// Parse the WebVTT file contents.
|
|
21924
21927
|
const payloadWebVTT = (_frag$initSegment = frag.initSegment) != null && _frag$initSegment.data ? appendUint8Array(frag.initSegment.data, new Uint8Array(payload)) : payload;
|
|
21925
|
-
parseWebVTT(payloadWebVTT, this.initPTS[frag.cc], vttCCs, frag.cc, frag.start, cues => {
|
|
21928
|
+
parseWebVTT(payloadWebVTT, this.initPTS[frag.cc], this.vttCCs, frag.cc, frag.start, cues => {
|
|
21926
21929
|
this._appendCues(cues, frag.level);
|
|
21927
21930
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
|
21928
21931
|
success: true,
|
|
21929
21932
|
frag: frag
|
|
21930
21933
|
});
|
|
21931
21934
|
}, error => {
|
|
21932
|
-
|
|
21935
|
+
const missingInitPTS = error.message === 'Missing initPTS for VTT MPEGTS';
|
|
21936
|
+
if (missingInitPTS) {
|
|
21937
|
+
unparsedVttFrags.push(data);
|
|
21938
|
+
} else {
|
|
21939
|
+
this._fallbackToIMSC1(frag, payload);
|
|
21940
|
+
}
|
|
21933
21941
|
// Something went wrong while parsing. Trigger event with success false.
|
|
21934
21942
|
logger.log(`Failed to parse VTT cue: ${error}`);
|
|
21943
|
+
if (missingInitPTS && maxAvCC > frag.cc) {
|
|
21944
|
+
return;
|
|
21945
|
+
}
|
|
21935
21946
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
|
21936
21947
|
success: false,
|
|
21937
21948
|
frag: frag,
|
|
@@ -21981,10 +21992,6 @@ class TimelineController {
|
|
|
21981
21992
|
frag
|
|
21982
21993
|
} = data;
|
|
21983
21994
|
if (frag.type === PlaylistLevelType.SUBTITLE) {
|
|
21984
|
-
if (!this.initPTS[frag.cc]) {
|
|
21985
|
-
this.unparsedVttFrags.push(data);
|
|
21986
|
-
return;
|
|
21987
|
-
}
|
|
21988
21995
|
this.onFragLoaded(Events.FRAG_LOADED, data);
|
|
21989
21996
|
}
|
|
21990
21997
|
}
|
|
@@ -24117,6 +24124,7 @@ class XhrLoader {
|
|
|
24117
24124
|
const stats = this.stats;
|
|
24118
24125
|
stats.loading.first = 0;
|
|
24119
24126
|
stats.loaded = 0;
|
|
24127
|
+
stats.aborted = false;
|
|
24120
24128
|
const xhrSetup = this.xhrSetup;
|
|
24121
24129
|
if (xhrSetup) {
|
|
24122
24130
|
Promise.resolve().then(() => {
|
|
@@ -24988,7 +24996,7 @@ class Hls {
|
|
|
24988
24996
|
* Get the video-dev/hls.js package version.
|
|
24989
24997
|
*/
|
|
24990
24998
|
static get version() {
|
|
24991
|
-
return "1.4.
|
|
24999
|
+
return "1.4.7";
|
|
24992
25000
|
}
|
|
24993
25001
|
|
|
24994
25002
|
/**
|