hls.js 1.6.0-beta.4.0.canary.11044 → 1.6.0-beta.4.0.canary.11046

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
@@ -402,7 +402,7 @@ function enableLogs(debugConfig, context, id) {
402
402
  // Some browsers don't allow to use bind on console object anyway
403
403
  // fallback to default if needed
404
404
  try {
405
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.4.0.canary.11044"}`);
405
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.4.0.canary.11046"}`);
406
406
  } catch (e) {
407
407
  /* log fn threw an exception. All logger methods are no-ops. */
408
408
  return createLogger();
@@ -7955,15 +7955,12 @@ function findPart(partList, sn, partIndex) {
7955
7955
  function reassignFragmentLevelIndexes(levels) {
7956
7956
  levels.forEach((level, index) => {
7957
7957
  var _level$details;
7958
- const fragments = (_level$details = level.details) == null ? void 0 : _level$details.fragments;
7959
- if (fragments) {
7960
- fragments.forEach(fragment => {
7961
- fragment.level = index;
7962
- if (fragment.initSegment) {
7963
- fragment.initSegment.level = index;
7964
- }
7965
- });
7966
- }
7958
+ (_level$details = level.details) == null ? void 0 : _level$details.fragments.forEach(fragment => {
7959
+ fragment.level = index;
7960
+ if (fragment.initSegment) {
7961
+ fragment.initSegment.level = index;
7962
+ }
7963
+ });
7967
7964
  });
7968
7965
  }
7969
7966
 
@@ -8374,6 +8371,7 @@ class BaseStreamController extends TaskLoop {
8374
8371
  this.media = this.mediaBuffer = null;
8375
8372
  this.loopSn = undefined;
8376
8373
  if (transferringMedia) {
8374
+ this.resetLoadingState();
8377
8375
  this.resetTransmuxer();
8378
8376
  return;
8379
8377
  }
@@ -8416,42 +8414,6 @@ class BaseStreamController extends TaskLoop {
8416
8414
  super.onHandlerDestroyed();
8417
8415
  }
8418
8416
  loadFragment(frag, level, targetBufferTime) {
8419
- const config = this.hls.config;
8420
- if (config.interstitialsController && config.enableInterstitialPlayback !== false && frag.type !== PlaylistLevelType.SUBTITLE) {
8421
- // Do not load fragments outside the buffering schedule segment
8422
- const interstitials = this.hls.interstitialsManager;
8423
- const bufferingItem = interstitials == null ? void 0 : interstitials.bufferingItem;
8424
- if (bufferingItem) {
8425
- const bufferingInterstitial = bufferingItem.event;
8426
- if (bufferingInterstitial) {
8427
- // Do not stream fragments while buffering Interstitial Events (except for overlap at the start)
8428
- if (bufferingInterstitial.appendInPlace || Math.abs(frag.start - bufferingItem.start) > 1 || bufferingItem.start === 0) {
8429
- return;
8430
- }
8431
- } else {
8432
- var _level$details;
8433
- // Limit fragment loading to media in schedule item
8434
- if (frag.end <= bufferingItem.start && ((_level$details = level.details) == null ? void 0 : _level$details.live) === false) {
8435
- // fragment ends by schedule item start
8436
- return;
8437
- }
8438
- if (frag.start > bufferingItem.end && bufferingItem.nextEvent) {
8439
- // fragment is past schedule item end
8440
- return;
8441
- }
8442
- }
8443
- }
8444
- // Skip loading of fragments that overlap completely with appendInPlace interstitials
8445
- const playerQueue = interstitials == null ? void 0 : interstitials.playerQueue;
8446
- if (playerQueue) {
8447
- for (let i = playerQueue.length; i--;) {
8448
- const interstitial = playerQueue[i].interstitial;
8449
- if (interstitial.appendInPlace && frag.start >= interstitial.startTime && frag.end <= interstitial.resumeTime) {
8450
- return;
8451
- }
8452
- }
8453
- }
8454
- }
8455
8417
  this.startFragRequested = true;
8456
8418
  this._loadFragForPlayback(frag, level, targetBufferTime);
8457
8419
  }
@@ -8800,9 +8762,9 @@ class BaseStreamController extends TaskLoop {
8800
8762
  }
8801
8763
  doFragPartsLoad(frag, fromPart, level, progressCallback) {
8802
8764
  return new Promise((resolve, reject) => {
8803
- var _level$details2;
8765
+ var _level$details;
8804
8766
  const partsLoaded = [];
8805
- const initialPartList = (_level$details2 = level.details) == null ? void 0 : _level$details2.partList;
8767
+ const initialPartList = (_level$details = level.details) == null ? void 0 : _level$details.partList;
8806
8768
  const loadPart = part => {
8807
8769
  this.fragmentLoader.loadPart(frag, part, progressCallback).then(partLoadedData => {
8808
8770
  partsLoaded[part.index] = partLoadedData;
@@ -9077,6 +9039,7 @@ class BaseStreamController extends TaskLoop {
9077
9039
  const end = this.loadingParts ? levelDetails.partEnd : levelDetails.fragmentEnd;
9078
9040
  frag = this.getFragmentAtPosition(pos, end, levelDetails);
9079
9041
  }
9042
+ frag = this.filterReplacedPrimary(frag, levelDetails);
9080
9043
  return this.mapToInitFragWhenRequired(frag);
9081
9044
  }
9082
9045
  isLoopLoading(frag, targetBufferTime) {
@@ -9104,6 +9067,48 @@ class BaseStreamController extends TaskLoop {
9104
9067
  this.loopSn = undefined;
9105
9068
  return nextFragment;
9106
9069
  }
9070
+ filterReplacedPrimary(frag, details) {
9071
+ if (!frag) {
9072
+ return frag;
9073
+ }
9074
+ const config = this.hls.config;
9075
+ if (config.interstitialsController && config.enableInterstitialPlayback !== false && frag.type !== PlaylistLevelType.SUBTITLE) {
9076
+ // Do not load fragments outside the buffering schedule segment
9077
+ const interstitials = this.hls.interstitialsManager;
9078
+ const bufferingItem = interstitials == null ? void 0 : interstitials.bufferingItem;
9079
+ if (bufferingItem) {
9080
+ const bufferingInterstitial = bufferingItem.event;
9081
+ if (bufferingInterstitial) {
9082
+ // Do not stream fragments while buffering Interstitial Events (except for overlap at the start)
9083
+ if (bufferingInterstitial.appendInPlace || Math.abs(frag.start - bufferingItem.start) > 1 || bufferingItem.start === 0) {
9084
+ return null;
9085
+ }
9086
+ } else {
9087
+ // Limit fragment loading to media in schedule item
9088
+ if (frag.end <= bufferingItem.start && (details == null ? void 0 : details.live) === false) {
9089
+ // fragment ends by schedule item start
9090
+ // this.fragmentTracker.fragBuffered(frag, true);
9091
+ return null;
9092
+ }
9093
+ if (frag.start > bufferingItem.end && bufferingItem.nextEvent) {
9094
+ // fragment is past schedule item end
9095
+ return null;
9096
+ }
9097
+ }
9098
+ }
9099
+ // Skip loading of fragments that overlap completely with appendInPlace interstitials
9100
+ const playerQueue = interstitials == null ? void 0 : interstitials.playerQueue;
9101
+ if (playerQueue) {
9102
+ for (let i = playerQueue.length; i--;) {
9103
+ const interstitial = playerQueue[i].interstitial;
9104
+ if (interstitial.appendInPlace && frag.start >= interstitial.startTime && frag.end <= interstitial.resumeTime) {
9105
+ return null;
9106
+ }
9107
+ }
9108
+ }
9109
+ }
9110
+ return frag;
9111
+ }
9107
9112
  mapToInitFragWhenRequired(frag) {
9108
9113
  // If an initSegment is present, it must be buffered first
9109
9114
  if (frag != null && frag.initSegment && !(frag != null && frag.initSegment.data) && !this.bitrateTest) {
@@ -9476,7 +9481,6 @@ class BaseStreamController extends TaskLoop {
9476
9481
  this.fragmentTracker.removeFragmentsInRange(start, Infinity, this.playlistType, false, true);
9477
9482
  }
9478
9483
  updateLevelTiming(frag, part, level, partial) {
9479
- var _this$transmuxer;
9480
9484
  const details = level.details;
9481
9485
  if (!details) {
9482
9486
  this.warn('level.details undefined');
@@ -9507,25 +9511,28 @@ class BaseStreamController extends TaskLoop {
9507
9511
  }
9508
9512
  return result;
9509
9513
  }, false);
9510
- if (!parsed && ((_this$transmuxer = this.transmuxer) == null ? void 0 : _this$transmuxer.error) === null) {
9511
- const error = new Error(`Found no media in fragment ${frag.sn} of ${this.playlistLabel()} ${frag.level} resetting transmuxer to fallback to playlist timing`);
9514
+ if (!parsed) {
9515
+ var _this$transmuxer;
9512
9516
  if (level.fragmentError === 0) {
9513
9517
  // Mark and track the odd empty segment as a gap to avoid reloading
9514
9518
  this.treatAsGap(frag, level);
9515
9519
  }
9516
- this.warn(error.message);
9517
- this.hls.trigger(Events.ERROR, {
9518
- type: ErrorTypes.MEDIA_ERROR,
9519
- details: ErrorDetails.FRAG_PARSING_ERROR,
9520
- fatal: false,
9521
- error,
9522
- frag,
9523
- reason: `Found no media in msn ${frag.sn} of ${this.playlistLabel()} "${level.url}"`
9524
- });
9525
- if (!this.hls) {
9526
- return;
9520
+ if (((_this$transmuxer = this.transmuxer) == null ? void 0 : _this$transmuxer.error) === null) {
9521
+ const error = new Error(`Found no media in fragment ${frag.sn} of ${this.playlistLabel()} ${frag.level} resetting transmuxer to fallback to playlist timing`);
9522
+ this.warn(error.message);
9523
+ this.hls.trigger(Events.ERROR, {
9524
+ type: ErrorTypes.MEDIA_ERROR,
9525
+ details: ErrorDetails.FRAG_PARSING_ERROR,
9526
+ fatal: false,
9527
+ error,
9528
+ frag,
9529
+ reason: `Found no media in msn ${frag.sn} of ${this.playlistLabel()} "${level.url}"`
9530
+ });
9531
+ if (!this.hls) {
9532
+ return;
9533
+ }
9534
+ this.resetTransmuxer();
9527
9535
  }
9528
- this.resetTransmuxer();
9529
9536
  // For this error fallthrough. Marking parsed will allow advancing to next fragment.
9530
9537
  }
9531
9538
  this.state = State.PARSED;
@@ -9968,7 +9975,7 @@ function requireEventemitter3 () {
9968
9975
  var eventemitter3Exports = requireEventemitter3();
9969
9976
  var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
9970
9977
 
9971
- const version = "1.6.0-beta.4.0.canary.11044";
9978
+ const version = "1.6.0-beta.4.0.canary.11046";
9972
9979
 
9973
9980
  // ensure the worker ends up in the bundle
9974
9981
  // If the worker should not be included this gets aliased to empty.js
@@ -17851,15 +17858,14 @@ class BufferController extends Logger {
17851
17858
  if (!media || !mediaSource) {
17852
17859
  return;
17853
17860
  }
17861
+ // once received, don't listen anymore to sourceopen event
17862
+ mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);
17854
17863
  media.removeEventListener('emptied', this._onMediaEmptied);
17855
17864
  this.updateDuration();
17856
17865
  this.hls.trigger(Events.MEDIA_ATTACHED, {
17857
17866
  media,
17858
17867
  mediaSource: mediaSource
17859
17868
  });
17860
-
17861
- // once received, don't listen anymore to sourceopen event
17862
- mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);
17863
17869
  if (this.mediaSource !== null) {
17864
17870
  this.checkPendingTracks();
17865
17871
  }
@@ -23036,6 +23042,7 @@ class HlsAssetPlayer {
23036
23042
  this.tracks = null;
23037
23043
  this.hasDetails = false;
23038
23044
  this.mediaAttached = null;
23045
+ this._currentTime = void 0;
23039
23046
  this.checkPlayout = () => {
23040
23047
  const interstitial = this.interstitial;
23041
23048
  const playoutLimit = interstitial.playoutLimit;
@@ -23089,7 +23096,7 @@ class HlsAssetPlayer {
23089
23096
  get bufferedEnd() {
23090
23097
  const media = this.media || this.mediaAttached;
23091
23098
  if (!media) {
23092
- return 0;
23099
+ return this.currentTime;
23093
23100
  }
23094
23101
  const bufferInfo = BufferHelper.bufferInfo(media, media.currentTime, 0.001);
23095
23102
  return this.getAssetTime(bufferInfo.end);
@@ -23097,7 +23104,7 @@ class HlsAssetPlayer {
23097
23104
  get currentTime() {
23098
23105
  const media = this.media || this.mediaAttached;
23099
23106
  if (!media) {
23100
- return 0;
23107
+ return this._currentTime || 0;
23101
23108
  }
23102
23109
  return this.getAssetTime(media.currentTime);
23103
23110
  }
@@ -23142,6 +23149,7 @@ class HlsAssetPlayer {
23142
23149
  removeMediaListeners() {
23143
23150
  const media = this.mediaAttached;
23144
23151
  if (media) {
23152
+ this._currentTime = media.currentTime;
23145
23153
  media.removeEventListener('timeupdate', this.checkPlayout);
23146
23154
  }
23147
23155
  }
@@ -23158,6 +23166,7 @@ class HlsAssetPlayer {
23158
23166
  }
23159
23167
  detachMedia() {
23160
23168
  this.removeMediaListeners();
23169
+ this.mediaAttached = null;
23161
23170
  this.hls.detachMedia();
23162
23171
  }
23163
23172
  resumeBuffering() {
@@ -23179,7 +23188,8 @@ class HlsAssetPlayer {
23179
23188
  this.hls.off(event, listener);
23180
23189
  }
23181
23190
  toString() {
23182
- return `HlsAssetPlayer: ${eventAssetToString(this.assetItem)} ${this.hls.sessionId} ${this.interstitial.appendInPlace ? 'append-in-place' : ''}`;
23191
+ var _this$hls4, _this$interstitial;
23192
+ return `HlsAssetPlayer: ${eventAssetToString(this.assetItem)} ${(_this$hls4 = this.hls) == null ? void 0 : _this$hls4.sessionId} ${(_this$interstitial = this.interstitial) != null && _this$interstitial.appendInPlace ? 'append-in-place' : ''}`;
23183
23193
  }
23184
23194
  }
23185
23195
 
@@ -23336,7 +23346,7 @@ class InterstitialsSchedule extends Logger {
23336
23346
  }
23337
23347
  return null;
23338
23348
  }
23339
- parseInterstitialDateRanges(mediaSelection) {
23349
+ parseInterstitialDateRanges(mediaSelection, enableAppendInPlace) {
23340
23350
  const details = mediaSelection.main.details;
23341
23351
  const {
23342
23352
  dateRanges
@@ -23344,7 +23354,7 @@ class InterstitialsSchedule extends Logger {
23344
23354
  const previousInterstitialEvents = this.events;
23345
23355
  const interstitialEvents = this.parseDateRanges(dateRanges, {
23346
23356
  url: details.url
23347
- });
23357
+ }, enableAppendInPlace);
23348
23358
  const ids = Object.keys(dateRanges);
23349
23359
  const removedInterstitials = previousInterstitialEvents ? previousInterstitialEvents.filter(event => !ids.includes(event.identifier)) : [];
23350
23360
  if (interstitialEvents.length) {
@@ -23400,7 +23410,7 @@ class InterstitialsSchedule extends Logger {
23400
23410
  }
23401
23411
  }
23402
23412
  }
23403
- parseDateRanges(dateRanges, baseData) {
23413
+ parseDateRanges(dateRanges, baseData, enableAppendInPlace) {
23404
23414
  const interstitialEvents = [];
23405
23415
  const ids = Object.keys(dateRanges);
23406
23416
  for (let i = 0; i < ids.length; i++) {
@@ -23415,6 +23425,9 @@ class InterstitialsSchedule extends Logger {
23415
23425
  } else {
23416
23426
  interstitial = new InterstitialEvent(dateRange, baseData);
23417
23427
  this.eventMap[id] = interstitial;
23428
+ if (enableAppendInPlace === false) {
23429
+ interstitial.appendInPlace = enableAppendInPlace;
23430
+ }
23418
23431
  }
23419
23432
  interstitialEvents.push(interstitial);
23420
23433
  }
@@ -23618,13 +23631,11 @@ class InterstitialsSchedule extends Logger {
23618
23631
  interstitial.appendInPlace = false;
23619
23632
  }
23620
23633
  }
23621
- if (!interstitial.appendInPlace) {
23634
+ if (!interstitial.appendInPlace && i + 1 < interstitialEvents.length) {
23622
23635
  // abutting Interstitials must use the same MediaSource strategy, this applies to all whether or not they are back to back:
23623
- for (let j = i - 1; i--;) {
23624
- const timeBetween = interstitialEvents[j + 1].startTime - interstitialEvents[j].resumeTime;
23625
- if (timeBetween < ABUTTING_THRESHOLD_SECONDS) {
23626
- interstitialEvents[j].appendInPlace = false;
23627
- }
23636
+ const timeBetween = interstitialEvents[i + 1].startTime - interstitialEvents[i].resumeTime;
23637
+ if (timeBetween < ABUTTING_THRESHOLD_SECONDS) {
23638
+ interstitialEvents[i + 1].appendInPlace = false;
23628
23639
  }
23629
23640
  }
23630
23641
  // Update cumulativeDuration for next abutting interstitial with the same start date
@@ -23951,9 +23962,6 @@ class InterstitialsController extends Logger {
23951
23962
  const removedIds = removedInterstitials.map(interstitial => interstitial.identifier);
23952
23963
  const interstitialsUpdated = !!(interstitialEvents.length || removedIds.length);
23953
23964
  if (interstitialsUpdated) {
23954
- if (this.hls.config.interstitialAppendInPlace === false) {
23955
- interstitialEvents.forEach(event => event.appendInPlace = false);
23956
- }
23957
23965
  this.log(`INTERSTITIALS_UPDATED (${interstitialEvents.length}): ${interstitialEvents}
23958
23966
  Schedule: ${scheduleItems.map(seg => segmentToString(seg))}`);
23959
23967
  }
@@ -24083,10 +24091,12 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))}`);
24083
24091
  this.pauseBuffering();
24084
24092
  }
24085
24093
  resumeBuffering() {
24086
- this.playerQueue.forEach(player => player.resumeBuffering());
24094
+ var _this$getBufferingPla;
24095
+ (_this$getBufferingPla = this.getBufferingPlayer()) == null ? void 0 : _this$getBufferingPla.resumeBuffering();
24087
24096
  }
24088
24097
  pauseBuffering() {
24089
- this.playerQueue.forEach(player => player.pauseBuffering());
24098
+ var _this$getBufferingPla2;
24099
+ (_this$getBufferingPla2 = this.getBufferingPlayer()) == null ? void 0 : _this$getBufferingPla2.pauseBuffering();
24090
24100
  }
24091
24101
  destroy() {
24092
24102
  this.unregisterListeners();
@@ -24524,33 +24534,48 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))}`);
24524
24534
  }
24525
24535
  transferMediaTo(player, media) {
24526
24536
  var _this$detachedData2, _attachMediaSourceDat;
24537
+ if (player.media === media) {
24538
+ return;
24539
+ }
24527
24540
  let attachMediaSourceData = null;
24528
24541
  const primaryPlayer = this.hls;
24529
24542
  const isAssetPlayer = player !== primaryPlayer;
24530
24543
  const appendInPlace = isAssetPlayer && player.interstitial.appendInPlace;
24531
24544
  const detachedMediaSource = (_this$detachedData2 = this.detachedData) == null ? void 0 : _this$detachedData2.mediaSource;
24532
24545
  let logFromSource;
24533
- if (primaryPlayer.media && appendInPlace) {
24534
- attachMediaSourceData = primaryPlayer.transferMedia();
24535
- this.detachedData = attachMediaSourceData;
24546
+ if (primaryPlayer.media) {
24547
+ if (appendInPlace) {
24548
+ attachMediaSourceData = primaryPlayer.transferMedia();
24549
+ this.detachedData = attachMediaSourceData;
24550
+ }
24536
24551
  logFromSource = `Primary`;
24537
24552
  } else if (detachedMediaSource) {
24538
24553
  const bufferingPlayer = this.getBufferingPlayer();
24539
24554
  if (bufferingPlayer) {
24540
24555
  attachMediaSourceData = bufferingPlayer.transferMedia();
24556
+ logFromSource = `${bufferingPlayer}`;
24557
+ } else {
24558
+ logFromSource = `detached MediaSource`;
24541
24559
  }
24542
- logFromSource = `${bufferingPlayer}`;
24543
24560
  } else {
24544
- logFromSource = `<unknown>`;
24561
+ logFromSource = `detached media`;
24545
24562
  }
24546
- this.log(`transferring to ${isAssetPlayer ? player : 'Primary'}
24547
- MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
24548
24563
  if (!attachMediaSourceData) {
24549
24564
  if (detachedMediaSource) {
24550
24565
  attachMediaSourceData = this.detachedData;
24551
24566
  this.log(`using detachedData: MediaSource ${stringify(attachMediaSourceData)}`);
24552
- } else if (!this.detachedData || this.hls.media === media) {
24553
- // Media is attaching when `detachedData` and `hls.media` are populated. Detach to clear the MediaSource.
24567
+ } else if (!this.detachedData || primaryPlayer.media === media) {
24568
+ // Keep interstitial media transition consistent
24569
+ const playerQueue = this.playerQueue;
24570
+ if (playerQueue.length > 1) {
24571
+ playerQueue.forEach(queuedPlayer => {
24572
+ if (isAssetPlayer && queuedPlayer.interstitial.appendInPlace !== appendInPlace) {
24573
+ const interstitial = queuedPlayer.interstitial;
24574
+ this.clearInterstitial(queuedPlayer.interstitial, null);
24575
+ interstitial.appendInPlace = false;
24576
+ }
24577
+ });
24578
+ }
24554
24579
  this.hls.detachMedia();
24555
24580
  this.detachedData = {
24556
24581
  media
@@ -24559,7 +24584,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
24559
24584
  }
24560
24585
  const transferring = attachMediaSourceData && 'mediaSource' in attachMediaSourceData && ((_attachMediaSourceDat = attachMediaSourceData.mediaSource) == null ? void 0 : _attachMediaSourceDat.readyState) !== 'closed';
24561
24586
  const dataToAttach = transferring && attachMediaSourceData ? attachMediaSourceData : media;
24562
- this.log(`${transferring ? 'transfering MediaSource' : 'attaching media'} to ${isAssetPlayer ? player : 'Primary'}`);
24587
+ this.log(`${transferring ? 'transfering MediaSource' : 'attaching media'} to ${isAssetPlayer ? player : 'Primary'} from ${logFromSource}`);
24563
24588
  if (dataToAttach === attachMediaSourceData) {
24564
24589
  const isAssetAtEndOfSchedule = isAssetPlayer && player.assetId === this.schedule.assetIdAtEnd;
24565
24590
  // Prevent asset players from marking EoS on transferred MediaSource
@@ -24656,6 +24681,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
24656
24681
  const assetId = playingAsset == null ? void 0 : playingAsset.identifier;
24657
24682
  const player = assetId ? this.getAssetPlayer(assetId) : null;
24658
24683
  if (player && assetId && (!this.eventItemsMatch(currentItem, scheduledItem) || assetListIndex !== undefined && assetId !== ((_interstitial$assetLi = interstitial.assetList) == null ? void 0 : _interstitial$assetLi[assetListIndex].identifier))) {
24684
+ var _this$detachedData3;
24659
24685
  const _assetListIndex = interstitial.findAssetIndex(playingAsset);
24660
24686
  this.log(`INTERSTITIAL_ASSET_ENDED ${_assetListIndex + 1}/${interstitial.assetList.length} ${eventAssetToString(playingAsset)}`);
24661
24687
  this.endedAsset = playingAsset;
@@ -24669,7 +24695,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
24669
24695
  player
24670
24696
  });
24671
24697
  this.retreiveMediaSource(assetId, scheduledItem);
24672
- if (player.media && !this.detachedData) {
24698
+ if (player.media && !((_this$detachedData3 = this.detachedData) != null && _this$detachedData3.mediaSource)) {
24673
24699
  player.detachMedia();
24674
24700
  }
24675
24701
  }
@@ -24810,13 +24836,13 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
24810
24836
  return !!((_this$primaryDetails = this.primaryDetails) != null && _this$primaryDetails.live);
24811
24837
  }
24812
24838
  resumePrimary(scheduledItem, index, fromItem) {
24813
- var _this$detachedData3;
24839
+ var _this$detachedData4;
24814
24840
  this.playingItem = scheduledItem;
24815
24841
  this.playingAsset = this.endedAsset = null;
24816
24842
  this.waitingItem = this.endedItem = null;
24817
24843
  this.bufferedToItem(scheduledItem);
24818
24844
  this.log(`resuming ${segmentToString(scheduledItem)}`);
24819
- if (!((_this$detachedData3 = this.detachedData) != null && _this$detachedData3.mediaSource)) {
24845
+ if (!((_this$detachedData4 = this.detachedData) != null && _this$detachedData4.mediaSource)) {
24820
24846
  let timelinePos = this.timelinePos;
24821
24847
  if (timelinePos < scheduledItem.start || timelinePos >= scheduledItem.end) {
24822
24848
  timelinePos = this.getPrimaryResumption(scheduledItem, index);
@@ -24917,7 +24943,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
24917
24943
  main
24918
24944
  });
24919
24945
  this.mediaSelection = currentSelection;
24920
- this.schedule.parseInterstitialDateRanges(currentSelection);
24946
+ this.schedule.parseInterstitialDateRanges(currentSelection, this.hls.config.interstitialAppendInPlace);
24921
24947
  if (!this.effectivePlayingItem && this.schedule.items) {
24922
24948
  this.checkStart();
24923
24949
  }
@@ -24999,6 +25025,8 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
24999
25025
  if (!this.playingLastItem && playingItem) {
25000
25026
  const playingIndex = this.findItemIndex(playingItem);
25001
25027
  this.setSchedulePosition(playingIndex + 1);
25028
+ } else {
25029
+ this.shouldPlay = false;
25002
25030
  }
25003
25031
  }
25004
25032
  updateItem(previousItem, time) {
@@ -25167,16 +25195,16 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
25167
25195
  }
25168
25196
  }
25169
25197
  preloadAssets(interstitial, assetListIndex) {
25198
+ const uri = interstitial.assetUrl;
25170
25199
  const assetListLength = interstitial.assetList.length;
25171
25200
  const neverLoaded = assetListLength === 0 && !interstitial.assetListLoader;
25172
25201
  const playOnce = interstitial.cue.once;
25173
25202
  if (neverLoaded) {
25174
- this.log(`Load interstitial asset ${assetListIndex + 1}/${assetListLength} ${interstitial}`);
25203
+ this.log(`Load interstitial asset ${assetListIndex + 1}/${uri ? 1 : assetListLength} ${interstitial}`);
25175
25204
  const timelineStart = interstitial.timelineStart;
25176
25205
  if (interstitial.appendInPlace) {
25177
25206
  this.flushFrontBuffer(timelineStart + 0.25);
25178
25207
  }
25179
- const uri = interstitial.assetUrl;
25180
25208
  if (uri) {
25181
25209
  return this.createAsset(interstitial, 0, 0, timelineStart, interstitial.duration, uri);
25182
25210
  }
@@ -25474,12 +25502,10 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
25474
25502
  }
25475
25503
 
25476
25504
  // detach media and attach to interstitial player if it does not have another element attached
25477
- if (!player.media) {
25478
- this.bufferAssetPlayer(player, media);
25479
- }
25505
+ this.bufferAssetPlayer(player, media);
25480
25506
  }
25481
25507
  bufferAssetPlayer(player, media) {
25482
- var _this$schedule$items4, _this$detachedData4;
25508
+ var _this$schedule$items4, _this$detachedData5;
25483
25509
  const {
25484
25510
  interstitial,
25485
25511
  assetItem,
@@ -25496,8 +25522,13 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
25496
25522
  if (bufferingPlayer === player) {
25497
25523
  return;
25498
25524
  }
25499
- const activeTracks = (bufferingPlayer == null ? void 0 : bufferingPlayer.tracks) || ((_this$detachedData4 = this.detachedData) == null ? void 0 : _this$detachedData4.tracks) || this.requiredTracks;
25500
- if (interstitial.appendInPlace && assetItem !== this.playingAsset) {
25525
+ const appendInPlaceNext = interstitial.appendInPlace;
25526
+ if (appendInPlaceNext && (bufferingPlayer == null ? void 0 : bufferingPlayer.interstitial.appendInPlace) === false) {
25527
+ // Media is detached and not available to append in place
25528
+ return;
25529
+ }
25530
+ const activeTracks = (bufferingPlayer == null ? void 0 : bufferingPlayer.tracks) || ((_this$detachedData5 = this.detachedData) == null ? void 0 : _this$detachedData5.tracks) || this.requiredTracks;
25531
+ if (appendInPlaceNext && assetItem !== this.playingAsset) {
25501
25532
  // Do not buffer another item if tracks are unknown or incompatible
25502
25533
  if (!player.tracks) {
25503
25534
  return;
@@ -25569,7 +25600,6 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
25569
25600
  if (playingItem) {
25570
25601
  this.log(`Fallback to primary from event "${interstitial.identifier}" start: ${flushStart} pos: ${this.timelinePos} playing: ${playingItem ? segmentToString(playingItem) : '<none>'} error: ${interstitial.error}`);
25571
25602
  if (interstitial.appendInPlace) {
25572
- interstitial.appendInPlace = false;
25573
25603
  this.attachPrimary(flushStart, null);
25574
25604
  this.flushFrontBuffer(flushStart);
25575
25605
  }
@@ -25581,6 +25611,8 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`);
25581
25611
  if (!this.itemsMatch(playingItem, newPlayingItem)) {
25582
25612
  const scheduleIndex = this.schedule.findItemIndexAtTime(timelinePos);
25583
25613
  this.setSchedulePosition(scheduleIndex);
25614
+ } else {
25615
+ this.clearInterstitial(interstitial, null);
25584
25616
  }
25585
25617
  } else {
25586
25618
  this.checkStart();
@@ -25985,21 +26017,22 @@ class SubtitleStreamController extends BaseStreamController {
25985
26017
  } else {
25986
26018
  foundFrag = fragments[fragLen - 1];
25987
26019
  }
26020
+ foundFrag = this.filterReplacedPrimary(foundFrag, track.details);
25988
26021
  if (!foundFrag) {
25989
26022
  return;
25990
26023
  }
25991
- foundFrag = this.mapToInitFragWhenRequired(foundFrag);
25992
- if (isMediaFragment(foundFrag)) {
25993
- // Load earlier fragment in same discontinuity to make up for misaligned playlists and cues that extend beyond end of segment
25994
- const curSNIdx = foundFrag.sn - trackDetails.startSN;
25995
- const prevFrag = fragments[curSNIdx - 1];
25996
- if (prevFrag && prevFrag.cc === foundFrag.cc && this.fragmentTracker.getState(prevFrag) === FragmentState.NOT_LOADED) {
25997
- foundFrag = prevFrag;
25998
- }
26024
+ // Load earlier fragment in same discontinuity to make up for misaligned playlists and cues that extend beyond end of segment
26025
+ const curSNIdx = foundFrag.sn - trackDetails.startSN;
26026
+ const prevFrag = fragments[curSNIdx - 1];
26027
+ if (prevFrag && prevFrag.cc === foundFrag.cc && this.fragmentTracker.getState(prevFrag) === FragmentState.NOT_LOADED) {
26028
+ foundFrag = prevFrag;
25999
26029
  }
26000
26030
  if (this.fragmentTracker.getState(foundFrag) === FragmentState.NOT_LOADED) {
26001
26031
  // only load if fragment is not loaded
26002
- this.loadFragment(foundFrag, track, targetBufferTime);
26032
+ const fragToLoad = this.mapToInitFragWhenRequired(foundFrag);
26033
+ if (fragToLoad) {
26034
+ this.loadFragment(fragToLoad, track, targetBufferTime);
26035
+ }
26003
26036
  }
26004
26037
  }
26005
26038
  }