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

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.10764"}`);
403
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10766"}`);
404
404
  } catch (e) {
405
405
  /* log fn threw an exception. All logger methods are no-ops. */
406
406
  return createLogger();
@@ -2856,6 +2856,10 @@ class BaseSegment {
2856
2856
  elementaryStreams[ElementaryStreamTypes.AUDIOVIDEO] = null;
2857
2857
  }
2858
2858
  }
2859
+ function isMediaFragment(frag) {
2860
+ return frag.sn !== 'initSegment';
2861
+ }
2862
+
2859
2863
  /**
2860
2864
  * Object representing parsed data from an HLS Segment. Found in {@link hls.js#LevelDetails.fragments}.
2861
2865
  */
@@ -3009,7 +3013,7 @@ class Fragment extends BaseSegment {
3009
3013
  this._programDateTime = value;
3010
3014
  }
3011
3015
  get ref() {
3012
- if (this.sn === 'initSegment') {
3016
+ if (!isMediaFragment(this)) {
3013
3017
  return null;
3014
3018
  }
3015
3019
  if (!this._ref) {
@@ -7924,7 +7928,7 @@ class BaseStreamController extends TaskLoop {
7924
7928
  fragBufferedComplete(frag, part) {
7925
7929
  const media = this.mediaBuffer ? this.mediaBuffer : this.media;
7926
7930
  this.log(`Buffered ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag, false, part)} > buffer:${media ? TimeRanges.toString(BufferHelper.getBuffered(media)) : '(detached)'})`);
7927
- if (frag.sn !== 'initSegment') {
7931
+ if (isMediaFragment(frag)) {
7928
7932
  var _this$levels;
7929
7933
  if (frag.type !== PlaylistLevelType.SUBTITLE) {
7930
7934
  const el = frag.elementaryStreams;
@@ -7993,7 +7997,7 @@ class BaseStreamController extends TaskLoop {
7993
7997
  this.keyLoader.loadClear(frag, details.encryptedFragments);
7994
7998
  }
7995
7999
  const fragPrevious = this.fragPrevious;
7996
- if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
8000
+ if (isMediaFragment(frag) && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
7997
8001
  const shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
7998
8002
  if (shouldLoadParts !== this.loadingParts) {
7999
8003
  this.log(`LL-Part loading ${shouldLoadParts ? 'ON' : 'OFF'} loading sn ${fragPrevious == null ? void 0 : fragPrevious.sn}->${frag.sn}`);
@@ -8001,7 +8005,7 @@ class BaseStreamController extends TaskLoop {
8001
8005
  }
8002
8006
  }
8003
8007
  targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
8004
- if (this.loadingParts && frag.sn !== 'initSegment') {
8008
+ if (this.loadingParts && isMediaFragment(frag)) {
8005
8009
  const partList = details.partList;
8006
8010
  if (partList && progressCallback) {
8007
8011
  if (targetBufferTime > frag.end && details.fragmentHint) {
@@ -8040,7 +8044,7 @@ class BaseStreamController extends TaskLoop {
8040
8044
  }
8041
8045
  }
8042
8046
  }
8043
- if (frag.sn !== 'initSegment' && this.loadingParts) {
8047
+ if (isMediaFragment(frag) && this.loadingParts) {
8044
8048
  this.log(`LL-Part loading OFF after next part miss @${targetBufferTime.toFixed(2)}`);
8045
8049
  this.loadingParts = false;
8046
8050
  } else if (!frag.url) {
@@ -8599,7 +8603,7 @@ class BaseStreamController extends TaskLoop {
8599
8603
  return pos;
8600
8604
  }
8601
8605
  handleFragLoadAborted(frag, part) {
8602
- if (this.transmuxer && frag.sn !== 'initSegment' && frag.stats.aborted) {
8606
+ if (this.transmuxer && isMediaFragment(frag) && frag.stats.aborted) {
8603
8607
  this.warn(`Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of level ${frag.level} was aborted`);
8604
8608
  this.resetFragmentLoading(frag);
8605
8609
  }
@@ -8634,10 +8638,18 @@ class BaseStreamController extends TaskLoop {
8634
8638
  const errorAction = data.errorAction;
8635
8639
  const {
8636
8640
  action,
8641
+ flags,
8637
8642
  retryCount = 0,
8638
8643
  retryConfig
8639
8644
  } = errorAction || {};
8640
- if (errorAction && action === NetworkErrorAction.RetryRequest && retryConfig) {
8645
+ const couldRetry = !!errorAction && !!retryConfig;
8646
+ const retry = couldRetry && action === NetworkErrorAction.RetryRequest;
8647
+ const noAlternate = couldRetry && !errorAction.resolved && flags === ErrorActionFlags.MoveAllAlternatesMatchingHost;
8648
+ if (!retry && noAlternate && isMediaFragment(frag) && !frag.endList) {
8649
+ this.resetFragmentErrors(filterType);
8650
+ this.treatAsGap(frag);
8651
+ errorAction.resolved = true;
8652
+ } else if ((retry || noAlternate) && retryCount < retryConfig.maxNumRetry) {
8641
8653
  this.resetStartWhenNotLoaded(this.levelLastLoaded);
8642
8654
  const delay = getRetryDelay(retryConfig, retryCount);
8643
8655
  this.warn(`Fragment ${frag.sn} of ${filterType} ${frag.level} errored with ${data.details}, retrying loading ${retryCount + 1}/${retryConfig.maxNumRetry} in ${delay}ms`);
@@ -8655,7 +8667,7 @@ class BaseStreamController extends TaskLoop {
8655
8667
  this.warn(`${data.details} reached or exceeded max retry (${retryCount})`);
8656
8668
  return;
8657
8669
  }
8658
- } else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
8670
+ } else if (action === NetworkErrorAction.SendAlternateToPenaltyBox) {
8659
8671
  this.state = State.WAITING_LEVEL;
8660
8672
  } else {
8661
8673
  this.state = State.ERROR;
@@ -8787,10 +8799,7 @@ class BaseStreamController extends TaskLoop {
8787
8799
  const error = new Error(`Found no media in fragment ${frag.sn} of level ${frag.level} resetting transmuxer to fallback to playlist timing`);
8788
8800
  if (level.fragmentError === 0) {
8789
8801
  // Mark and track the odd empty segment as a gap to avoid reloading
8790
- level.fragmentError++;
8791
- frag.gap = true;
8792
- this.fragmentTracker.removeFragment(frag);
8793
- this.fragmentTracker.fragBuffered(frag, true);
8802
+ this.treatAsGap(frag, level);
8794
8803
  }
8795
8804
  this.warn(error.message);
8796
8805
  this.hls.trigger(Events.ERROR, {
@@ -8821,6 +8830,14 @@ class BaseStreamController extends TaskLoop {
8821
8830
  var _ref, _ref2;
8822
8831
  return `${this.playlistLabel()} ${frag.level} (${part ? 'part' : 'frag'}:[${((_ref = pts && !part ? frag.startPTS : (part || frag).start) != null ? _ref : NaN).toFixed(3)}-${((_ref2 = pts && !part ? frag.endPTS : (part || frag).end) != null ? _ref2 : NaN).toFixed(3)}]${part && frag.type === 'main' ? 'INDEPENDENT=' + (part.independent ? 'YES' : 'NO') : ''}`;
8823
8832
  }
8833
+ treatAsGap(frag, level) {
8834
+ if (level) {
8835
+ level.fragmentError++;
8836
+ }
8837
+ frag.gap = true;
8838
+ this.fragmentTracker.removeFragment(frag);
8839
+ this.fragmentTracker.fragBuffered(frag, true);
8840
+ }
8824
8841
  resetTransmuxer() {
8825
8842
  var _this$transmuxer2;
8826
8843
  (_this$transmuxer2 = this.transmuxer) == null ? void 0 : _this$transmuxer2.reset();
@@ -18608,7 +18625,7 @@ class LevelController extends BasePlaylistController {
18608
18625
  level,
18609
18626
  details
18610
18627
  } = data;
18611
- const curLevel = this._levels[level];
18628
+ const curLevel = data.levelInfo;
18612
18629
  if (!curLevel) {
18613
18630
  var _data$deliveryDirecti;
18614
18631
  this.warn(`Invalid level index ${level}`);
@@ -18619,7 +18636,7 @@ class LevelController extends BasePlaylistController {
18619
18636
  }
18620
18637
 
18621
18638
  // only process level loaded events matching with expected level
18622
- if (level === this.currentLevelIndex) {
18639
+ if (curLevel === this.currentLevel) {
18623
18640
  // reset level load error counter on successful level loaded only if there is no issues with fragments
18624
18641
  if (curLevel.fragmentError === 0) {
18625
18642
  curLevel.loadError = 0;
@@ -18657,6 +18674,7 @@ class LevelController extends BasePlaylistController {
18657
18674
  this.hls.trigger(Events.LEVEL_LOADING, {
18658
18675
  url,
18659
18676
  level: currentLevelIndex,
18677
+ levelInfo: currentLevel,
18660
18678
  pathwayId: currentLevel.attrs['PATHWAY-ID'],
18661
18679
  id: 0,
18662
18680
  // Deprecated Level urlId
@@ -19081,7 +19099,7 @@ class GapController extends Logger {
19081
19099
  }
19082
19100
  }
19083
19101
 
19084
- const version = "1.6.0-beta.1.0.canary.10764";
19102
+ const version = "1.6.0-beta.1.0.canary.10766";
19085
19103
 
19086
19104
  // ensure the worker ends up in the bundle
19087
19105
  // If the worker should not be included this gets aliased to empty.js
@@ -19741,7 +19759,7 @@ class StreamController extends BaseStreamController {
19741
19759
  const targetBufferTime = this.backtrackFragment ? this.backtrackFragment.start : bufferInfo.end;
19742
19760
  let frag = this.getNextFragment(targetBufferTime, levelDetails);
19743
19761
  // Avoid backtracking by loading an earlier segment in streams with segments that do not start with a key frame (flagged by `couldBacktrack`)
19744
- if (this.couldBacktrack && !this.fragPrevious && frag && frag.sn !== 'initSegment' && this.fragmentTracker.getState(frag) !== FragmentState.OK) {
19762
+ if (this.couldBacktrack && !this.fragPrevious && frag && isMediaFragment(frag) && this.fragmentTracker.getState(frag) !== FragmentState.OK) {
19745
19763
  var _this$backtrackFragme;
19746
19764
  const backtrackSn = ((_this$backtrackFragme = this.backtrackFragment) != null ? _this$backtrackFragme : frag).sn;
19747
19765
  const fragIdx = backtrackSn - levelDetails.startSN;
@@ -19778,7 +19796,7 @@ class StreamController extends BaseStreamController {
19778
19796
  // Check if fragment is not loaded
19779
19797
  const fragState = this.fragmentTracker.getState(frag);
19780
19798
  if (fragState === FragmentState.NOT_LOADED || fragState === FragmentState.PARTIAL) {
19781
- if (frag.sn === 'initSegment') {
19799
+ if (!isMediaFragment(frag)) {
19782
19800
  this._loadInitSegment(frag, level);
19783
19801
  } else if (this.bitrateTest) {
19784
19802
  this.log(`Fragment ${frag.sn} of level ${frag.level} is being downloaded to test bitrate and will not be buffered`);
@@ -19972,7 +19990,7 @@ class StreamController extends BaseStreamController {
19972
19990
  if (!levels || this.state !== State.IDLE) {
19973
19991
  return;
19974
19992
  }
19975
- const level = levels[data.level];
19993
+ const level = data.levelInfo;
19976
19994
  if (!level.details || level.details.live && this.levelLastLoaded !== level || this.waitForCdnTuneIn(level.details)) {
19977
19995
  this.state = State.WAITING_LEVEL;
19978
19996
  }
@@ -19991,7 +20009,7 @@ class StreamController extends BaseStreamController {
19991
20009
  return;
19992
20010
  }
19993
20011
  this.log(`Level ${newLevelId} loaded [${newDetails.startSN},${newDetails.endSN}]${newDetails.lastPartSn ? `[part-${newDetails.lastPartSn}-${newDetails.lastPartIndex}]` : ''}, cc [${newDetails.startCC}, ${newDetails.endCC}] duration:${duration}`);
19994
- const curLevel = levels[newLevelId];
20012
+ const curLevel = data.levelInfo;
19995
20013
  const fragCurrent = this.fragCurrent;
19996
20014
  if (fragCurrent && (this.state === State.FRAG_LOADING || this.state === State.FRAG_LOADING_WAITING_RETRY)) {
19997
20015
  if (fragCurrent.level !== data.level && fragCurrent.loader) {
@@ -20204,7 +20222,7 @@ class StreamController extends BaseStreamController {
20204
20222
  }
20205
20223
  const stats = part ? part.stats : frag.stats;
20206
20224
  this.fragLastKbps = Math.round(8 * stats.total / (stats.buffering.end - stats.loading.first));
20207
- if (frag.sn !== 'initSegment') {
20225
+ if (isMediaFragment(frag)) {
20208
20226
  this.fragPrevious = frag;
20209
20227
  }
20210
20228
  this.fragBufferedComplete(frag, part);
@@ -21064,6 +21082,7 @@ class PlaylistLoader {
21064
21082
  hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
21065
21083
  hls.on(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);
21066
21084
  hls.on(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);
21085
+ hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
21067
21086
  }
21068
21087
  unregisterListeners() {
21069
21088
  const {
@@ -21073,6 +21092,7 @@ class PlaylistLoader {
21073
21092
  hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);
21074
21093
  hls.off(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);
21075
21094
  hls.off(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);
21095
+ hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
21076
21096
  }
21077
21097
 
21078
21098
  /**
@@ -21124,7 +21144,8 @@ class PlaylistLoader {
21124
21144
  responseType: 'text',
21125
21145
  type: PlaylistContextType.MANIFEST,
21126
21146
  url,
21127
- deliveryDirectives: null
21147
+ deliveryDirectives: null,
21148
+ levelOrTrack: null
21128
21149
  });
21129
21150
  }
21130
21151
  onLevelLoading(event, data) {
@@ -21133,7 +21154,8 @@ class PlaylistLoader {
21133
21154
  level,
21134
21155
  pathwayId,
21135
21156
  url,
21136
- deliveryDirectives
21157
+ deliveryDirectives,
21158
+ levelInfo
21137
21159
  } = data;
21138
21160
  this.load({
21139
21161
  id,
@@ -21142,7 +21164,8 @@ class PlaylistLoader {
21142
21164
  responseType: 'text',
21143
21165
  type: PlaylistContextType.LEVEL,
21144
21166
  url,
21145
- deliveryDirectives
21167
+ deliveryDirectives,
21168
+ levelOrTrack: levelInfo
21146
21169
  });
21147
21170
  }
21148
21171
  onAudioTrackLoading(event, data) {
@@ -21150,7 +21173,8 @@ class PlaylistLoader {
21150
21173
  id,
21151
21174
  groupId,
21152
21175
  url,
21153
- deliveryDirectives
21176
+ deliveryDirectives,
21177
+ track
21154
21178
  } = data;
21155
21179
  this.load({
21156
21180
  id,
@@ -21159,7 +21183,8 @@ class PlaylistLoader {
21159
21183
  responseType: 'text',
21160
21184
  type: PlaylistContextType.AUDIO_TRACK,
21161
21185
  url,
21162
- deliveryDirectives
21186
+ deliveryDirectives,
21187
+ levelOrTrack: track
21163
21188
  });
21164
21189
  }
21165
21190
  onSubtitleTrackLoading(event, data) {
@@ -21167,7 +21192,8 @@ class PlaylistLoader {
21167
21192
  id,
21168
21193
  groupId,
21169
21194
  url,
21170
- deliveryDirectives
21195
+ deliveryDirectives,
21196
+ track
21171
21197
  } = data;
21172
21198
  this.load({
21173
21199
  id,
@@ -21176,9 +21202,21 @@ class PlaylistLoader {
21176
21202
  responseType: 'text',
21177
21203
  type: PlaylistContextType.SUBTITLE_TRACK,
21178
21204
  url,
21179
- deliveryDirectives
21205
+ deliveryDirectives,
21206
+ levelOrTrack: track
21180
21207
  });
21181
21208
  }
21209
+ onLevelsUpdated(event, data) {
21210
+ // abort and delete loader of removed levels
21211
+ const loader = this.loaders[PlaylistContextType.LEVEL];
21212
+ if (loader) {
21213
+ const context = loader.context;
21214
+ if (context && !data.levels.some(lvl => lvl === context.levelOrTrack)) {
21215
+ loader.abort();
21216
+ delete this.loaders[PlaylistContextType.LEVEL];
21217
+ }
21218
+ }
21219
+ }
21182
21220
  load(context) {
21183
21221
  var _context$deliveryDire;
21184
21222
  const config = this.hls.config;
@@ -21189,7 +21227,7 @@ class PlaylistLoader {
21189
21227
  let loader = this.getInternalLoader(context);
21190
21228
  if (loader) {
21191
21229
  const loaderContext = loader.context;
21192
- if (loaderContext && loaderContext.url === context.url && loaderContext.level === context.level) {
21230
+ if (loaderContext && loaderContext.url === context.url && loaderContext.levelOrTrack === context.levelOrTrack) {
21193
21231
  // same URL can't overlap
21194
21232
  this.hls.logger.trace('[playlist-loader]: playlist request ongoing');
21195
21233
  return;
@@ -21511,6 +21549,7 @@ class PlaylistLoader {
21511
21549
  case PlaylistContextType.LEVEL:
21512
21550
  hls.trigger(Events.LEVEL_LOADED, {
21513
21551
  details: levelDetails,
21552
+ levelInfo: context.levelOrTrack || hls.levels[0],
21514
21553
  level: levelIndex || 0,
21515
21554
  id: id || 0,
21516
21555
  stats,
@@ -21521,6 +21560,7 @@ class PlaylistLoader {
21521
21560
  case PlaylistContextType.AUDIO_TRACK:
21522
21561
  hls.trigger(Events.AUDIO_TRACK_LOADED, {
21523
21562
  details: levelDetails,
21563
+ track: context.levelOrTrack,
21524
21564
  id: id || 0,
21525
21565
  groupId: groupId || '',
21526
21566
  stats,
@@ -21531,6 +21571,7 @@ class PlaylistLoader {
21531
21571
  case PlaylistContextType.SUBTITLE_TRACK:
21532
21572
  hls.trigger(Events.SUBTITLE_TRACK_LOADED, {
21533
21573
  details: levelDetails,
21574
+ track: context.levelOrTrack,
21534
21575
  id: id || 0,
21535
21576
  groupId: groupId || '',
21536
21577
  stats,