hls.js 1.6.0-beta.1.0.canary.10712 → 1.6.0-beta.1.0.canary.10715

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
@@ -397,7 +397,7 @@ function enableLogs(debugConfig, context, id) {
397
397
  // Some browsers don't allow to use bind on console object anyway
398
398
  // fallback to default if needed
399
399
  try {
400
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10712"}`);
400
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10715"}`);
401
401
  } catch (e) {
402
402
  /* log fn threw an exception. All logger methods are no-ops. */
403
403
  return createLogger();
@@ -1324,6 +1324,7 @@ class AbrController extends Logger {
1324
1324
  quickly enough to prevent underbuffering
1325
1325
  */
1326
1326
  this._abandonRulesCheck = () => {
1327
+ var _this$hls$latestLevel;
1327
1328
  const {
1328
1329
  fragCurrent: frag,
1329
1330
  partCurrent: part,
@@ -1378,12 +1379,15 @@ class AbrController extends Logger {
1378
1379
  }
1379
1380
  const loadRate = loadedFirstByte ? stats.loaded * 1000 / timeStreaming : 0;
1380
1381
  // fragLoadDelay is an estimate of the time (in seconds) it will take to buffer the remainder of the fragment
1381
- const fragLoadedDelay = loadRate ? (expectedLen - stats.loaded) / loadRate : expectedLen * 8 / bwEstimate + ttfbEstimate / 1000;
1382
+ const ttfbSeconds = ttfbEstimate / 1000;
1383
+ const fragLoadedDelay = loadRate ? (expectedLen - stats.loaded) / loadRate : expectedLen * 8 / bwEstimate + ttfbSeconds;
1382
1384
  // Only downswitch if the time to finish loading the current fragment is greater than the amount of buffer left
1383
1385
  if (fragLoadedDelay <= bufferStarvationDelay) {
1384
1386
  return;
1385
1387
  }
1386
1388
  const bwe = loadRate ? loadRate * 8 : bwEstimate;
1389
+ const live = ((_this$hls$latestLevel = this.hls.latestLevelDetails) == null ? void 0 : _this$hls$latestLevel.live) === true;
1390
+ const abrBandWidthUpFactor = this.hls.config.abrBandWidthUpFactor;
1387
1391
  let fragLevelNextLoadedDelay = Number.POSITIVE_INFINITY;
1388
1392
  let nextLoadLevel;
1389
1393
  // Iterate through lower level and try to find the largest one that avoids rebuffering
@@ -1391,8 +1395,9 @@ class AbrController extends Logger {
1391
1395
  // compute time to load next fragment at lower level
1392
1396
  // 8 = bits per byte (bps/Bps)
1393
1397
  const levelNextBitrate = levels[nextLoadLevel].maxBitrate;
1394
- fragLevelNextLoadedDelay = this.getTimeToLoadFrag(ttfbEstimate / 1000, bwe, duration * levelNextBitrate, !levels[nextLoadLevel].details);
1395
- if (fragLevelNextLoadedDelay < bufferStarvationDelay) {
1398
+ const requiresLevelLoad = !levels[nextLoadLevel].details || live;
1399
+ fragLevelNextLoadedDelay = this.getTimeToLoadFrag(ttfbSeconds, bwe, duration * levelNextBitrate, requiresLevelLoad);
1400
+ if (fragLevelNextLoadedDelay < Math.min(bufferStarvationDelay, duration + ttfbSeconds)) {
1396
1401
  break;
1397
1402
  }
1398
1403
  }
@@ -1406,7 +1411,6 @@ class AbrController extends Logger {
1406
1411
  if (fragLevelNextLoadedDelay > duration * 10) {
1407
1412
  return;
1408
1413
  }
1409
- hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
1410
1414
  if (loadedFirstByte) {
1411
1415
  // If there has been loading progress, sample bandwidth using loading time offset by minimum TTFB time
1412
1416
  this.bwEstimator.sample(timeLoading - Math.min(ttfbEstimate, ttfb), stats.loaded);
@@ -1415,11 +1419,15 @@ class AbrController extends Logger {
1415
1419
  this.bwEstimator.sampleTTFB(timeLoading);
1416
1420
  }
1417
1421
  const nextLoadLevelBitrate = levels[nextLoadLevel].maxBitrate;
1418
- if (this.getBwEstimate() * this.hls.config.abrBandWidthUpFactor > nextLoadLevelBitrate) {
1422
+ if (this.getBwEstimate() * abrBandWidthUpFactor > nextLoadLevelBitrate) {
1419
1423
  this.resetEstimator(nextLoadLevelBitrate);
1420
1424
  }
1421
- this.clearTimer();
1425
+ const bestSwitchLevel = this.findBestLevel(nextLoadLevelBitrate, minAutoLevel, nextLoadLevel, 0, bufferStarvationDelay, 1, 1);
1426
+ if (bestSwitchLevel > -1) {
1427
+ nextLoadLevel = bestSwitchLevel;
1428
+ }
1422
1429
  this.warn(`Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of level ${frag.level} is loading too slowly;
1430
+ Fragment duration: ${frag.duration.toFixed(3)}
1423
1431
  Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s
1424
1432
  Estimated load time for current fragment: ${fragLoadedDelay.toFixed(3)} s
1425
1433
  Estimated load time for down switch fragment: ${fragLevelNextLoadedDelay.toFixed(3)} s
@@ -1427,6 +1435,28 @@ class AbrController extends Logger {
1427
1435
  Current BW estimate: ${isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown'} bps
1428
1436
  New BW estimate: ${this.getBwEstimate() | 0} bps
1429
1437
  Switching to level ${nextLoadLevel} @ ${nextLoadLevelBitrate | 0} bps`);
1438
+ hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
1439
+ this.clearTimer();
1440
+ this.timer = self.setInterval(() => {
1441
+ // Are nextLoadLevel details available or is stream-controller still in "WAITING_LEVEL" state?
1442
+ this.clearTimer();
1443
+ if (this.fragCurrent === frag && this.hls.loadLevel === nextLoadLevel && nextLoadLevel > 0) {
1444
+ const bufferStarvationDelay = this.getStarvationDelay();
1445
+ this.warn(`Aborting inflight request ${nextLoadLevel > 0 ? 'and switching down' : ''}
1446
+ Fragment duration: ${frag.duration.toFixed(3)} s
1447
+ Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s`);
1448
+ frag.abortRequests();
1449
+ this.fragCurrent = this.partCurrent = null;
1450
+ if (nextLoadLevel > minAutoLevel) {
1451
+ let lowestSwitchLevel = this.findBestLevel(this.hls.levels[minAutoLevel].bitrate, minAutoLevel, nextLoadLevel, 0, bufferStarvationDelay, 1, 1);
1452
+ if (lowestSwitchLevel === -1) {
1453
+ lowestSwitchLevel = minAutoLevel;
1454
+ }
1455
+ this.hls.nextLoadLevel = this.hls.nextAutoLevel = lowestSwitchLevel;
1456
+ this.resetEstimator(this.hls.levels[lowestSwitchLevel].bitrate);
1457
+ }
1458
+ }
1459
+ }, fragLevelNextLoadedDelay * 1000);
1430
1460
  hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
1431
1461
  frag,
1432
1462
  part,
@@ -1787,7 +1817,7 @@ class AbrController extends Logger {
1787
1817
  return this.bwEstimator.canEstimate() ? this.bwEstimator.getEstimate() : this.hls.config.abrEwmaDefaultEstimate;
1788
1818
  }
1789
1819
  findBestLevel(currentBw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor) {
1790
- var _level$details;
1820
+ var _this$hls$latestLevel2;
1791
1821
  const maxFetchDuration = bufferStarvationDelay + maxStarvationDelay;
1792
1822
  const lastLoadedFragLevel = this.lastLoadedFragLevel;
1793
1823
  const selectionBaseLevel = lastLoadedFragLevel === -1 ? this.hls.firstLevel : lastLoadedFragLevel;
@@ -1805,7 +1835,7 @@ class AbrController extends Logger {
1805
1835
  return 0;
1806
1836
  }
1807
1837
  const level = levels[selectionBaseLevel];
1808
- const live = !!(level != null && (_level$details = level.details) != null && _level$details.live);
1838
+ const live = !!((_this$hls$latestLevel2 = this.hls.latestLevelDetails) != null && _this$hls$latestLevel2.live);
1809
1839
  const firstSelection = loadLevel === -1 || lastLoadedFragLevel === -1;
1810
1840
  let currentCodecSet;
1811
1841
  let currentVideoRange = 'SDR';
@@ -9626,7 +9656,7 @@ var eventemitter3 = {exports: {}};
9626
9656
  var eventemitter3Exports = eventemitter3.exports;
9627
9657
  var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
9628
9658
 
9629
- const version = "1.6.0-beta.1.0.canary.10712";
9659
+ const version = "1.6.0-beta.1.0.canary.10715";
9630
9660
 
9631
9661
  // ensure the worker ends up in the bundle
9632
9662
  // If the worker should not be included this gets aliased to empty.js
@@ -30161,8 +30191,10 @@ class LevelController extends BasePlaylistController {
30161
30191
  const pathwayId = level.attrs['PATHWAY-ID'];
30162
30192
  this.currentLevelIndex = newLevel;
30163
30193
  this.currentLevel = level;
30164
- if (lastLevelIndex === newLevel && level.details && lastLevel && lastPathwayId === pathwayId) {
30165
- return;
30194
+ if (lastLevelIndex === newLevel && lastLevel && lastPathwayId === pathwayId) {
30195
+ if (level.details || this.requestScheduled !== -1) {
30196
+ return;
30197
+ }
30166
30198
  }
30167
30199
  this.log(`Switching to level ${newLevel} (${level.height ? level.height + 'p ' : ''}${level.videoRange ? level.videoRange + ' ' : ''}${level.codecSet ? level.codecSet + ' ' : ''}@${level.bitrate})${pathwayId ? ' with Pathway ' + pathwayId : ''} from level ${lastLevelIndex}${lastPathwayId ? ' with Pathway ' + lastPathwayId : ''}`);
30168
30200
  const levelSwitchingData = {
@@ -30256,7 +30288,10 @@ class LevelController extends BasePlaylistController {
30256
30288
  return;
30257
30289
  }
30258
30290
  if (data.context.type === PlaylistContextType.LEVEL && data.context.level === this.level) {
30259
- this.checkRetry(data);
30291
+ const retry = this.checkRetry(data);
30292
+ if (!retry) {
30293
+ this.requestScheduled = -1;
30294
+ }
30260
30295
  }
30261
30296
  }
30262
30297