hls.js 1.6.0-beta.2.0.canary.10941 → 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.
@@ -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
- private getFwdBufferInfoAtPos(
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 (partial) {
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.media;
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.config.timelineOffset || 0;
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
- if (!this.playbackStarted || !playingItem) {
616
+ const items = this.schedule?.items;
617
+ if (!this.playbackStarted || !playingItem || !items) {
617
618
  return false;
618
619
  }
619
- const items = this.schedule?.items;
620
- return this.itemsMatch(playingItem, items ? items[items.length - 1] : null);
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: false,
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.setBufferingItem(playingItem);
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.nextEvent?.identifier === b.nextEvent?.identifier))
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
- bufferingItem &&
1652
- bufferEnd >= bufferingItem.end
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
- return !Object.keys(mediaSelection).some((playlistType) => {
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
- this.log(
600
- `"${interstitial.identifier}" resumption ${resumeTime} past ${playlistType} playlist end ${playlistEnd}`,
601
- );
602
- return true;
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
- this.log(`Media seeked to ${(currentTime as number).toFixed(3)}`);
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
- const bufferInfo = this.getMainFwdBufferInfo();
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
  );