hls.js 1.6.3-0.canary.11253 → 1.6.3-0.canary.11255
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 +8 -4
- package/dist/hls.d.ts +8 -4
- package/dist/hls.js +220 -166
- package/dist/hls.js.d.ts +8 -4
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +72 -31
- 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 +69 -30
- 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 +127 -84
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +1 -1
- package/src/config.ts +2 -0
- package/src/controller/audio-stream-controller.ts +39 -31
- package/src/controller/base-stream-controller.ts +17 -6
- package/src/controller/eme-controller.ts +47 -19
- package/src/controller/fragment-finders.ts +18 -14
- package/src/controller/interstitials-controller.ts +1 -1
- package/src/loader/key-loader.ts +42 -17
package/dist/hls.mjs
CHANGED
@@ -523,7 +523,7 @@ function enableLogs(debugConfig, context, id) {
|
|
523
523
|
// Some browsers don't allow to use bind on console object anyway
|
524
524
|
// fallback to default if needed
|
525
525
|
try {
|
526
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.3-0.canary.
|
526
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.3-0.canary.11255"}`);
|
527
527
|
} catch (e) {
|
528
528
|
/* log fn threw an exception. All logger methods are no-ops. */
|
529
529
|
return createLogger();
|
@@ -4113,7 +4113,6 @@ function findFragmentByPDT(fragments, PDTValue, maxFragLookUpTolerance) {
|
|
4113
4113
|
if (PDTValue >= (endPDT || 0)) {
|
4114
4114
|
return null;
|
4115
4115
|
}
|
4116
|
-
maxFragLookUpTolerance = maxFragLookUpTolerance || 0;
|
4117
4116
|
for (let seg = 0; seg < fragments.length; ++seg) {
|
4118
4117
|
const frag = fragments[seg];
|
4119
4118
|
if (pdtWithinToleranceTest(PDTValue, maxFragLookUpTolerance, frag)) {
|
@@ -4224,40 +4223,34 @@ function pdtWithinToleranceTest(pdtBufferEnd, maxFragLookUpTolerance, candidate)
|
|
4224
4223
|
const endProgramDateTime = candidate.endProgramDateTime || 0;
|
4225
4224
|
return endProgramDateTime - candidateLookupTolerance > pdtBufferEnd;
|
4226
4225
|
}
|
4227
|
-
function
|
4228
|
-
return BinarySearch.search(fragments, candidate => {
|
4229
|
-
if (candidate.cc < cc) {
|
4230
|
-
return 1;
|
4231
|
-
} else if (candidate.cc > cc) {
|
4232
|
-
return -1;
|
4233
|
-
} else {
|
4234
|
-
return 0;
|
4235
|
-
}
|
4236
|
-
});
|
4237
|
-
}
|
4238
|
-
function findNearestWithCC(details, cc, fragment) {
|
4226
|
+
function findNearestWithCC(details, cc, pos) {
|
4239
4227
|
if (details) {
|
4240
4228
|
if (details.startCC <= cc && details.endCC >= cc) {
|
4241
|
-
const start = fragment.start;
|
4242
|
-
const end = fragment.end;
|
4243
4229
|
let fragments = details.fragments;
|
4244
|
-
|
4245
|
-
|
4246
|
-
|
4247
|
-
|
4248
|
-
|
4249
|
-
|
4230
|
+
const {
|
4231
|
+
fragmentHint
|
4232
|
+
} = details;
|
4233
|
+
if (fragmentHint) {
|
4234
|
+
fragments = fragments.concat(fragmentHint);
|
4235
|
+
}
|
4236
|
+
let closest;
|
4237
|
+
BinarySearch.search(fragments, candidate => {
|
4238
|
+
if (candidate.cc < cc) {
|
4239
|
+
return 1;
|
4250
4240
|
}
|
4251
|
-
|
4252
|
-
|
4253
|
-
|
4241
|
+
if (candidate.cc > cc) {
|
4242
|
+
return -1;
|
4243
|
+
}
|
4244
|
+
closest = candidate;
|
4245
|
+
if (candidate.end <= pos) {
|
4254
4246
|
return 1;
|
4255
|
-
}
|
4247
|
+
}
|
4248
|
+
if (candidate.start > pos) {
|
4256
4249
|
return -1;
|
4257
|
-
} else {
|
4258
|
-
return 0;
|
4259
4250
|
}
|
4251
|
+
return 0;
|
4260
4252
|
});
|
4253
|
+
return closest || null;
|
4261
4254
|
}
|
4262
4255
|
}
|
4263
4256
|
return null;
|
@@ -8908,8 +8901,11 @@ class BaseStreamController extends TaskLoop {
|
|
8908
8901
|
if (this.fragCurrent === null) {
|
8909
8902
|
keyLoadingPromise = Promise.reject(new Error(`frag load aborted, context changed in KEY_LOADING`));
|
8910
8903
|
}
|
8911
|
-
} else if (!frag.encrypted
|
8912
|
-
this.keyLoader.loadClear(frag, details.encryptedFragments);
|
8904
|
+
} else if (!frag.encrypted) {
|
8905
|
+
keyLoadingPromise = this.keyLoader.loadClear(frag, details.encryptedFragments);
|
8906
|
+
if (keyLoadingPromise) {
|
8907
|
+
this.log(`[eme] blocking frag load until media-keys acquired`);
|
8908
|
+
}
|
8913
8909
|
}
|
8914
8910
|
const fragPrevious = this.fragPrevious;
|
8915
8911
|
if (isMediaFragment(frag) && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
|
@@ -9264,7 +9260,7 @@ class BaseStreamController extends TaskLoop {
|
|
9264
9260
|
this.log(`LL-Part loading ON for initial live fragment`);
|
9265
9261
|
this.loadingParts = true;
|
9266
9262
|
}
|
9267
|
-
frag = this.getInitialLiveFragment(levelDetails
|
9263
|
+
frag = this.getInitialLiveFragment(levelDetails);
|
9268
9264
|
const mainStart = this.hls.startPosition;
|
9269
9265
|
const liveSyncPosition = this.hls.liveSyncPosition;
|
9270
9266
|
const startPosition = frag ? (mainStart !== -1 && mainStart >= start ? mainStart : liveSyncPosition) || frag.start : pos;
|
@@ -9404,7 +9400,8 @@ class BaseStreamController extends TaskLoop {
|
|
9404
9400
|
"sliding" of the playlist, which is its offset from the start of playback. After sliding we can compute the real
|
9405
9401
|
start and end times for each fragment in the playlist (after which this method will not need to be called).
|
9406
9402
|
*/
|
9407
|
-
getInitialLiveFragment(levelDetails
|
9403
|
+
getInitialLiveFragment(levelDetails) {
|
9404
|
+
const fragments = levelDetails.fragments;
|
9408
9405
|
const fragPrevious = this.fragPrevious;
|
9409
9406
|
let frag = null;
|
9410
9407
|
if (fragPrevious) {
|
@@ -9427,7 +9424,7 @@ class BaseStreamController extends TaskLoop {
|
|
9427
9424
|
// It's important to stay within the continuity range if available; otherwise the fragments in the playlist
|
9428
9425
|
// will have the wrong start times
|
9429
9426
|
if (!frag) {
|
9430
|
-
frag =
|
9427
|
+
frag = findNearestWithCC(levelDetails, fragPrevious.cc, fragPrevious.end);
|
9431
9428
|
if (frag) {
|
9432
9429
|
this.log(`Live playlist, switching playlist, load frag with same CC: ${frag.sn}`);
|
9433
9430
|
}
|
@@ -10237,7 +10234,7 @@ function requireEventemitter3 () {
|
|
10237
10234
|
var eventemitter3Exports = requireEventemitter3();
|
10238
10235
|
var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
|
10239
10236
|
|
10240
|
-
const version = "1.6.3-0.canary.
|
10237
|
+
const version = "1.6.3-0.canary.11255";
|
10241
10238
|
|
10242
10239
|
// ensure the worker ends up in the bundle
|
10243
10240
|
// If the worker should not be included this gets aliased to empty.js
|
@@ -16528,23 +16525,46 @@ class AudioStreamController extends BaseStreamController {
|
|
16528
16525
|
if (this.state === State.WAITING_INIT_PTS) {
|
16529
16526
|
const waitingData = this.waitingData;
|
16530
16527
|
if (!waitingData && !this.loadingParts || waitingData && waitingData.frag.cc !== cc) {
|
16531
|
-
this.
|
16528
|
+
this.syncWithAnchor(frag, waitingData == null ? void 0 : waitingData.frag);
|
16532
16529
|
}
|
16533
|
-
this.tick();
|
16534
16530
|
} else if (!this.hls.hasEnoughToStart && inFlightFrag && inFlightFrag.cc !== cc) {
|
16535
|
-
this.startFragRequested = false;
|
16536
|
-
this.nextLoadPosition = this.findSyncFrag(frag).start;
|
16537
16531
|
inFlightFrag.abortRequests();
|
16538
|
-
this.
|
16532
|
+
this.syncWithAnchor(frag, inFlightFrag);
|
16539
16533
|
} else if (this.state === State.IDLE) {
|
16540
16534
|
this.tick();
|
16541
16535
|
}
|
16542
16536
|
}
|
16543
16537
|
}
|
16544
|
-
|
16538
|
+
getLoadPosition() {
|
16539
|
+
if (!this.startFragRequested && this.nextLoadPosition >= 0) {
|
16540
|
+
return this.nextLoadPosition;
|
16541
|
+
}
|
16542
|
+
return super.getLoadPosition();
|
16543
|
+
}
|
16544
|
+
syncWithAnchor(mainAnchor, waitingToAppend) {
|
16545
|
+
var _this$mainFragLoading;
|
16546
|
+
// Drop waiting fragment if videoTrackCC has changed since waitingFragment was set and initPTS was not found
|
16547
|
+
const mainFragLoading = ((_this$mainFragLoading = this.mainFragLoading) == null ? void 0 : _this$mainFragLoading.frag) || null;
|
16548
|
+
if (waitingToAppend) {
|
16549
|
+
if ((mainFragLoading == null ? void 0 : mainFragLoading.cc) === waitingToAppend.cc) {
|
16550
|
+
// Wait for loading frag to complete and INIT_PTS_FOUND
|
16551
|
+
return;
|
16552
|
+
}
|
16553
|
+
}
|
16554
|
+
const targetDiscontinuity = (mainFragLoading || mainAnchor).cc;
|
16545
16555
|
const trackDetails = this.getLevelDetails();
|
16546
|
-
const
|
16547
|
-
|
16556
|
+
const pos = this.getLoadPosition();
|
16557
|
+
const syncFrag = findNearestWithCC(trackDetails, targetDiscontinuity, pos);
|
16558
|
+
// Only stop waiting for audioFrag.cc if an audio segment of the same discontinuity domain (cc) is found
|
16559
|
+
if (syncFrag) {
|
16560
|
+
this.log(`Waiting fragment cc (${waitingToAppend == null ? void 0 : waitingToAppend.cc}) cancelled because video is at cc ${mainAnchor.cc}`);
|
16561
|
+
this.startFragRequested = false;
|
16562
|
+
this.nextLoadPosition = syncFrag.start;
|
16563
|
+
this.resetLoadingState();
|
16564
|
+
if (this.state === State.IDLE) {
|
16565
|
+
this.doTickIdle();
|
16566
|
+
}
|
16567
|
+
}
|
16548
16568
|
}
|
16549
16569
|
startLoad(startPosition, skipSeekToStartPosition) {
|
16550
16570
|
if (!this.levels) {
|
@@ -16631,10 +16651,7 @@ class AudioStreamController extends BaseStreamController {
|
|
16631
16651
|
super._handleFragmentLoadComplete(data);
|
16632
16652
|
}
|
16633
16653
|
} else if (mainAnchor && mainAnchor.cc !== waitingData.frag.cc) {
|
16634
|
-
|
16635
|
-
this.log(`Waiting fragment cc (${frag.cc}) cancelled because video is at cc ${mainAnchor.cc}`);
|
16636
|
-
this.nextLoadPosition = this.findSyncFrag(mainAnchor).start;
|
16637
|
-
this.clearWaitingFragment();
|
16654
|
+
this.syncWithAnchor(mainAnchor, waitingData.frag);
|
16638
16655
|
}
|
16639
16656
|
} else {
|
16640
16657
|
this.state = State.IDLE;
|
@@ -16643,22 +16660,12 @@ class AudioStreamController extends BaseStreamController {
|
|
16643
16660
|
}
|
16644
16661
|
this.onTickEnd();
|
16645
16662
|
}
|
16646
|
-
|
16663
|
+
resetLoadingState() {
|
16647
16664
|
const waitingData = this.waitingData;
|
16648
16665
|
if (waitingData) {
|
16649
|
-
if (!this.hls.hasEnoughToStart) {
|
16650
|
-
// Load overlapping fragment on start when discontinuity start times are not aligned
|
16651
|
-
this.startFragRequested = false;
|
16652
|
-
}
|
16653
16666
|
this.fragmentTracker.removeFragment(waitingData.frag);
|
16654
16667
|
this.waitingData = null;
|
16655
|
-
if (this.state !== State.STOPPED) {
|
16656
|
-
this.state = State.IDLE;
|
16657
|
-
}
|
16658
16668
|
}
|
16659
|
-
}
|
16660
|
-
resetLoadingState() {
|
16661
|
-
this.clearWaitingFragment();
|
16662
16669
|
super.resetLoadingState();
|
16663
16670
|
}
|
16664
16671
|
onTickEnd() {
|
@@ -16672,7 +16679,7 @@ class AudioStreamController extends BaseStreamController {
|
|
16672
16679
|
this.lastCurrentTime = media.currentTime;
|
16673
16680
|
}
|
16674
16681
|
doTickIdle() {
|
16675
|
-
var _this$
|
16682
|
+
var _this$mainFragLoading2;
|
16676
16683
|
const {
|
16677
16684
|
hls,
|
16678
16685
|
levels,
|
@@ -16746,7 +16753,7 @@ class AudioStreamController extends BaseStreamController {
|
|
16746
16753
|
}
|
16747
16754
|
|
16748
16755
|
// Request audio segments up to one fragment ahead of main stream-controller
|
16749
|
-
let mainFragLoading = ((_this$
|
16756
|
+
let mainFragLoading = ((_this$mainFragLoading2 = this.mainFragLoading) == null ? void 0 : _this$mainFragLoading2.frag) || null;
|
16750
16757
|
if (!this.audioOnly && this.startFragRequested && mainFragLoading && isMediaFragment(frag) && !frag.endList && (!trackDetails.live || !this.loadingParts && targetBufferTime < this.hls.liveSyncPosition)) {
|
16751
16758
|
if (this.fragmentTracker.getState(mainFragLoading) === FragmentState.OK) {
|
16752
16759
|
this.mainFragLoading = mainFragLoading = null;
|
@@ -21828,6 +21835,7 @@ class EMEController extends Logger {
|
|
21828
21835
|
this.log(`Create media-keys for "${keySystem}"`);
|
21829
21836
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(mediaKeys => {
|
21830
21837
|
this.log(`Media-keys created for "${keySystem}"`);
|
21838
|
+
_keySystemAccessPromises.hasMediaKeys = true;
|
21831
21839
|
return certificateRequest.then(certificate => {
|
21832
21840
|
if (certificate) {
|
21833
21841
|
return this.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
@@ -21888,18 +21896,26 @@ class EMEController extends Logger {
|
|
21888
21896
|
} (data length: ${data ? data.byteLength : data})`);
|
21889
21897
|
return keySession.update(data);
|
21890
21898
|
}
|
21891
|
-
|
21892
|
-
|
21893
|
-
|
21894
|
-
|
21895
|
-
|
21896
|
-
|
21897
|
-
|
21899
|
+
getSelectedKeySystemFormats() {
|
21900
|
+
return Object.keys(this.keySystemAccessPromises).map(keySystem => ({
|
21901
|
+
keySystem,
|
21902
|
+
hasMediaKeys: this.keySystemAccessPromises[keySystem].hasMediaKeys
|
21903
|
+
})).filter(({
|
21904
|
+
hasMediaKeys
|
21905
|
+
}) => !!hasMediaKeys).map(({
|
21906
|
+
keySystem
|
21907
|
+
}) => keySystemDomainToKeySystemFormat(keySystem)).filter(keySystem => !!keySystem);
|
21908
|
+
}
|
21909
|
+
getKeySystemAccess(keySystemsToAttempt) {
|
21910
|
+
return this.getKeySystemSelectionPromise(keySystemsToAttempt).then(({
|
21911
|
+
keySystem,
|
21912
|
+
mediaKeys
|
21913
|
+
}) => {
|
21914
|
+
return this.attemptSetMediaKeys(keySystem, mediaKeys);
|
21915
|
+
});
|
21898
21916
|
}
|
21899
|
-
|
21917
|
+
selectKeySystem(keySystemsToAttempt) {
|
21900
21918
|
return new Promise((resolve, reject) => {
|
21901
|
-
const keySystemsInConfig = getKeySystemsForConfig(this.config);
|
21902
|
-
const keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(value => !!value && keySystemsInConfig.indexOf(value) !== -1);
|
21903
21919
|
return this.getKeySystemSelectionPromise(keySystemsToAttempt).then(({
|
21904
21920
|
keySystem
|
21905
21921
|
}) => {
|
@@ -21912,6 +21928,19 @@ class EMEController extends Logger {
|
|
21912
21928
|
}).catch(reject);
|
21913
21929
|
});
|
21914
21930
|
}
|
21931
|
+
selectKeySystemFormat(frag) {
|
21932
|
+
const keyFormats = Object.keys(frag.levelkeys || {});
|
21933
|
+
if (!this.keyFormatPromise) {
|
21934
|
+
this.log(`Selecting key-system from fragment (sn: ${frag.sn} ${frag.type}: ${frag.level}) key formats ${keyFormats.join(', ')}`);
|
21935
|
+
this.keyFormatPromise = this.getKeyFormatPromise(keyFormats);
|
21936
|
+
}
|
21937
|
+
return this.keyFormatPromise;
|
21938
|
+
}
|
21939
|
+
getKeyFormatPromise(keyFormats) {
|
21940
|
+
const keySystemsInConfig = getKeySystemsForConfig(this.config);
|
21941
|
+
const keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(value => !!value && keySystemsInConfig.indexOf(value) !== -1);
|
21942
|
+
return this.selectKeySystem(keySystemsToAttempt);
|
21943
|
+
}
|
21915
21944
|
loadKey(data) {
|
21916
21945
|
const decryptdata = data.keyInfo.decryptdata;
|
21917
21946
|
const keyId = this.getKeyIdString(decryptdata);
|
@@ -26061,8 +26090,7 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
|
|
26061
26090
|
var _this$schedule$items4, _this$detachedData5;
|
26062
26091
|
const {
|
26063
26092
|
interstitial,
|
26064
|
-
assetItem
|
26065
|
-
assetId
|
26093
|
+
assetItem
|
26066
26094
|
} = player;
|
26067
26095
|
const scheduleIndex = this.schedule.findEventIndex(interstitial.identifier);
|
26068
26096
|
const item = (_this$schedule$items4 = this.schedule.items) == null ? void 0 : _this$schedule$items4[scheduleIndex];
|
@@ -30293,6 +30321,8 @@ const hlsDefaultConfig = _objectSpread2(_objectSpread2({
|
|
30293
30321
|
// used by eme-controller
|
30294
30322
|
requestMediaKeySystemAccessFunc: requestMediaKeySystemAccess ,
|
30295
30323
|
// used by eme-controller
|
30324
|
+
requireKeySystemAccessOnStart: false,
|
30325
|
+
// used by eme-controller
|
30296
30326
|
testBandwidth: true,
|
30297
30327
|
progressive: false,
|
30298
30328
|
lowLatencyMode: true,
|
@@ -33683,22 +33713,35 @@ class KeyLoader {
|
|
33683
33713
|
});
|
33684
33714
|
}
|
33685
33715
|
loadClear(loadingFrag, encryptedFragments) {
|
33686
|
-
if (this.emeController && this.config.emeEnabled) {
|
33687
|
-
// access key-system with nearest key on start (
|
33688
|
-
|
33689
|
-
|
33690
|
-
|
33691
|
-
|
33692
|
-
|
33693
|
-
|
33694
|
-
|
33695
|
-
|
33696
|
-
frag.
|
33697
|
-
|
33698
|
-
|
33716
|
+
if (this.emeController && this.config.emeEnabled && !this.emeController.getSelectedKeySystemFormats().length) {
|
33717
|
+
// access key-system with nearest key on start (loading frag is unencrypted)
|
33718
|
+
if (encryptedFragments.length) {
|
33719
|
+
const {
|
33720
|
+
sn,
|
33721
|
+
cc
|
33722
|
+
} = loadingFrag;
|
33723
|
+
for (let i = 0; i < encryptedFragments.length; i++) {
|
33724
|
+
const frag = encryptedFragments[i];
|
33725
|
+
if (cc <= frag.cc && (sn === 'initSegment' || frag.sn === 'initSegment' || sn < frag.sn)) {
|
33726
|
+
return this.emeController.selectKeySystemFormat(frag).then(keySystemFormat => {
|
33727
|
+
frag.setKeyFormat(keySystemFormat);
|
33728
|
+
if (this.emeController && this.config.requireKeySystemAccessOnStart) {
|
33729
|
+
const keySystem = keySystemFormatToKeySystemDomain(keySystemFormat);
|
33730
|
+
if (keySystem) {
|
33731
|
+
return this.emeController.getKeySystemAccess([keySystem]);
|
33732
|
+
}
|
33733
|
+
}
|
33734
|
+
});
|
33735
|
+
}
|
33736
|
+
}
|
33737
|
+
} else if (this.config.requireKeySystemAccessOnStart) {
|
33738
|
+
const keySystemsInConfig = getKeySystemsForConfig(this.config);
|
33739
|
+
if (keySystemsInConfig.length) {
|
33740
|
+
return this.emeController.getKeySystemAccess(keySystemsInConfig);
|
33699
33741
|
}
|
33700
33742
|
}
|
33701
33743
|
}
|
33744
|
+
return null;
|
33702
33745
|
}
|
33703
33746
|
load(frag) {
|
33704
33747
|
if (!frag.decryptdata && frag.encrypted && this.emeController && this.config.emeEnabled) {
|