hls.js 1.6.0-beta.1.0.canary.10766 → 1.6.0-beta.1.0.canary.10768

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.
@@ -400,7 +400,7 @@ function enableLogs(debugConfig, context, id) {
400
400
  // Some browsers don't allow to use bind on console object anyway
401
401
  // fallback to default if needed
402
402
  try {
403
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10766"}`);
403
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10768"}`);
404
404
  } catch (e) {
405
405
  /* log fn threw an exception. All logger methods are no-ops. */
406
406
  return createLogger();
@@ -3256,6 +3256,13 @@ class LevelDetails {
3256
3256
  }
3257
3257
  return this.endSN;
3258
3258
  }
3259
+ get expired() {
3260
+ if (this.live && this.age) {
3261
+ const playlistWindowDuration = this.partEnd - this.fragmentStart;
3262
+ return this.age > Math.max(playlistWindowDuration, this.totalduration) + this.levelTargetDuration;
3263
+ }
3264
+ return false;
3265
+ }
3259
3266
  }
3260
3267
 
3261
3268
  var DecrypterAesMode = {
@@ -7836,6 +7843,10 @@ class BaseStreamController extends TaskLoop {
7836
7843
  details.deltaUpdateFailed = true;
7837
7844
  }
7838
7845
  }
7846
+ waitForLive(levelInfo) {
7847
+ const details = levelInfo.details;
7848
+ return (details == null ? void 0 : details.live) && details.type !== 'EVENT' && (this.levelLastLoaded !== levelInfo || details.expired);
7849
+ }
7839
7850
  flushMainBuffer(startOffset, endOffset, type = null) {
7840
7851
  if (!(startOffset - endOffset)) {
7841
7852
  return;
@@ -8192,7 +8203,7 @@ class BaseStreamController extends TaskLoop {
8192
8203
  part: partIndex
8193
8204
  } = chunkMeta;
8194
8205
  if (!(levels != null && levels[levelIndex])) {
8195
- this.warn(`Levels object was unset while buffering fragment ${sn} of level ${levelIndex}. The current chunk will not be buffered.`);
8206
+ this.warn(`Levels object was unset while buffering fragment ${sn} of ${this.playlistLabel()} ${levelIndex}. The current chunk will not be buffered.`);
8196
8207
  return null;
8197
8208
  }
8198
8209
  const level = levels[levelIndex];
@@ -8581,6 +8592,7 @@ class BaseStreamController extends TaskLoop {
8581
8592
  // Leave this.startPosition at -1, so that we can use `getInitialLiveFragment` logic when startPosition has
8582
8593
  // not been specified via the config or an as an argument to startLoad (#3736).
8583
8594
  startPosition = this.hls.liveSyncPosition || sliding;
8595
+ this.startPosition = -1;
8584
8596
  } else {
8585
8597
  this.log(`setting startPosition to 0 by default`);
8586
8598
  this.startPosition = startPosition = 0;
@@ -8603,8 +8615,8 @@ class BaseStreamController extends TaskLoop {
8603
8615
  return pos;
8604
8616
  }
8605
8617
  handleFragLoadAborted(frag, part) {
8606
- if (this.transmuxer && isMediaFragment(frag) && frag.stats.aborted) {
8607
- this.warn(`Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of level ${frag.level} was aborted`);
8618
+ if (this.transmuxer && frag.type === this.playlistType && isMediaFragment(frag) && frag.stats.aborted) {
8619
+ this.warn(`Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of ${this.playlistLabel()} ${frag.level} was aborted`);
8608
8620
  this.resetFragmentLoading(frag);
8609
8621
  }
8610
8622
  }
@@ -8755,7 +8767,7 @@ class BaseStreamController extends TaskLoop {
8755
8767
  }
8756
8768
  }
8757
8769
  resetWhenMissingContext(chunkMeta) {
8758
- this.warn(`The loading context changed while buffering fragment ${chunkMeta.sn} of level ${chunkMeta.level}. This chunk will not be buffered.`);
8770
+ this.warn(`The loading context changed while buffering fragment ${chunkMeta.sn} of ${this.playlistLabel()} ${chunkMeta.level}. This chunk will not be buffered.`);
8759
8771
  this.removeUnbufferedFrags();
8760
8772
  this.resetStartWhenNotLoaded(this.levelLastLoaded);
8761
8773
  this.resetLoadingState();
@@ -8796,7 +8808,7 @@ class BaseStreamController extends TaskLoop {
8796
8808
  return result;
8797
8809
  }, false);
8798
8810
  if (!parsed && ((_this$transmuxer = this.transmuxer) == null ? void 0 : _this$transmuxer.error) === null) {
8799
- const error = new Error(`Found no media in fragment ${frag.sn} of level ${frag.level} resetting transmuxer to fallback to playlist timing`);
8811
+ const error = new Error(`Found no media in fragment ${frag.sn} of ${this.playlistLabel()} ${frag.level} resetting transmuxer to fallback to playlist timing`);
8800
8812
  if (level.fragmentError === 0) {
8801
8813
  // Mark and track the odd empty segment as a gap to avoid reloading
8802
8814
  this.treatAsGap(frag, level);
@@ -8808,7 +8820,7 @@ class BaseStreamController extends TaskLoop {
8808
8820
  fatal: false,
8809
8821
  error,
8810
8822
  frag,
8811
- reason: `Found no media in msn ${frag.sn} of level "${level.url}"`
8823
+ reason: `Found no media in msn ${frag.sn} of ${this.playlistLabel()} "${level.url}"`
8812
8824
  });
8813
8825
  if (!this.hls) {
8814
8826
  return;
@@ -18666,7 +18678,9 @@ class LevelController extends BasePlaylistController {
18666
18678
  }
18667
18679
  }
18668
18680
  const pathwayId = currentLevel.attrs['PATHWAY-ID'];
18669
- this.log(`Loading level index ${currentLevelIndex}${(hlsUrlParameters == null ? void 0 : hlsUrlParameters.msn) !== undefined ? ' at sn ' + hlsUrlParameters.msn + ' part ' + hlsUrlParameters.part : ''} with${pathwayId ? ' Pathway ' + pathwayId : ''} ${url}`);
18681
+ const details = currentLevel.details;
18682
+ const age = details == null ? void 0 : details.age;
18683
+ this.log(`Loading level index ${currentLevelIndex}${(hlsUrlParameters == null ? void 0 : hlsUrlParameters.msn) !== undefined ? ' at sn ' + hlsUrlParameters.msn + ' part ' + hlsUrlParameters.part : ''}${pathwayId ? ' Pathway ' + pathwayId : ''}${age && details.live ? ' age ' + age.toFixed(1) + (details.type ? ' ' + details.type || '' : '') : ''} ${url}`);
18670
18684
 
18671
18685
  // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);
18672
18686
  // console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level);
@@ -19099,7 +19113,7 @@ class GapController extends Logger {
19099
19113
  }
19100
19114
  }
19101
19115
 
19102
- const version = "1.6.0-beta.1.0.canary.10766";
19116
+ const version = "1.6.0-beta.1.0.canary.10768";
19103
19117
 
19104
19118
  // ensure the worker ends up in the bundle
19105
19119
  // If the worker should not be included this gets aliased to empty.js
@@ -19618,7 +19632,7 @@ class StreamController extends BaseStreamController {
19618
19632
  this._hasEnoughToStart = false;
19619
19633
  }
19620
19634
  // if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime
19621
- if (lastCurrentTime > 0 && startPosition === -1) {
19635
+ if (lastCurrentTime > 0 && startPosition === -1 && !skipSeekToStartPosition) {
19622
19636
  this.log(`Override startPosition with lastCurrentTime @${lastCurrentTime.toFixed(3)}`);
19623
19637
  startPosition = lastCurrentTime;
19624
19638
  }
@@ -19645,7 +19659,7 @@ class StreamController extends BaseStreamController {
19645
19659
  } = this;
19646
19660
  const currentLevel = levels == null ? void 0 : levels[level];
19647
19661
  const details = currentLevel == null ? void 0 : currentLevel.details;
19648
- if (details && (!details.live || this.levelLastLoaded === currentLevel)) {
19662
+ if (details && (!details.live || this.levelLastLoaded === currentLevel && !this.waitForLive(currentLevel))) {
19649
19663
  if (this.waitForCdnTuneIn(details)) {
19650
19664
  break;
19651
19665
  }
@@ -19739,9 +19753,10 @@ class StreamController extends BaseStreamController {
19739
19753
  // if level info not retrieved yet, switch state and wait for level retrieval
19740
19754
  // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load
19741
19755
  // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist)
19742
- if (!levelDetails || this.state === State.WAITING_LEVEL || levelDetails.live && this.levelLastLoaded !== levelInfo) {
19756
+ if (!levelDetails || this.state === State.WAITING_LEVEL || this.waitForLive(levelInfo)) {
19743
19757
  this.level = level;
19744
19758
  this.state = State.WAITING_LEVEL;
19759
+ this.startFragRequested = false;
19745
19760
  return;
19746
19761
  }
19747
19762
  const bufferLen = bufferInfo.len;
@@ -19991,7 +20006,7 @@ class StreamController extends BaseStreamController {
19991
20006
  return;
19992
20007
  }
19993
20008
  const level = data.levelInfo;
19994
- if (!level.details || level.details.live && this.levelLastLoaded !== level || this.waitForCdnTuneIn(level.details)) {
20009
+ if (!level.details || level.details.live && (this.levelLastLoaded !== level || level.details.expired) || this.waitForCdnTuneIn(level.details)) {
19995
20010
  this.state = State.WAITING_LEVEL;
19996
20011
  }
19997
20012
  }
@@ -21226,13 +21241,18 @@ class PlaylistLoader {
21226
21241
  // Check if a loader for this context already exists
21227
21242
  let loader = this.getInternalLoader(context);
21228
21243
  if (loader) {
21244
+ const logger = this.hls.logger;
21229
21245
  const loaderContext = loader.context;
21230
- if (loaderContext && loaderContext.url === context.url && loaderContext.levelOrTrack === context.levelOrTrack) {
21231
- // same URL can't overlap
21232
- this.hls.logger.trace('[playlist-loader]: playlist request ongoing');
21246
+ if (loaderContext && loaderContext.levelOrTrack === context.levelOrTrack && (loaderContext.url === context.url || loaderContext.deliveryDirectives && !context.deliveryDirectives)) {
21247
+ // same URL can't overlap, or wait for blocking request
21248
+ if (loaderContext.url === context.url) {
21249
+ logger.log(`[playlist-loader]: playlist request ongoing`);
21250
+ } else {
21251
+ logger.log(`[playlist-loader]: ignore ${context.url} in favor of ${loaderContext.url}`);
21252
+ }
21233
21253
  return;
21234
21254
  }
21235
- this.hls.logger.log(`[playlist-loader]: aborting previous loader for type: ${context.type}`);
21255
+ logger.log(`[playlist-loader]: aborting previous loader for type: ${context.type}`);
21236
21256
  loader.abort();
21237
21257
  }
21238
21258
 
@@ -21942,6 +21962,10 @@ class Hls {
21942
21962
  return;
21943
21963
  }
21944
21964
  this.logger.log(`attachMedia`);
21965
+ if (this._media) {
21966
+ this.logger.warn(`media must be detached before attaching`);
21967
+ this.detachMedia();
21968
+ }
21945
21969
  const attachMediaSource = 'media' in data;
21946
21970
  const media = attachMediaSource ? data.media : data;
21947
21971
  const attachingData = attachMediaSource ? data : {