hls.js 1.5.5-0.canary.9984 → 1.5.5-0.canary.9986
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 +75 -8
- package/dist/hls.js.d.ts +2 -0
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +75 -8
- 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 +75 -8
- 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 +75 -8
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +1 -1
- package/src/controller/base-playlist-controller.ts +13 -1
- package/src/controller/base-stream-controller.ts +93 -4
- package/src/controller/level-controller.ts +7 -1
package/dist/hls.mjs
CHANGED
@@ -512,7 +512,7 @@ function enableLogs(debugConfig, context, id) {
|
|
512
512
|
// Some browsers don't allow to use bind on console object anyway
|
513
513
|
// fallback to default if needed
|
514
514
|
try {
|
515
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.5-0.canary.
|
515
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.5-0.canary.9986"}`);
|
516
516
|
} catch (e) {
|
517
517
|
/* log fn threw an exception. All logger methods are no-ops. */
|
518
518
|
return createLogger();
|
@@ -6197,7 +6197,12 @@ class BasePlaylistController extends Logger {
|
|
6197
6197
|
const cdnAge = lastAdvanced + details.ageHeader;
|
6198
6198
|
let currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5);
|
6199
6199
|
if (currentGoal > 0) {
|
6200
|
-
if (
|
6200
|
+
if (cdnAge > details.targetduration * 3) {
|
6201
|
+
// Omit segment and part directives when the last response was more than 3 target durations ago,
|
6202
|
+
this.log(`Playlist last advanced ${lastAdvanced.toFixed(2)}s ago. Omitting segment and part directives.`);
|
6203
|
+
msn = undefined;
|
6204
|
+
part = undefined;
|
6205
|
+
} else if (previousDetails != null && previousDetails.tuneInGoal && cdnAge - details.partTarget > previousDetails.tuneInGoal) {
|
6201
6206
|
// If we attempted to get the next or latest playlist update, but currentGoal increased,
|
6202
6207
|
// then we either can't catchup, or the "age" header cannot be trusted.
|
6203
6208
|
this.warn(`CDN Tune-in goal increased from: ${previousDetails.tuneInGoal} to: ${currentGoal} with playlist age: ${details.age}`);
|
@@ -9182,6 +9187,7 @@ class BaseStreamController extends TaskLoop {
|
|
9182
9187
|
this.decrypter = void 0;
|
9183
9188
|
this.initPTS = [];
|
9184
9189
|
this.buffering = true;
|
9190
|
+
this.loadingParts = false;
|
9185
9191
|
this.onMediaSeeking = () => {
|
9186
9192
|
const {
|
9187
9193
|
config,
|
@@ -9218,6 +9224,14 @@ class BaseStreamController extends TaskLoop {
|
|
9218
9224
|
// Remove gap fragments
|
9219
9225
|
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
9220
9226
|
this.lastCurrentTime = currentTime;
|
9227
|
+
if (!this.loadingParts) {
|
9228
|
+
const bufferEnd = Math.max(bufferInfo.end, currentTime);
|
9229
|
+
const shouldLoadParts = this.shouldLoadParts(this.getLevelDetails(), bufferEnd);
|
9230
|
+
if (shouldLoadParts) {
|
9231
|
+
this.log(`LL-Part loading ON after seeking to ${currentTime.toFixed(2)} with buffer @${bufferEnd.toFixed(2)}`);
|
9232
|
+
this.loadingParts = shouldLoadParts;
|
9233
|
+
}
|
9234
|
+
}
|
9221
9235
|
}
|
9222
9236
|
|
9223
9237
|
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
@@ -9628,8 +9642,16 @@ class BaseStreamController extends TaskLoop {
|
|
9628
9642
|
} else if (!frag.encrypted && details.encryptedFragments.length) {
|
9629
9643
|
this.keyLoader.loadClear(frag, details.encryptedFragments);
|
9630
9644
|
}
|
9645
|
+
const fragPrevious = this.fragPrevious;
|
9646
|
+
if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
|
9647
|
+
const shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
|
9648
|
+
if (shouldLoadParts !== this.loadingParts) {
|
9649
|
+
this.log(`LL-Part loading ${shouldLoadParts ? 'ON' : 'OFF'} loading sn ${fragPrevious == null ? void 0 : fragPrevious.sn}->${frag.sn}`);
|
9650
|
+
this.loadingParts = shouldLoadParts;
|
9651
|
+
}
|
9652
|
+
}
|
9631
9653
|
targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
|
9632
|
-
if (this.
|
9654
|
+
if (this.loadingParts && frag.sn !== 'initSegment') {
|
9633
9655
|
const partList = details.partList;
|
9634
9656
|
if (partList && progressCallback) {
|
9635
9657
|
if (targetBufferTime > frag.end && details.fragmentHint) {
|
@@ -9667,6 +9689,13 @@ class BaseStreamController extends TaskLoop {
|
|
9667
9689
|
}
|
9668
9690
|
}
|
9669
9691
|
}
|
9692
|
+
if (frag.sn !== 'initSegment' && this.loadingParts) {
|
9693
|
+
this.log(`LL-Part loading OFF after next part miss @${targetBufferTime.toFixed(2)}`);
|
9694
|
+
this.loadingParts = false;
|
9695
|
+
} else if (!frag.url) {
|
9696
|
+
// Selected fragment hint for part but not loading parts
|
9697
|
+
return Promise.resolve(null);
|
9698
|
+
}
|
9670
9699
|
this.log(`Loading fragment ${frag.sn} cc: ${frag.cc} ${details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : ''}${this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'}: ${frag.level}, target: ${parseFloat(targetBufferTime.toFixed(3))}`);
|
9671
9700
|
// Don't update nextLoadPosition for fragments which are not buffered
|
9672
9701
|
if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
|
@@ -9765,8 +9794,36 @@ class BaseStreamController extends TaskLoop {
|
|
9765
9794
|
if (part) {
|
9766
9795
|
part.stats.parsing.end = now;
|
9767
9796
|
}
|
9797
|
+
// See if part loading should be disabled/enabled based on buffer and playback position.
|
9798
|
+
if (frag.sn !== 'initSegment') {
|
9799
|
+
const levelDetails = this.getLevelDetails();
|
9800
|
+
const loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
|
9801
|
+
const shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
|
9802
|
+
if (shouldLoadParts !== this.loadingParts) {
|
9803
|
+
this.log(`LL-Part loading ${shouldLoadParts ? 'ON' : 'OFF'} after parsing segment ending @${frag.end.toFixed(2)}`);
|
9804
|
+
this.loadingParts = shouldLoadParts;
|
9805
|
+
}
|
9806
|
+
}
|
9768
9807
|
this.updateLevelTiming(frag, part, level, chunkMeta.partial);
|
9769
9808
|
}
|
9809
|
+
shouldLoadParts(details, bufferEnd) {
|
9810
|
+
if (this.config.lowLatencyMode) {
|
9811
|
+
if (!details) {
|
9812
|
+
return this.loadingParts;
|
9813
|
+
}
|
9814
|
+
if (details != null && details.partList) {
|
9815
|
+
var _details$fragmentHint;
|
9816
|
+
// Buffer must be ahead of first part + duration of parts after last segment
|
9817
|
+
// and playback must be at or past segment adjacent to part list
|
9818
|
+
const firstPart = details.partList[0];
|
9819
|
+
const safePartStart = firstPart.end + (((_details$fragmentHint = details.fragmentHint) == null ? void 0 : _details$fragmentHint.duration) || 0);
|
9820
|
+
if (bufferEnd >= safePartStart && this.lastCurrentTime > firstPart.start - firstPart.fragment.duration) {
|
9821
|
+
return true;
|
9822
|
+
}
|
9823
|
+
}
|
9824
|
+
}
|
9825
|
+
return false;
|
9826
|
+
}
|
9770
9827
|
getCurrentContext(chunkMeta) {
|
9771
9828
|
const {
|
9772
9829
|
levels,
|
@@ -9915,7 +9972,8 @@ class BaseStreamController extends TaskLoop {
|
|
9915
9972
|
config
|
9916
9973
|
} = this;
|
9917
9974
|
const start = fragments[0].start;
|
9918
|
-
|
9975
|
+
const canLoadParts = config.lowLatencyMode && !!levelDetails.partList;
|
9976
|
+
let frag = null;
|
9919
9977
|
if (levelDetails.live) {
|
9920
9978
|
const initialLiveManifestSize = config.initialLiveManifestSize;
|
9921
9979
|
if (fragLen < initialLiveManifestSize) {
|
@@ -9927,6 +9985,10 @@ class BaseStreamController extends TaskLoop {
|
|
9927
9985
|
// Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that
|
9928
9986
|
// we get the fragment matching that start time
|
9929
9987
|
if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1 || pos < start) {
|
9988
|
+
if (canLoadParts && !this.loadingParts) {
|
9989
|
+
this.log(`LL-Part loading ON for initial live fragment`);
|
9990
|
+
this.loadingParts = true;
|
9991
|
+
}
|
9930
9992
|
frag = this.getInitialLiveFragment(levelDetails, fragments);
|
9931
9993
|
this.startPosition = this.nextLoadPosition = frag ? this.hls.liveSyncPosition || frag.start : pos;
|
9932
9994
|
}
|
@@ -9937,7 +9999,7 @@ class BaseStreamController extends TaskLoop {
|
|
9937
9999
|
|
9938
10000
|
// If we haven't run into any special cases already, just load the fragment most closely matching the requested position
|
9939
10001
|
if (!frag) {
|
9940
|
-
const end =
|
10002
|
+
const end = this.loadingParts ? levelDetails.partEnd : levelDetails.fragmentEnd;
|
9941
10003
|
frag = this.getFragmentAtPosition(pos, end, levelDetails);
|
9942
10004
|
}
|
9943
10005
|
return this.mapToInitFragWhenRequired(frag);
|
@@ -10059,7 +10121,7 @@ class BaseStreamController extends TaskLoop {
|
|
10059
10121
|
} = levelDetails;
|
10060
10122
|
const tolerance = config.maxFragLookUpTolerance;
|
10061
10123
|
const partList = levelDetails.partList;
|
10062
|
-
const loadingParts = !!(
|
10124
|
+
const loadingParts = !!(this.loadingParts && partList != null && partList.length && fragmentHint);
|
10063
10125
|
if (loadingParts && fragmentHint && !this.bitrateTest) {
|
10064
10126
|
// Include incomplete fragment with parts at end
|
10065
10127
|
fragments = fragments.concat(fragmentHint);
|
@@ -26658,7 +26720,12 @@ class LevelController extends BasePlaylistController {
|
|
26658
26720
|
if (curLevel.fragmentError === 0) {
|
26659
26721
|
curLevel.loadError = 0;
|
26660
26722
|
}
|
26661
|
-
|
26723
|
+
// Ignore matching details populated by loading a Media Playlist directly
|
26724
|
+
let previousDetails = curLevel.details;
|
26725
|
+
if (previousDetails === data.details && previousDetails.advanced) {
|
26726
|
+
previousDetails = undefined;
|
26727
|
+
}
|
26728
|
+
this.playlistLoaded(level, data, previousDetails);
|
26662
26729
|
} else if ((_data$deliveryDirecti2 = data.deliveryDirectives) != null && _data$deliveryDirecti2.skip) {
|
26663
26730
|
// received a delta playlist update that cannot be merged
|
26664
26731
|
details.deltaUpdateFailed = true;
|
@@ -28527,7 +28594,7 @@ class Hls {
|
|
28527
28594
|
* Get the video-dev/hls.js package version.
|
28528
28595
|
*/
|
28529
28596
|
static get version() {
|
28530
|
-
return "1.5.5-0.canary.
|
28597
|
+
return "1.5.5-0.canary.9986";
|
28531
28598
|
}
|
28532
28599
|
|
28533
28600
|
/**
|