hls.js 1.6.0-beta.4.0.canary.11033 → 1.6.0-beta.4.0.canary.11034

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.js CHANGED
@@ -1073,7 +1073,7 @@
1073
1073
  // Some browsers don't allow to use bind on console object anyway
1074
1074
  // fallback to default if needed
1075
1075
  try {
1076
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.6.0-beta.4.0.canary.11033");
1076
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.6.0-beta.4.0.canary.11034");
1077
1077
  } catch (e) {
1078
1078
  /* log fn threw an exception. All logger methods are no-ops. */
1079
1079
  return createLogger();
@@ -3853,8 +3853,8 @@
3853
3853
  This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
3854
3854
  quickly enough to prevent underbuffering
3855
3855
  */
3856
- _this._abandonRulesCheck = function () {
3857
- var _this$hls$latestLevel;
3856
+ _this._abandonRulesCheck = function (levelLoaded) {
3857
+ var _ref;
3858
3858
  var _this2 = _this,
3859
3859
  frag = _this2.fragCurrent,
3860
3860
  part = _this2.partCurrent,
@@ -3869,20 +3869,29 @@
3869
3869
  var duration = part ? part.duration : frag.duration;
3870
3870
  var timeLoading = now - stats.loading.start;
3871
3871
  var minAutoLevel = hls.minAutoLevel;
3872
+ var loadingFragForLevel = frag.level;
3873
+ var currentAutoLevel = _this._nextAutoLevel;
3872
3874
  // If frag loading is aborted, complete, or from lowest level, stop timer and return
3873
- if (stats.aborted || stats.loaded && stats.loaded === stats.total || frag.level <= minAutoLevel) {
3875
+ if (stats.aborted || stats.loaded && stats.loaded === stats.total || loadingFragForLevel <= minAutoLevel) {
3874
3876
  _this.clearTimer();
3875
3877
  // reset forced auto level value so that next level will be selected
3876
3878
  _this._nextAutoLevel = -1;
3877
3879
  return;
3878
3880
  }
3879
3881
 
3880
- // This check only runs if we're in ABR mode and actually playing
3881
- if (!autoLevelEnabled || media.paused || !media.playbackRate || !media.readyState) {
3882
+ // This check only runs if we're in ABR mode
3883
+ if (!autoLevelEnabled) {
3884
+ return;
3885
+ }
3886
+
3887
+ // Must be loading/loaded a new level or be in a playing state
3888
+ var fragBlockingSwitch = currentAutoLevel > -1 && currentAutoLevel !== loadingFragForLevel;
3889
+ var levelChange = !!levelLoaded || fragBlockingSwitch;
3890
+ if (!levelChange && (media.paused || !media.playbackRate || !media.readyState)) {
3882
3891
  return;
3883
3892
  }
3884
3893
  var bufferInfo = hls.mainForwardBufferInfo;
3885
- if (bufferInfo === null) {
3894
+ if (!levelChange && bufferInfo === null) {
3886
3895
  return;
3887
3896
  }
3888
3897
  var ttfbEstimate = _this.bwEstimator.getEstimateTTFB();
@@ -3893,12 +3902,12 @@
3893
3902
  }
3894
3903
 
3895
3904
  // bufferStarvationDelay is an estimate of the amount time (in seconds) it will take to exhaust the buffer
3896
- var bufferStarvationDelay = bufferInfo.len / playbackRate;
3905
+ var bufferStarvationDelay = bufferInfo ? bufferInfo.len / playbackRate : 0;
3897
3906
  var ttfb = stats.loading.first ? stats.loading.first - stats.loading.start : -1;
3898
3907
  var loadedFirstByte = stats.loaded && ttfb > -1;
3899
3908
  var bwEstimate = _this.getBwEstimate();
3900
3909
  var levels = hls.levels;
3901
- var level = levels[frag.level];
3910
+ var level = levels[loadingFragForLevel];
3902
3911
  var expectedLen = Math.max(stats.loaded, Math.round(duration * (frag.bitrate || level.averageBitrate) / 8));
3903
3912
  var timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
3904
3913
  if (timeStreaming < 1 && loadedFirstByte) {
@@ -3913,12 +3922,12 @@
3913
3922
  return;
3914
3923
  }
3915
3924
  var bwe = loadRate ? loadRate * 8 : bwEstimate;
3916
- var live = ((_this$hls$latestLevel = _this.hls.latestLevelDetails) == null ? void 0 : _this$hls$latestLevel.live) === true;
3925
+ var live = ((_ref = (levelLoaded == null ? void 0 : levelLoaded.details) || _this.hls.latestLevelDetails) == null ? void 0 : _ref.live) === true;
3917
3926
  var abrBandWidthUpFactor = _this.hls.config.abrBandWidthUpFactor;
3918
3927
  var fragLevelNextLoadedDelay = Number.POSITIVE_INFINITY;
3919
3928
  var nextLoadLevel;
3920
3929
  // Iterate through lower level and try to find the largest one that avoids rebuffering
3921
- for (nextLoadLevel = frag.level - 1; nextLoadLevel > minAutoLevel; nextLoadLevel--) {
3930
+ for (nextLoadLevel = loadingFragForLevel - 1; nextLoadLevel > minAutoLevel; nextLoadLevel--) {
3922
3931
  // compute time to load next fragment at lower level
3923
3932
  // 8 = bits per byte (bps/Bps)
3924
3933
  var levelNextBitrate = levels[nextLoadLevel].maxBitrate;
@@ -3953,10 +3962,10 @@
3953
3962
  if (bestSwitchLevel > -1) {
3954
3963
  nextLoadLevel = bestSwitchLevel;
3955
3964
  }
3956
- _this.warn("Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + frag.level + " is loading too slowly;\n Fragment duration: " + frag.duration.toFixed(3) + "\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for down switch fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n TTFB estimate: " + (ttfb | 0) + " ms\n Current BW estimate: " + (isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown') + " bps\n New BW estimate: " + (_this.getBwEstimate() | 0) + " bps\n Switching to level " + nextLoadLevel + " @ " + (nextLoadLevelBitrate | 0) + " bps");
3965
+ _this.warn("Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + loadingFragForLevel + " is loading too slowly;\n Fragment duration: " + frag.duration.toFixed(3) + "\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for down switch fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n TTFB estimate: " + (ttfb | 0) + " ms\n Current BW estimate: " + (isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown') + " bps\n New BW estimate: " + (_this.getBwEstimate() | 0) + " bps\n Switching to level " + nextLoadLevel + " @ " + (nextLoadLevelBitrate | 0) + " bps");
3957
3966
  hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
3958
3967
  _this.clearTimer();
3959
- _this.timer = self.setInterval(function () {
3968
+ var abortAndSwitch = function abortAndSwitch() {
3960
3969
  // Are nextLoadLevel details available or is stream-controller still in "WAITING_LEVEL" state?
3961
3970
  _this.clearTimer();
3962
3971
  if (_this.fragCurrent === frag && _this.hls.loadLevel === nextLoadLevel && nextLoadLevel > 0) {
@@ -3973,7 +3982,12 @@
3973
3982
  _this.resetEstimator(_this.hls.levels[lowestSwitchLevel].bitrate);
3974
3983
  }
3975
3984
  }
3976
- }, fragLevelNextLoadedDelay * 1000);
3985
+ };
3986
+ if (fragBlockingSwitch || fragLoadedDelay > fragLevelNextLoadedDelay * 2) {
3987
+ abortAndSwitch();
3988
+ } else {
3989
+ _this.timer = self.setInterval(abortAndSwitch, fragLevelNextLoadedDelay * 1000);
3990
+ }
3977
3991
  hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
3978
3992
  frag: frag,
3979
3993
  part: part,
@@ -4105,13 +4119,13 @@
4105
4119
  };
4106
4120
  _proto.getTimeToLoadFrag = function getTimeToLoadFrag(timeToFirstByteSec, bandwidth, fragSizeBits, isSwitch) {
4107
4121
  var fragLoadSec = timeToFirstByteSec + fragSizeBits / bandwidth;
4108
- var playlistLoadSec = isSwitch ? this.lastLevelLoadSec : 0;
4122
+ var playlistLoadSec = isSwitch ? timeToFirstByteSec + this.lastLevelLoadSec : 0;
4109
4123
  return fragLoadSec + playlistLoadSec;
4110
4124
  };
4111
4125
  _proto.onLevelLoaded = function onLevelLoaded(event, data) {
4112
4126
  var config = this.hls.config;
4113
4127
  var loading = data.stats.loading;
4114
- var timeLoadingMs = loading.end - loading.start;
4128
+ var timeLoadingMs = loading.end - loading.first;
4115
4129
  if (isFiniteNumber(timeLoadingMs)) {
4116
4130
  this.lastLevelLoadSec = timeLoadingMs / 1000;
4117
4131
  }
@@ -4120,10 +4134,13 @@
4120
4134
  } else {
4121
4135
  this.bwEstimator.update(config.abrEwmaSlowVoD, config.abrEwmaFastVoD);
4122
4136
  }
4137
+ if (this.timer > -1) {
4138
+ this._abandonRulesCheck(data.levelInfo);
4139
+ }
4123
4140
  };
4124
- _proto.onFragLoaded = function onFragLoaded(event, _ref) {
4125
- var frag = _ref.frag,
4126
- part = _ref.part;
4141
+ _proto.onFragLoaded = function onFragLoaded(event, _ref2) {
4142
+ var frag = _ref2.frag,
4143
+ part = _ref2.part;
4127
4144
  var stats = part ? part.stats : frag.stats;
4128
4145
  if (frag.type === PlaylistLevelType.MAIN) {
4129
4146
  this.bwEstimator.sampleTTFB(stats.loading.first - stats.loading.start);
@@ -4272,7 +4289,7 @@
4272
4289
  return this.bwEstimator.canEstimate() ? this.bwEstimator.getEstimate() : this.hls.config.abrEwmaDefaultEstimate;
4273
4290
  };
4274
4291
  _proto.findBestLevel = function findBestLevel(currentBw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor) {
4275
- var _this$hls$latestLevel2,
4292
+ var _this$hls$latestLevel,
4276
4293
  _this3 = this;
4277
4294
  var maxFetchDuration = bufferStarvationDelay + maxStarvationDelay;
4278
4295
  var lastLoadedFragLevel = this.lastLoadedFragLevel;
@@ -4288,7 +4305,7 @@
4288
4305
  return 0;
4289
4306
  }
4290
4307
  var level = levels[selectionBaseLevel];
4291
- var live = !!((_this$hls$latestLevel2 = this.hls.latestLevelDetails) != null && _this$hls$latestLevel2.live);
4308
+ var live = !!((_this$hls$latestLevel = this.hls.latestLevelDetails) != null && _this$hls$latestLevel.live);
4292
4309
  var firstSelection = loadLevel === -1 || lastLoadedFragLevel === -1;
4293
4310
  var currentCodecSet;
4294
4311
  var currentVideoRange = 'SDR';
@@ -5541,7 +5558,6 @@
5541
5558
  };
5542
5559
  _proto.removeFragment = function removeFragment(fragment) {
5543
5560
  var fragKey = getFragmentKey(fragment);
5544
- fragment.stats.loaded = 0;
5545
5561
  fragment.clearElementaryStreamInfo();
5546
5562
  var activeParts = this.activePartLists[fragment.type];
5547
5563
  if (activeParts) {
@@ -9791,7 +9807,7 @@
9791
9807
  var mainStart = this.hls.startPosition;
9792
9808
  var liveSyncPosition = this.hls.liveSyncPosition;
9793
9809
  var startPosition = frag ? (mainStart !== -1 && mainStart >= start ? mainStart : liveSyncPosition) || frag.start : pos;
9794
- this.log("Setting startPosition to " + startPosition + " to match initial live edge. mainStart: " + mainStart + " liveSyncPosition: " + liveSyncPosition + " frag.start: " + ((_frag = frag) == null ? void 0 : _frag.start));
9810
+ this.log("Setting startPosition to " + startPosition + " to match start frag at live edge. mainStart: " + mainStart + " liveSyncPosition: " + liveSyncPosition + " frag.start: " + ((_frag = frag) == null ? void 0 : _frag.start));
9795
9811
  this.startPosition = this.nextLoadPosition = startPosition;
9796
9812
  }
9797
9813
  } else if (pos <= start) {
@@ -10007,6 +10023,7 @@
10007
10023
  // Leave this.startPosition at -1, so that we can use `getInitialLiveFragment` logic when startPosition has
10008
10024
  // not been specified via the config or an as an argument to startLoad (#3736).
10009
10025
  startPosition = this.hls.liveSyncPosition || sliding;
10026
+ this.log("Setting startPosition to -1 to start at live edge " + startPosition);
10010
10027
  this.startPosition = -1;
10011
10028
  } else {
10012
10029
  this.log("setting startPosition to 0 by default");
@@ -16426,7 +16443,7 @@
16426
16443
  return !remuxResult.audio && !remuxResult.video && !remuxResult.text && !remuxResult.id3 && !remuxResult.initSegment;
16427
16444
  }
16428
16445
 
16429
- var version = "1.6.0-beta.4.0.canary.11033";
16446
+ var version = "1.6.0-beta.4.0.canary.11034";
16430
16447
 
16431
16448
  // ensure the worker ends up in the bundle
16432
16449
  // If the worker should not be included this gets aliased to empty.js
@@ -24765,8 +24782,9 @@
24765
24782
  }
24766
24783
  };
24767
24784
  _proto.startLoadingPrimaryAt = function startLoadingPrimaryAt(timelinePos, skipSeekToStartPosition) {
24785
+ var _hls$mainForwardBuffe;
24768
24786
  var hls = this.hls;
24769
- if (!hls.loadingEnabled || !hls.media || Math.abs(hls.media.currentTime - timelinePos) > 0.5) {
24787
+ if (!hls.loadingEnabled || !hls.media || Math.abs((((_hls$mainForwardBuffe = hls.mainForwardBufferInfo) == null ? void 0 : _hls$mainForwardBuffe.start) || hls.media.currentTime) - timelinePos) > 0.5) {
24770
24788
  hls.startLoad(timelinePos, skipSeekToStartPosition);
24771
24789
  } else if (!hls.bufferingEnabled) {
24772
24790
  hls.resumeBuffering();
@@ -24974,11 +24992,11 @@
24974
24992
  }
24975
24993
  var isInterstitial = this.isInterstitial(item);
24976
24994
  var bufferingPlayer = this.getBufferingPlayer();
24977
- var timeRemaining = bufferingPlayer ? bufferingPlayer.remaining : bufferingLast ? bufferingLast.end - this.timelinePos : 0;
24978
- this.log("buffered to boundary " + segmentToString(item) + (bufferingLast ? " (" + timeRemaining.toFixed(2) + " remaining)" : ''));
24979
24995
  this.bufferingItem = item;
24980
24996
  this.bufferedPos = Math.max(item.start, Math.min(item.end, this.timelinePos));
24981
24997
  if (!this.playbackDisabled) {
24998
+ var timeRemaining = bufferingPlayer ? bufferingPlayer.remaining : bufferingLast ? bufferingLast.end - this.timelinePos : 0;
24999
+ this.log("buffered to boundary " + segmentToString(item) + (bufferingLast ? " (" + timeRemaining.toFixed(2) + " remaining)" : ''));
24982
25000
  if (isInterstitial) {
24983
25001
  // primary fragment loading will exit early in base-stream-controller while `bufferingItem` is set to an Interstitial block
24984
25002
  item.event.assetList.forEach(function (asset) {
@@ -33131,8 +33149,7 @@
33131
33149
  return;
33132
33150
  }
33133
33151
  var liveSyncPosition = this.hls.liveSyncPosition;
33134
- var mediaCurrentTime = media.currentTime;
33135
- var currentTime = this.hasEnoughToStart || mediaCurrentTime > 0 ? mediaCurrentTime : this.startPosition;
33152
+ var currentTime = this.getLoadPosition();
33136
33153
  var start = levelDetails.fragmentStart;
33137
33154
  var end = levelDetails.edge;
33138
33155
  var withinSlidingWindow = currentTime >= start - config.maxFragLookUpTolerance && currentTime <= end;