hls.js 1.6.3-0.canary.11251 → 1.6.3-0.canary.11252

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.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.11251"}`);
526
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.3-0.canary.11252"}`);
527
527
  } catch (e) {
528
528
  /* log fn threw an exception. All logger methods are no-ops. */
529
529
  return createLogger();
@@ -10237,7 +10237,7 @@ function requireEventemitter3 () {
10237
10237
  var eventemitter3Exports = requireEventemitter3();
10238
10238
  var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
10239
10239
 
10240
- const version = "1.6.3-0.canary.11251";
10240
+ const version = "1.6.3-0.canary.11252";
10241
10241
 
10242
10242
  // ensure the worker ends up in the bundle
10243
10243
  // If the worker should not be included this gets aliased to empty.js
@@ -23276,14 +23276,18 @@ class InterstitialEvent {
23276
23276
  // using `schedule.resetErrorsInRange(start, end)`.
23277
23277
  }
23278
23278
  isAssetPastPlayoutLimit(assetIndex) {
23279
- if (assetIndex >= this.assetList.length) {
23279
+ var _this$assetList$asset;
23280
+ if (assetIndex > 0 && assetIndex >= this.assetList.length) {
23280
23281
  return true;
23281
23282
  }
23282
23283
  const playoutLimit = this.playoutLimit;
23283
23284
  if (assetIndex <= 0 || isNaN(playoutLimit)) {
23284
23285
  return false;
23285
23286
  }
23286
- const assetOffset = this.assetList[assetIndex].startOffset;
23287
+ if (playoutLimit === 0) {
23288
+ return true;
23289
+ }
23290
+ const assetOffset = ((_this$assetList$asset = this.assetList[assetIndex]) == null ? void 0 : _this$assetList$asset.startOffset) || 0;
23287
23291
  return assetOffset > playoutLimit;
23288
23292
  }
23289
23293
  findAssetIndex(asset) {
@@ -23429,6 +23433,12 @@ function getInterstitialUrl(uri, sessionId, baseUrl) {
23429
23433
  }
23430
23434
  return url;
23431
23435
  }
23436
+ function getNextAssetIndex(interstitial, assetListIndex) {
23437
+ while ((_interstitial$assetLi = interstitial.assetList[++assetListIndex]) != null && _interstitial$assetLi.error) {
23438
+ var _interstitial$assetLi;
23439
+ } /* no-op */
23440
+ return assetListIndex;
23441
+ }
23432
23442
  function eventToString(interstitial) {
23433
23443
  return `["${interstitial.identifier}" ${interstitial.cue.pre ? '<pre>' : interstitial.cue.post ? '<post>' : ''}${interstitial.timelineStart.toFixed(2)}-${interstitial.resumeTime.toFixed(2)}]`;
23434
23444
  }
@@ -23627,6 +23637,17 @@ class HlsAssetPlayer {
23627
23637
  this.bufferSnapShot();
23628
23638
  return this.hls.transferMedia();
23629
23639
  }
23640
+ resetDetails() {
23641
+ const hls = this.hls;
23642
+ if (this.hasDetails) {
23643
+ hls.stopLoad();
23644
+ const deleteDetails = obj => delete obj.details;
23645
+ hls.levels.forEach(deleteDetails);
23646
+ hls.allAudioTracks.forEach(deleteDetails);
23647
+ hls.allSubtitleTracks.forEach(deleteDetails);
23648
+ this.hasDetails = false;
23649
+ }
23650
+ }
23630
23651
  on(event, listener, context) {
23631
23652
  this.hls.on(event, listener);
23632
23653
  }
@@ -24409,7 +24430,7 @@ class InterstitialsController extends Logger {
24409
24430
  const durations = schedule.durations;
24410
24431
  const removedIds = removedInterstitials.map(interstitial => interstitial.identifier);
24411
24432
  const interstitialsUpdated = !!(interstitialEvents.length || removedIds.length);
24412
- if (interstitialsUpdated) {
24433
+ if (interstitialsUpdated || previousItems) {
24413
24434
  this.log(`INTERSTITIALS_UPDATED (${interstitialEvents.length}): ${interstitialEvents}
24414
24435
  Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timelinePos}`);
24415
24436
  }
@@ -25082,8 +25103,8 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25082
25103
  }
25083
25104
  }
25084
25105
  advanceAfterAssetEnded(interstitial, index, assetListIndex) {
25085
- const nextAssetIndex = assetListIndex + 1;
25086
- if (!interstitial.isAssetPastPlayoutLimit(nextAssetIndex) && !interstitial.assetList[nextAssetIndex].error) {
25106
+ const nextAssetIndex = getNextAssetIndex(interstitial, assetListIndex);
25107
+ if (!interstitial.isAssetPastPlayoutLimit(nextAssetIndex)) {
25087
25108
  // Advance to next asset list item
25088
25109
  this.setSchedulePosition(index, nextAssetIndex);
25089
25110
  } else {
@@ -25113,7 +25134,7 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25113
25134
  if (interstitial) {
25114
25135
  const itemIndex = schedule.findEventIndex(parentIdentifier);
25115
25136
  const assetListIndex = schedule.findAssetIndex(interstitial, time);
25116
- this.setSchedulePosition(itemIndex, assetListIndex);
25137
+ this.advanceAfterAssetEnded(interstitial, itemIndex, assetListIndex - 1);
25117
25138
  }
25118
25139
  }
25119
25140
  setSchedulePosition(index, assetListIndex) {
@@ -25134,13 +25155,13 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25134
25155
  const player = assetId ? this.getAssetPlayer(assetId) : null;
25135
25156
  if (player && assetId && (!this.eventItemsMatch(currentItem, scheduledItem) || assetListIndex !== undefined && assetId !== ((_interstitial$assetLi = interstitial.assetList) == null ? void 0 : _interstitial$assetLi[assetListIndex].identifier))) {
25136
25157
  var _this$detachedData3;
25137
- const _assetListIndex = interstitial.findAssetIndex(playingAsset);
25138
- this.log(`INTERSTITIAL_ASSET_ENDED ${_assetListIndex + 1}/${interstitial.assetList.length} ${eventAssetToString(playingAsset)}`);
25158
+ const playingAssetListIndex = interstitial.findAssetIndex(playingAsset);
25159
+ this.log(`INTERSTITIAL_ASSET_ENDED ${playingAssetListIndex + 1}/${interstitial.assetList.length} ${eventAssetToString(playingAsset)}`);
25139
25160
  this.endedAsset = playingAsset;
25140
25161
  this.playingAsset = null;
25141
25162
  this.hls.trigger(Events.INTERSTITIAL_ASSET_ENDED, {
25142
25163
  asset: playingAsset,
25143
- assetListIndex: _assetListIndex,
25164
+ assetListIndex: playingAssetListIndex,
25144
25165
  event: interstitial,
25145
25166
  schedule: scheduleItems.slice(0),
25146
25167
  scheduleIndex: index,
@@ -25198,6 +25219,12 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25198
25219
  // find asset index
25199
25220
  if (assetListIndex === undefined) {
25200
25221
  assetListIndex = this.schedule.findAssetIndex(interstitial, this.timelinePos);
25222
+ const assetIndexCandidate = getNextAssetIndex(interstitial, assetListIndex - 1);
25223
+ if (interstitial.isAssetPastPlayoutLimit(assetIndexCandidate)) {
25224
+ this.advanceAfterAssetEnded(interstitial, index, assetListIndex);
25225
+ return;
25226
+ }
25227
+ assetListIndex = assetIndexCandidate;
25201
25228
  }
25202
25229
  // Ensure Interstitial is enqueued
25203
25230
  const waitingItem = this.waitingItem;
@@ -25311,7 +25338,7 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25311
25338
  if (!scheduleItems) {
25312
25339
  return;
25313
25340
  }
25314
- this.log(`resumed ${segmentToString(scheduledItem)}`);
25341
+ this.log(`INTERSTITIALS_PRIMARY_RESUMED ${segmentToString(scheduledItem)}`);
25315
25342
  this.hls.trigger(Events.INTERSTITIALS_PRIMARY_RESUMED, {
25316
25343
  schedule: scheduleItems.slice(0),
25317
25344
  scheduleIndex: index
@@ -25607,9 +25634,9 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25607
25634
  const bufferingPlayer = this.getBufferingPlayer();
25608
25635
  this.bufferingItem = item;
25609
25636
  this.bufferedPos = Math.max(item.start, Math.min(item.end, this.timelinePos));
25637
+ const timeRemaining = bufferingPlayer ? bufferingPlayer.remaining : bufferingLast ? bufferingLast.end - this.timelinePos : 0;
25638
+ this.log(`INTERSTITIALS_BUFFERED_TO_BOUNDARY ${segmentToString(item)}` + (bufferingLast ? ` (${timeRemaining.toFixed(2)} remaining)` : ''));
25610
25639
  if (!this.playbackDisabled) {
25611
- const timeRemaining = bufferingPlayer ? bufferingPlayer.remaining : bufferingLast ? bufferingLast.end - this.timelinePos : 0;
25612
- this.log(`buffered to boundary ${segmentToString(item)}` + (bufferingLast ? ` (${timeRemaining.toFixed(2)} remaining)` : ''));
25613
25640
  if (isInterstitial) {
25614
25641
  // primary fragment loading will exit early in base-stream-controller while `bufferingItem` is set to an Interstitial block
25615
25642
  item.event.assetList.forEach(asset => {
@@ -25787,7 +25814,6 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25787
25814
  return this.createAssetPlayer(interstitial, assetItem, assetListIndex);
25788
25815
  }
25789
25816
  createAssetPlayer(interstitial, assetItem, assetListIndex) {
25790
- this.log(`create HLSAssetPlayer for ${eventAssetToString(assetItem)}`);
25791
25817
  const primary = this.hls;
25792
25818
  const userConfig = primary.userConfig;
25793
25819
  let videoPreference = userConfig.videoPreference;
@@ -25896,11 +25922,11 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25896
25922
  }
25897
25923
  // Preload at end of asset
25898
25924
  const scheduleIndex = this.schedule.findEventIndex(interstitial.identifier);
25899
- const assetListIndex = interstitial.findAssetIndex(assetItem);
25900
- const nextAssetIndex = assetListIndex + 1;
25901
25925
  const item = (_this$schedule$items2 = this.schedule.items) == null ? void 0 : _this$schedule$items2[scheduleIndex];
25902
25926
  if (this.isInterstitial(item)) {
25903
- if (assetListIndex !== -1 && !interstitial.isAssetPastPlayoutLimit(nextAssetIndex) && !interstitial.assetList[nextAssetIndex].error) {
25927
+ const assetListIndex = interstitial.findAssetIndex(assetItem);
25928
+ const nextAssetIndex = getNextAssetIndex(interstitial, assetListIndex);
25929
+ if (!interstitial.isAssetPastPlayoutLimit(nextAssetIndex)) {
25904
25930
  this.bufferedToItem(item, nextAssetIndex);
25905
25931
  } else {
25906
25932
  var _this$schedule$items3;
@@ -25958,6 +25984,7 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25958
25984
  };
25959
25985
  this.handleAssetItemError(errorData, interstitial, this.schedule.findEventIndex(interstitial.identifier), assetListIndex, error.message);
25960
25986
  });
25987
+ this.log(`INTERSTITIAL_ASSET_PLAYER_CREATED ${eventAssetToString(assetItem)}`);
25961
25988
  this.hls.trigger(Events.INTERSTITIAL_ASSET_PLAYER_CREATED, {
25962
25989
  asset: assetItem,
25963
25990
  assetListIndex,
@@ -25973,10 +26000,20 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
25973
26000
  // Remove asset list and resolved duration
25974
26001
  interstitial.reset();
25975
26002
  }
26003
+ resetAssetPlayer(assetId) {
26004
+ // Reset asset player so that it's timeline can be adjusted without reloading the MVP
26005
+ const playerIndex = this.getAssetPlayerQueueIndex(assetId);
26006
+ if (playerIndex !== -1) {
26007
+ this.log(`reset asset player "${assetId}" after error`);
26008
+ const player = this.playerQueue[playerIndex];
26009
+ this.transferMediaFromPlayer(player, null);
26010
+ player.resetDetails();
26011
+ }
26012
+ }
25976
26013
  clearAssetPlayer(assetId, toSegment) {
25977
26014
  const playerIndex = this.getAssetPlayerQueueIndex(assetId);
25978
26015
  if (playerIndex !== -1) {
25979
- this.log(`clearAssetPlayer "${assetId}" toSegment: ${toSegment ? segmentToString(toSegment) : toSegment}`);
26016
+ this.log(`clear asset player "${assetId}" toSegment: ${toSegment ? segmentToString(toSegment) : toSegment}`);
25980
26017
  const player = this.playerQueue[playerIndex];
25981
26018
  this.transferMediaFromPlayer(player, toSegment);
25982
26019
  this.playerQueue.splice(playerIndex, 1);
@@ -26006,7 +26043,7 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
26006
26043
  this.clearAssetPlayer(playingAsset.identifier, scheduleItems[scheduleIndex]);
26007
26044
  delete playingAsset.error;
26008
26045
  }
26009
- this.log(`INTERSTITIAL_ASSET_STARTED ${assetListIndex + 1}/${assetListLength} ${player}`);
26046
+ this.log(`INTERSTITIAL_ASSET_STARTED ${assetListIndex + 1}/${assetListLength} ${eventAssetToString(assetItem)}`);
26010
26047
  this.hls.trigger(Events.INTERSTITIAL_ASSET_STARTED, {
26011
26048
  asset: assetItem,
26012
26049
  assetListIndex,
@@ -26050,7 +26087,7 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
26050
26087
  return;
26051
26088
  }
26052
26089
  if (activeTracks && !isCompatibleTrackChange(activeTracks, player.tracks)) {
26053
- const error = new Error(`Asset "${assetId}" SourceBuffer tracks ('${Object.keys(player.tracks)}') are not compatible with primary content tracks ('${Object.keys(activeTracks)}')`);
26090
+ const error = new Error(`Asset ${eventAssetToString(assetItem)} SourceBuffer tracks ('${Object.keys(player.tracks)}') are not compatible with primary content tracks ('${Object.keys(activeTracks)}')`);
26054
26091
  const errorData = {
26055
26092
  fatal: true,
26056
26093
  type: ErrorTypes.OTHER_ERROR,
@@ -26068,12 +26105,11 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
26068
26105
  if (data.details === ErrorDetails.BUFFER_STALLED_ERROR) {
26069
26106
  return;
26070
26107
  }
26071
- const assetItem = interstitial.assetList[assetListIndex] || null;
26072
- let player = null;
26073
- if (assetItem) {
26074
- const playerIndex = this.getAssetPlayerQueueIndex(assetItem.identifier);
26075
- player = this.playerQueue[playerIndex] || null;
26076
- }
26108
+ const assetItem = interstitial.assetList[assetListIndex];
26109
+ this.warn(`INTERSTITIAL_ASSET_ERROR ${assetItem ? eventAssetToString(assetItem) : assetItem} ${data.error}`);
26110
+ const assetId = assetItem == null ? void 0 : assetItem.identifier;
26111
+ const playerIndex = this.getAssetPlayerQueueIndex(assetId);
26112
+ const player = this.playerQueue[playerIndex] || null;
26077
26113
  const items = this.schedule.items;
26078
26114
  const interstitialAssetError = _extends({}, data, {
26079
26115
  fatal: false,
@@ -26085,16 +26121,14 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
26085
26121
  scheduleIndex,
26086
26122
  player
26087
26123
  });
26088
- this.warn(`Asset item error: ${data.error}`);
26089
26124
  this.hls.trigger(Events.INTERSTITIAL_ASSET_ERROR, interstitialAssetError);
26090
26125
  if (!data.fatal) {
26091
26126
  return;
26092
26127
  }
26128
+ const playingAsset = this.playingAsset;
26093
26129
  const error = new Error(errorMessage);
26094
26130
  if (assetItem) {
26095
- if (this.playingAsset !== assetItem) {
26096
- this.clearAssetPlayer(assetItem.identifier, null);
26097
- }
26131
+ this.clearAssetPlayer(assetId, null);
26098
26132
  assetItem.error = error;
26099
26133
  }
26100
26134
 
@@ -26102,10 +26136,17 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
26102
26136
  if (!interstitial.assetList.some(asset => !asset.error)) {
26103
26137
  interstitial.error = error;
26104
26138
  } else if (interstitial.appendInPlace) {
26105
- // Skip entire interstitial since moving up subsequent assets is error prone
26106
- interstitial.error = error;
26139
+ // Reset level details and reload/parse media playlists to align with updated schedule
26140
+ for (let i = assetListIndex; i < interstitial.assetList.length; i++) {
26141
+ this.resetAssetPlayer(interstitial.assetList[i].identifier);
26142
+ }
26143
+ this.updateSchedule();
26144
+ }
26145
+ if (interstitial.error) {
26146
+ this.primaryFallback(interstitial);
26147
+ } else if (playingAsset && playingAsset.identifier === assetId) {
26148
+ this.advanceAfterAssetEnded(interstitial, scheduleIndex, assetListIndex);
26107
26149
  }
26108
- this.primaryFallback(interstitial);
26109
26150
  }
26110
26151
  primaryFallback(interstitial) {
26111
26152
  // Fallback to Primary by on current or future events by updating schedule to skip errored interstitials/assets
@@ -26120,16 +26161,15 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
26120
26161
  timelinePos = this.hls.startPosition;
26121
26162
  }
26122
26163
  const newPlayingItem = this.updateItem(playingItem, timelinePos);
26123
- if (!this.itemsMatch(playingItem, newPlayingItem)) {
26124
- const scheduleIndex = this.schedule.findItemIndexAtTime(timelinePos);
26125
- this.setSchedulePosition(scheduleIndex);
26126
- } else {
26164
+ if (this.itemsMatch(playingItem, newPlayingItem)) {
26127
26165
  this.clearInterstitial(interstitial, null);
26128
26166
  }
26129
26167
  if (interstitial.appendInPlace) {
26130
26168
  this.attachPrimary(flushStart, null);
26131
26169
  this.flushFrontBuffer(flushStart);
26132
26170
  }
26171
+ const scheduleIndex = this.schedule.findItemIndexAtTime(timelinePos);
26172
+ this.setSchedulePosition(scheduleIndex);
26133
26173
  } else {
26134
26174
  this.checkStart();
26135
26175
  }