hls.js 1.6.0-beta.1.0.canary.10767 → 1.6.0-beta.1.0.canary.10770

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
@@ -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.10767"}`);
403
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10770"}`);
404
404
  } catch (e) {
405
405
  /* log fn threw an exception. All logger methods are no-ops. */
406
406
  return createLogger();
@@ -6399,6 +6399,13 @@ class LevelDetails {
6399
6399
  }
6400
6400
  return this.endSN;
6401
6401
  }
6402
+ get expired() {
6403
+ if (this.live && this.age) {
6404
+ const playlistWindowDuration = this.partEnd - this.fragmentStart;
6405
+ return this.age > Math.max(playlistWindowDuration, this.totalduration) + this.levelTargetDuration;
6406
+ }
6407
+ return false;
6408
+ }
6402
6409
  }
6403
6410
 
6404
6411
  function isFullSegmentEncryption(method) {
@@ -8378,6 +8385,10 @@ class BaseStreamController extends TaskLoop {
8378
8385
  details.deltaUpdateFailed = true;
8379
8386
  }
8380
8387
  }
8388
+ waitForLive(levelInfo) {
8389
+ const details = levelInfo.details;
8390
+ return (details == null ? void 0 : details.live) && details.type !== 'EVENT' && (this.levelLastLoaded !== levelInfo || details.expired);
8391
+ }
8381
8392
  flushMainBuffer(startOffset, endOffset, type = null) {
8382
8393
  if (!(startOffset - endOffset)) {
8383
8394
  return;
@@ -8734,7 +8745,7 @@ class BaseStreamController extends TaskLoop {
8734
8745
  part: partIndex
8735
8746
  } = chunkMeta;
8736
8747
  if (!(levels != null && levels[levelIndex])) {
8737
- this.warn(`Levels object was unset while buffering fragment ${sn} of level ${levelIndex}. The current chunk will not be buffered.`);
8748
+ this.warn(`Levels object was unset while buffering fragment ${sn} of ${this.playlistLabel()} ${levelIndex}. The current chunk will not be buffered.`);
8738
8749
  return null;
8739
8750
  }
8740
8751
  const level = levels[levelIndex];
@@ -9123,6 +9134,7 @@ class BaseStreamController extends TaskLoop {
9123
9134
  // Leave this.startPosition at -1, so that we can use `getInitialLiveFragment` logic when startPosition has
9124
9135
  // not been specified via the config or an as an argument to startLoad (#3736).
9125
9136
  startPosition = this.hls.liveSyncPosition || sliding;
9137
+ this.startPosition = -1;
9126
9138
  } else {
9127
9139
  this.log(`setting startPosition to 0 by default`);
9128
9140
  this.startPosition = startPosition = 0;
@@ -9145,8 +9157,8 @@ class BaseStreamController extends TaskLoop {
9145
9157
  return pos;
9146
9158
  }
9147
9159
  handleFragLoadAborted(frag, part) {
9148
- if (this.transmuxer && isMediaFragment(frag) && frag.stats.aborted) {
9149
- this.warn(`Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of level ${frag.level} was aborted`);
9160
+ if (this.transmuxer && frag.type === this.playlistType && isMediaFragment(frag) && frag.stats.aborted) {
9161
+ this.warn(`Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of ${this.playlistLabel()} ${frag.level} was aborted`);
9150
9162
  this.resetFragmentLoading(frag);
9151
9163
  }
9152
9164
  }
@@ -9297,7 +9309,7 @@ class BaseStreamController extends TaskLoop {
9297
9309
  }
9298
9310
  }
9299
9311
  resetWhenMissingContext(chunkMeta) {
9300
- this.warn(`The loading context changed while buffering fragment ${chunkMeta.sn} of level ${chunkMeta.level}. This chunk will not be buffered.`);
9312
+ this.warn(`The loading context changed while buffering fragment ${chunkMeta.sn} of ${this.playlistLabel()} ${chunkMeta.level}. This chunk will not be buffered.`);
9301
9313
  this.removeUnbufferedFrags();
9302
9314
  this.resetStartWhenNotLoaded(this.levelLastLoaded);
9303
9315
  this.resetLoadingState();
@@ -9338,7 +9350,7 @@ class BaseStreamController extends TaskLoop {
9338
9350
  return result;
9339
9351
  }, false);
9340
9352
  if (!parsed && ((_this$transmuxer = this.transmuxer) == null ? void 0 : _this$transmuxer.error) === null) {
9341
- const error = new Error(`Found no media in fragment ${frag.sn} of level ${frag.level} resetting transmuxer to fallback to playlist timing`);
9353
+ const error = new Error(`Found no media in fragment ${frag.sn} of ${this.playlistLabel()} ${frag.level} resetting transmuxer to fallback to playlist timing`);
9342
9354
  if (level.fragmentError === 0) {
9343
9355
  // Mark and track the odd empty segment as a gap to avoid reloading
9344
9356
  this.treatAsGap(frag, level);
@@ -9350,7 +9362,7 @@ class BaseStreamController extends TaskLoop {
9350
9362
  fatal: false,
9351
9363
  error,
9352
9364
  frag,
9353
- reason: `Found no media in msn ${frag.sn} of level "${level.url}"`
9365
+ reason: `Found no media in msn ${frag.sn} of ${this.playlistLabel()} "${level.url}"`
9354
9366
  });
9355
9367
  if (!this.hls) {
9356
9368
  return;
@@ -9791,7 +9803,7 @@ var eventemitter3 = {exports: {}};
9791
9803
  var eventemitter3Exports = eventemitter3.exports;
9792
9804
  var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
9793
9805
 
9794
- const version = "1.6.0-beta.1.0.canary.10767";
9806
+ const version = "1.6.0-beta.1.0.canary.10770";
9795
9807
 
9796
9808
  // ensure the worker ends up in the bundle
9797
9809
  // If the worker should not be included this gets aliased to empty.js
@@ -16173,13 +16185,13 @@ class AudioStreamController extends BaseStreamController {
16173
16185
  break;
16174
16186
  case State.WAITING_TRACK:
16175
16187
  {
16176
- var _levels$trackId;
16177
16188
  const {
16178
16189
  levels,
16179
16190
  trackId
16180
16191
  } = this;
16181
- const details = levels == null ? void 0 : (_levels$trackId = levels[trackId]) == null ? void 0 : _levels$trackId.details;
16182
- if (details) {
16192
+ const currenTrack = levels == null ? void 0 : levels[trackId];
16193
+ const details = currenTrack == null ? void 0 : currenTrack.details;
16194
+ if (details && !this.waitForLive(currenTrack)) {
16183
16195
  if (this.waitForCdnTuneIn(details)) {
16184
16196
  break;
16185
16197
  }
@@ -16292,8 +16304,9 @@ class AudioStreamController extends BaseStreamController {
16292
16304
  }
16293
16305
  const levelInfo = levels[trackId];
16294
16306
  const trackDetails = levelInfo.details;
16295
- if (!trackDetails || trackDetails.live && this.levelLastLoaded !== levelInfo || this.waitForCdnTuneIn(trackDetails)) {
16307
+ if (!trackDetails || this.waitForLive(levelInfo) || this.waitForCdnTuneIn(trackDetails)) {
16296
16308
  this.state = State.WAITING_TRACK;
16309
+ this.startFragRequested = false;
16297
16310
  return;
16298
16311
  }
16299
16312
  const bufferable = this.mediaBuffer ? this.mediaBuffer : this.media;
@@ -17395,7 +17408,9 @@ class AudioTrackController extends BasePlaylistController {
17395
17408
  }
17396
17409
  }
17397
17410
  // track not retrieved yet, or live playlist we need to (re)load it
17398
- this.log(`loading audio-track playlist ${id} "${audioTrack.name}" lang:${audioTrack.lang} group:${groupId}`);
17411
+ const details = audioTrack.details;
17412
+ const age = details == null ? void 0 : details.age;
17413
+ this.log(`Loading audio-track ${id} "${audioTrack.name}" lang:${audioTrack.lang} group:${groupId}${(hlsUrlParameters == null ? void 0 : hlsUrlParameters.msn) !== undefined ? ' at sn ' + hlsUrlParameters.msn + ' part ' + hlsUrlParameters.part : ''}${age && details.live ? ' age ' + age.toFixed(1) + (details.type ? ' ' + details.type || '' : '') : ''} ${url}`);
17399
17414
  this.clearTimer();
17400
17415
  this.hls.trigger(Events.AUDIO_TRACK_LOADING, {
17401
17416
  url,
@@ -22438,7 +22453,9 @@ class SubtitleTrackController extends BasePlaylistController {
22438
22453
  this.warn(`Could not construct new URL with HLS Delivery Directives: ${error}`);
22439
22454
  }
22440
22455
  }
22441
- this.log(`Loading subtitle playlist for id ${id}`);
22456
+ const details = currentTrack.details;
22457
+ const age = details == null ? void 0 : details.age;
22458
+ this.log(`Loading subtitle ${id} "${currentTrack.name}" lang:${currentTrack.lang} group:${groupId}${(hlsUrlParameters == null ? void 0 : hlsUrlParameters.msn) !== undefined ? ' at sn ' + hlsUrlParameters.msn + ' part ' + hlsUrlParameters.part : ''}${age && details.live ? ' age ' + age.toFixed(1) + (details.type ? ' ' + details.type || '' : '') : ''} ${url}`);
22442
22459
  this.hls.trigger(Events.SUBTITLE_TRACK_LOADING, {
22443
22460
  url,
22444
22461
  id,
@@ -25528,6 +25545,9 @@ class SubtitleStreamController extends BaseStreamController {
25528
25545
  if (!track || !levels.length || !track.details) {
25529
25546
  return;
25530
25547
  }
25548
+ if (this.waitForLive(track)) {
25549
+ return;
25550
+ }
25531
25551
  const {
25532
25552
  config
25533
25553
  } = this;
@@ -30560,7 +30580,9 @@ class LevelController extends BasePlaylistController {
30560
30580
  }
30561
30581
  }
30562
30582
  const pathwayId = currentLevel.attrs['PATHWAY-ID'];
30563
- 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}`);
30583
+ const details = currentLevel.details;
30584
+ const age = details == null ? void 0 : details.age;
30585
+ 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}`);
30564
30586
 
30565
30587
  // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);
30566
30588
  // console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level);
@@ -31130,7 +31152,7 @@ class StreamController extends BaseStreamController {
31130
31152
  this._hasEnoughToStart = false;
31131
31153
  }
31132
31154
  // if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime
31133
- if (lastCurrentTime > 0 && startPosition === -1) {
31155
+ if (lastCurrentTime > 0 && startPosition === -1 && !skipSeekToStartPosition) {
31134
31156
  this.log(`Override startPosition with lastCurrentTime @${lastCurrentTime.toFixed(3)}`);
31135
31157
  startPosition = lastCurrentTime;
31136
31158
  }
@@ -31157,7 +31179,7 @@ class StreamController extends BaseStreamController {
31157
31179
  } = this;
31158
31180
  const currentLevel = levels == null ? void 0 : levels[level];
31159
31181
  const details = currentLevel == null ? void 0 : currentLevel.details;
31160
- if (details && (!details.live || this.levelLastLoaded === currentLevel)) {
31182
+ if (details && (!details.live || this.levelLastLoaded === currentLevel && !this.waitForLive(currentLevel))) {
31161
31183
  if (this.waitForCdnTuneIn(details)) {
31162
31184
  break;
31163
31185
  }
@@ -31251,9 +31273,10 @@ class StreamController extends BaseStreamController {
31251
31273
  // if level info not retrieved yet, switch state and wait for level retrieval
31252
31274
  // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load
31253
31275
  // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist)
31254
- if (!levelDetails || this.state === State.WAITING_LEVEL || levelDetails.live && this.levelLastLoaded !== levelInfo) {
31276
+ if (!levelDetails || this.state === State.WAITING_LEVEL || this.waitForLive(levelInfo)) {
31255
31277
  this.level = level;
31256
31278
  this.state = State.WAITING_LEVEL;
31279
+ this.startFragRequested = false;
31257
31280
  return;
31258
31281
  }
31259
31282
  const bufferLen = bufferInfo.len;
@@ -31503,7 +31526,7 @@ class StreamController extends BaseStreamController {
31503
31526
  return;
31504
31527
  }
31505
31528
  const level = data.levelInfo;
31506
- if (!level.details || level.details.live && this.levelLastLoaded !== level || this.waitForCdnTuneIn(level.details)) {
31529
+ if (!level.details || level.details.live && (this.levelLastLoaded !== level || level.details.expired) || this.waitForCdnTuneIn(level.details)) {
31507
31530
  this.state = State.WAITING_LEVEL;
31508
31531
  }
31509
31532
  }
@@ -32738,13 +32761,18 @@ class PlaylistLoader {
32738
32761
  // Check if a loader for this context already exists
32739
32762
  let loader = this.getInternalLoader(context);
32740
32763
  if (loader) {
32764
+ const logger = this.hls.logger;
32741
32765
  const loaderContext = loader.context;
32742
- if (loaderContext && loaderContext.url === context.url && loaderContext.levelOrTrack === context.levelOrTrack) {
32743
- // same URL can't overlap
32744
- this.hls.logger.trace('[playlist-loader]: playlist request ongoing');
32766
+ if (loaderContext && loaderContext.levelOrTrack === context.levelOrTrack && (loaderContext.url === context.url || loaderContext.deliveryDirectives && !context.deliveryDirectives)) {
32767
+ // same URL can't overlap, or wait for blocking request
32768
+ if (loaderContext.url === context.url) {
32769
+ logger.log(`[playlist-loader]: playlist request ongoing`);
32770
+ } else {
32771
+ logger.log(`[playlist-loader]: ignore ${context.url} in favor of ${loaderContext.url}`);
32772
+ }
32745
32773
  return;
32746
32774
  }
32747
- this.hls.logger.log(`[playlist-loader]: aborting previous loader for type: ${context.type}`);
32775
+ logger.log(`[playlist-loader]: aborting previous loader for type: ${context.type}`);
32748
32776
  loader.abort();
32749
32777
  }
32750
32778