hls.js 1.6.0-beta.2.0.canary.10939 → 1.6.0-beta.2.0.canary.10942
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 -1
- package/dist/hls.d.ts +1 -1
- package/dist/hls.js +68 -45
- package/dist/hls.js.d.ts +1 -1
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +15 -10
- 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 +15 -10
- 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 +68 -45
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +2 -2
- package/src/controller/audio-stream-controller.ts +22 -19
- package/src/controller/base-stream-controller.ts +15 -1
- package/src/controller/gap-controller.ts +5 -2
- package/src/controller/interstitial-player.ts +2 -2
- package/src/controller/interstitials-controller.ts +14 -14
- package/src/controller/interstitials-schedule.ts +11 -5
- package/src/controller/stream-controller.ts +14 -4
@@ -488,6 +488,20 @@ export default class BaseStreamController
|
|
488
488
|
}
|
489
489
|
}
|
490
490
|
}
|
491
|
+
// Skip loading of fragments that overlap completely with appendInPlace interstitals
|
492
|
+
const playerQueue = interstitials?.playerQueue;
|
493
|
+
if (playerQueue) {
|
494
|
+
for (let i = playerQueue.length; i--; ) {
|
495
|
+
const interstitial = playerQueue[i].interstitial;
|
496
|
+
if (
|
497
|
+
interstitial.appendInPlace &&
|
498
|
+
frag.start >= interstitial.startTime &&
|
499
|
+
frag.end <= interstitial.resumeTime
|
500
|
+
) {
|
501
|
+
return;
|
502
|
+
}
|
503
|
+
}
|
504
|
+
}
|
491
505
|
}
|
492
506
|
this.startFragRequested = true;
|
493
507
|
this._loadFragForPlayback(frag, level, targetBufferTime);
|
@@ -1201,7 +1215,7 @@ export default class BaseStreamController
|
|
1201
1215
|
return this.getFwdBufferInfoAtPos(bufferable, pos, type, maxBufferHole);
|
1202
1216
|
}
|
1203
1217
|
|
1204
|
-
|
1218
|
+
protected getFwdBufferInfoAtPos(
|
1205
1219
|
bufferable: Bufferable | null,
|
1206
1220
|
pos: number,
|
1207
1221
|
type: PlaylistLevelType,
|
@@ -436,9 +436,12 @@ export default class GapController extends TaskLoop {
|
|
436
436
|
}
|
437
437
|
|
438
438
|
const currentTime = media.currentTime;
|
439
|
-
|
439
|
+
const levelDetails = this.hls?.latestLevelDetails;
|
440
440
|
const partial = fragmentTracker.getPartialFragment(currentTime);
|
441
|
-
if (
|
441
|
+
if (
|
442
|
+
partial ||
|
443
|
+
(levelDetails?.live && currentTime < levelDetails.fragmentStart)
|
444
|
+
) {
|
442
445
|
// Try to skip over the buffer hole caused by a partial fragment
|
443
446
|
// This method isn't limited by the size of the gap between buffered ranges
|
444
447
|
const targetTime = this._trySkipBufferHole(partial);
|
@@ -77,7 +77,7 @@ export class HlsAssetPlayer {
|
|
77
77
|
}
|
78
78
|
|
79
79
|
get media(): HTMLMediaElement | null {
|
80
|
-
return this.hls
|
80
|
+
return this.hls?.media || null;
|
81
81
|
}
|
82
82
|
|
83
83
|
get bufferedEnd(): number {
|
@@ -114,7 +114,7 @@ export class HlsAssetPlayer {
|
|
114
114
|
}
|
115
115
|
|
116
116
|
get timelineOffset(): number {
|
117
|
-
return this.hls
|
117
|
+
return this.hls?.config.timelineOffset || 0;
|
118
118
|
}
|
119
119
|
|
120
120
|
set timelineOffset(value: number) {
|
@@ -613,11 +613,12 @@ export default class InterstitialsController
|
|
613
613
|
// Schedule getters
|
614
614
|
private get playingLastItem(): boolean {
|
615
615
|
const playingItem = this.playingItem;
|
616
|
-
|
616
|
+
const items = this.schedule?.items;
|
617
|
+
if (!this.playbackStarted || !playingItem || !items) {
|
617
618
|
return false;
|
618
619
|
}
|
619
|
-
|
620
|
-
return this.
|
620
|
+
|
621
|
+
return this.findItemIndex(playingItem) === items.length - 1;
|
621
622
|
}
|
622
623
|
|
623
624
|
private get playbackStarted(): boolean {
|
@@ -677,6 +678,7 @@ export default class InterstitialsController
|
|
677
678
|
const appendInPlace = player.interstitial.appendInPlace;
|
678
679
|
const playerMedia = player.media;
|
679
680
|
if (appendInPlace && playerMedia === this.primaryMedia) {
|
681
|
+
this.bufferingAsset = null;
|
680
682
|
if (
|
681
683
|
!toSegment ||
|
682
684
|
(this.isInterstitial(toSegment) && !toSegment.event.appendInPlace)
|
@@ -685,14 +687,13 @@ export default class InterstitialsController
|
|
685
687
|
// no-op when toSegment is undefined
|
686
688
|
if (toSegment && playerMedia) {
|
687
689
|
this.detachedData = { media: playerMedia };
|
690
|
+
return;
|
688
691
|
}
|
689
|
-
return;
|
690
692
|
}
|
691
693
|
const attachMediaSourceData = player.transferMedia();
|
692
694
|
this.log(
|
693
695
|
`transfer MediaSource from ${player} ${JSON.stringify(attachMediaSourceData)}`,
|
694
696
|
);
|
695
|
-
this.bufferingAsset = null;
|
696
697
|
this.detachedData = attachMediaSourceData;
|
697
698
|
} else if (toSegment && playerMedia) {
|
698
699
|
this.shouldPlay ||= !playerMedia.paused;
|
@@ -760,7 +761,7 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
760
761
|
dataToAttach.overrides = {
|
761
762
|
duration: this.schedule.duration,
|
762
763
|
endOfStream: !isAssetPlayer || isAssetAtEndOfSchedule,
|
763
|
-
cueRemoval:
|
764
|
+
cueRemoval: !isAssetPlayer,
|
764
765
|
};
|
765
766
|
}
|
766
767
|
player.attachMedia(dataToAttach);
|
@@ -1417,7 +1418,7 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1417
1418
|
) {
|
1418
1419
|
const timelinePos = this.timelinePos;
|
1419
1420
|
this.bufferedPos = timelinePos;
|
1420
|
-
this.
|
1421
|
+
this.checkBuffer();
|
1421
1422
|
}
|
1422
1423
|
}
|
1423
1424
|
|
@@ -1582,7 +1583,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
1582
1583
|
(a.event && b.event && this.eventItemsMatch(a, b)) ||
|
1583
1584
|
(!a.event &&
|
1584
1585
|
!b.event &&
|
1585
|
-
a
|
1586
|
+
this.findItemIndex(a) === this.findItemIndex(b)))
|
1586
1587
|
);
|
1587
1588
|
}
|
1588
1589
|
|
@@ -1647,9 +1648,11 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
1647
1648
|
const nextToBufferIndex = Math.min(bufferingIndex + 1, items.length - 1);
|
1648
1649
|
const nextItemToBuffer = items[nextToBufferIndex];
|
1649
1650
|
if (
|
1650
|
-
bufferEndIndex === -1 &&
|
1651
|
-
|
1652
|
-
|
1651
|
+
(bufferEndIndex === -1 &&
|
1652
|
+
bufferingItem &&
|
1653
|
+
bufferEnd >= bufferingItem.end) ||
|
1654
|
+
(nextItemToBuffer.event?.appendInPlace &&
|
1655
|
+
bufferEnd + 0.01 >= nextItemToBuffer.start)
|
1653
1656
|
) {
|
1654
1657
|
bufferEndIndex = nextToBufferIndex;
|
1655
1658
|
}
|
@@ -2136,9 +2139,6 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
2136
2139
|
assetId: InterstitialAssetId,
|
2137
2140
|
toSegment: InterstitialScheduleItem | null,
|
2138
2141
|
) {
|
2139
|
-
if (toSegment === null) {
|
2140
|
-
return;
|
2141
|
-
}
|
2142
2142
|
const playerIndex = this.getAssetPlayerQueueIndex(assetId);
|
2143
2143
|
if (playerIndex !== -1) {
|
2144
2144
|
this.log(
|
@@ -132,6 +132,8 @@ export class InterstitialsSchedule extends Logger {
|
|
132
132
|
}
|
133
133
|
// Only return index of a Primary Item
|
134
134
|
while (index >= 0 && items[index]?.event) {
|
135
|
+
// If index found is an interstitial it is not a valid result as it should have been matched up top
|
136
|
+
// decrement until result is negative (not found) or a primary segment
|
135
137
|
index--;
|
136
138
|
}
|
137
139
|
}
|
@@ -592,14 +594,18 @@ export class InterstitialsSchedule extends Logger {
|
|
592
594
|
);
|
593
595
|
return false;
|
594
596
|
}
|
595
|
-
|
597
|
+
const playlists = Object.keys(mediaSelection);
|
598
|
+
return !playlists.some((playlistType) => {
|
596
599
|
const details = mediaSelection[playlistType].details;
|
597
600
|
const playlistEnd = details.edge;
|
598
601
|
if (resumeTime > playlistEnd) {
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
602
|
+
if (playlists.length > 1) {
|
603
|
+
this.log(
|
604
|
+
`"${interstitial.identifier}" resumption ${resumeTime} past ${playlistType} playlist end ${playlistEnd}`,
|
605
|
+
);
|
606
|
+
return true;
|
607
|
+
}
|
608
|
+
return false;
|
603
609
|
}
|
604
610
|
const startFragment = findFragmentByPTS(
|
605
611
|
null,
|
@@ -573,15 +573,25 @@ export default class StreamController
|
|
573
573
|
private onMediaSeeked = () => {
|
574
574
|
const media = this.media;
|
575
575
|
const currentTime = media ? media.currentTime : null;
|
576
|
-
if (Number.isFinite(currentTime)) {
|
577
|
-
|
576
|
+
if (currentTime === null || !Number.isFinite(currentTime)) {
|
577
|
+
return;
|
578
578
|
}
|
579
579
|
|
580
|
+
this.log(`Media seeked to ${currentTime.toFixed(3)}`);
|
581
|
+
|
580
582
|
// If seeked was issued before buffer was appended do not tick immediately
|
581
|
-
|
583
|
+
if (!this.getBufferedFrag(currentTime)) {
|
584
|
+
return;
|
585
|
+
}
|
586
|
+
const bufferInfo = this.getFwdBufferInfoAtPos(
|
587
|
+
media,
|
588
|
+
currentTime,
|
589
|
+
PlaylistLevelType.MAIN,
|
590
|
+
0,
|
591
|
+
);
|
582
592
|
if (bufferInfo === null || bufferInfo.len === 0) {
|
583
593
|
this.warn(
|
584
|
-
`Main forward buffer length on "seeked" event ${
|
594
|
+
`Main forward buffer length at ${currentTime} on "seeked" event ${
|
585
595
|
bufferInfo ? bufferInfo.len : 'empty'
|
586
596
|
})`,
|
587
597
|
);
|