hls.js 1.6.0-beta.3.0.canary.10986 → 1.6.0-beta.3.0.canary.10989

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.
@@ -396,8 +396,9 @@ export default class InterstitialsController
396
396
  const playingItem = c.effectivePlayingItem;
397
397
  const targetIndex = c.schedule.findItemIndexAtTime(time, timelineType);
398
398
  const targetItem = c.schedule.items?.[targetIndex];
399
- const playingInterstitial = playingItem?.event;
400
- const appendInPlace = playingInterstitial?.appendInPlace;
399
+ const bufferingPlayer = c.getBufferingPlayer();
400
+ const bufferingInterstitial = bufferingPlayer?.interstitial;
401
+ const appendInPlace = bufferingInterstitial?.appendInPlace;
401
402
  const seekInItem = playingItem && c.itemsMatch(playingItem, targetItem);
402
403
  if (playingItem && (appendInPlace || seekInItem)) {
403
404
  // seek in asset player or primary media (appendInPlace)
@@ -438,10 +439,12 @@ export default class InterstitialsController
438
439
  }
439
440
  const targetIsPrimary = !c.isInterstitial(targetItem);
440
441
  if (
441
- !c.isInterstitial(playingItem) &&
442
+ (!c.isInterstitial(playingItem) ||
443
+ playingItem.event.appendInPlace) &&
442
444
  (targetIsPrimary || targetItem.event.appendInPlace)
443
445
  ) {
444
- const media = c.hls.media;
446
+ const media =
447
+ c.media || (appendInPlace ? bufferingPlayer?.media : null);
445
448
  if (media) {
446
449
  media.currentTime = seekToTime;
447
450
  }
@@ -462,6 +465,7 @@ export default class InterstitialsController
462
465
  let assetIndex = 0;
463
466
  if (targetIsPrimary) {
464
467
  c.timelinePos = seekToTime;
468
+ c.checkBuffer();
465
469
  } else {
466
470
  const assetList = targetItem?.event?.assetList;
467
471
  if (assetList) {
@@ -840,13 +844,23 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
840
844
  const backwardSeek = diff <= -0.01;
841
845
  this.timelinePos = currentTime;
842
846
  this.bufferedPos = currentTime;
843
- this.checkBuffer();
844
847
 
845
848
  // Check if seeking out of an item
846
849
  const playingItem = this.playingItem;
847
850
  if (!playingItem) {
851
+ this.checkBuffer();
848
852
  return;
849
853
  }
854
+ if (backwardSeek) {
855
+ const resetCount = this.schedule.resetErrorsInRange(
856
+ currentTime,
857
+ currentTime - diff,
858
+ );
859
+ if (resetCount) {
860
+ this.updateSchedule();
861
+ }
862
+ }
863
+ this.checkBuffer();
850
864
  if (
851
865
  (backwardSeek && currentTime < playingItem.start) ||
852
866
  currentTime >= playingItem.end
@@ -909,10 +923,10 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
909
923
  // Only allow timeupdate to advance primary position, seeking is used for jumping back
910
924
  // this prevents primaryPos from being reset to 0 after re-attach
911
925
  if (currentTime > this.timelinePos) {
926
+ this.timelinePos = currentTime;
912
927
  if (currentTime > this.bufferedPos) {
913
928
  this.checkBuffer();
914
929
  }
915
- this.timelinePos = currentTime;
916
930
  } else {
917
931
  return;
918
932
  }
@@ -996,6 +1010,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
996
1010
  const resumptionTime = interstitial.resumeTime;
997
1011
  if (this.timelinePos < resumptionTime) {
998
1012
  this.timelinePos = resumptionTime;
1013
+ this.checkBuffer();
999
1014
  }
1000
1015
  this.setSchedulePosition(nextIndex);
1001
1016
  }
@@ -1070,7 +1085,6 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
1070
1085
  scheduleIndex: index,
1071
1086
  });
1072
1087
  // Exiting an Interstitial
1073
- this.clearInterstitial(interstitial, scheduledItem);
1074
1088
  if (interstitial.cue.once) {
1075
1089
  // Remove interstitial with CUE attribute value of ONCE after it has played
1076
1090
  this.updateSchedule();
@@ -1328,7 +1342,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
1328
1342
  if (item) {
1329
1343
  this.setBufferingItem(item);
1330
1344
  } else {
1331
- this.bufferingItem = null;
1345
+ this.bufferingItem = this.playingItem;
1332
1346
  }
1333
1347
  this.bufferingAsset = null;
1334
1348
 
@@ -1591,7 +1605,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
1591
1605
  this.bufferingItem = updatedBufferingItem;
1592
1606
  } else if (bufferingItem.event) {
1593
1607
  // Interstitial removed from schedule (Live -> VOD or other scenario where Start Date is outside the range of VOD Playlist)
1594
- this.bufferingItem = null;
1608
+ this.bufferingItem = this.playingItem;
1595
1609
  this.clearInterstitial(bufferingItem.event, null);
1596
1610
  }
1597
1611
  }
@@ -1780,7 +1794,10 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
1780
1794
  (bufferingLast ? ` (${timeRemaining.toFixed(2)} remaining)` : ''),
1781
1795
  );
1782
1796
  this.bufferingItem = item;
1783
- this.bufferedPos = item.start;
1797
+ this.bufferedPos = Math.max(
1798
+ item.start,
1799
+ Math.min(item.end, this.timelinePos),
1800
+ );
1784
1801
  if (!this.playbackDisabled) {
1785
1802
  if (isInterstitial) {
1786
1803
  // primary fragment loading will exit early in base-stream-controller while `bufferingItem` is set to an Interstitial block
@@ -1897,7 +1914,6 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
1897
1914
  liveStartPosition = this.hls.liveSyncPosition || 0;
1898
1915
  }
1899
1916
  }
1900
- interstitial.assetListResponse = null;
1901
1917
  const assetListLoader = this.assetListLoader.loadAssetList(
1902
1918
  interstitial as InterstitialEventWithAssetList,
1903
1919
  liveStartPosition,
@@ -2205,7 +2221,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
2205
2221
  interstitial.assetList.forEach((asset) => {
2206
2222
  this.clearAssetPlayer(asset.identifier, toSegment);
2207
2223
  });
2208
- interstitial.appendInPlaceStarted = false;
2224
+ // Remove asset list and resolved duration
2225
+ interstitial.reset();
2209
2226
  }
2210
2227
 
2211
2228
  private clearAssetPlayer(
@@ -91,6 +91,22 @@ export class InterstitialsSchedule extends Logger {
91
91
  this.events = this.items = null;
92
92
  }
93
93
 
94
+ public resetErrorsInRange(start: number, end: number): number {
95
+ if (this.events) {
96
+ return this.events.reduce((count, interstitial) => {
97
+ if (
98
+ start <= interstitial.startOffset &&
99
+ end > interstitial.startOffset
100
+ ) {
101
+ delete interstitial.error;
102
+ return count + 1;
103
+ }
104
+ return count;
105
+ }, 0);
106
+ }
107
+ return 0;
108
+ }
109
+
94
110
  get duration(): number {
95
111
  const items = this.items;
96
112
  return items ? items[items.length - 1].end : 0;
@@ -104,8 +104,16 @@ export class InterstitialEvent {
104
104
  }
105
105
 
106
106
  public reset() {
107
+ this.appendInPlaceStarted = false;
107
108
  this.assetListLoader?.destroy();
108
- this.assetListLoader = this.error = undefined;
109
+ this.assetListLoader = undefined;
110
+ if (!this.supplementsPrimary) {
111
+ this.assetListResponse = null;
112
+ this.assetList = [];
113
+ this._duration = null;
114
+ }
115
+ // `error?` is reset when seeking back over interstitial `startOffset`
116
+ // using `schedule.resetErrorsInRange(start, end)`.
109
117
  }
110
118
 
111
119
  public isAssetPastPlayoutLimit(assetIndex: number): boolean {