hls.js 1.6.0-beta.1.0.canary.10750 → 1.6.0-beta.1.0.canary.10752

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.10750"}`);
403
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10752"}`);
404
404
  } catch (e) {
405
405
  /* log fn threw an exception. All logger methods are no-ops. */
406
406
  return createLogger();
@@ -1375,7 +1375,7 @@ class AbrController extends Logger {
1375
1375
  const bwEstimate = this.getBwEstimate();
1376
1376
  const levels = hls.levels;
1377
1377
  const level = levels[frag.level];
1378
- const expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.averageBitrate / 8));
1378
+ const expectedLen = Math.max(stats.loaded, Math.round(duration * (frag.bitrate || level.averageBitrate) / 8));
1379
1379
  let timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
1380
1380
  if (timeStreaming < 1 && loadedFirstByte) {
1381
1381
  timeStreaming = Math.min(timeLoading, stats.loaded * 8 / bwEstimate);
@@ -1933,7 +1933,7 @@ class AbrController extends Logger {
1933
1933
  }
1934
1934
 
1935
1935
  // Use average bitrate when starvation delay (buffer length) is gt or eq two segment durations and rebuffering is not expected (maxStarvationDelay > 0)
1936
- const bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ? levels[i].averageBitrate : levels[i].maxBitrate;
1936
+ const bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ? levelInfo.averageBitrate : levelInfo.maxBitrate;
1937
1937
  const fetchDuration = this.getTimeToLoadFrag(ttfbEstimateSec, adjustedbw, bitrate * avgDuration, levelDetails === undefined);
1938
1938
  const canSwitchWithinTolerance =
1939
1939
  // if adjusted bw is greater than level bitrate AND
@@ -3737,6 +3737,8 @@ class Fragment extends BaseSegment {
3737
3737
  this._decryptdata = null;
3738
3738
  this._programDateTime = null;
3739
3739
  this._ref = null;
3740
+ // Approximate bit rate of the fragment expressed in bits per second (bps) as indicated by the last EXT-X-BITRATE (kbps) tag
3741
+ this._bitrate = void 0;
3740
3742
  this.rawProgramDateTime = null;
3741
3743
  this.tagList = [];
3742
3744
  // EXTINF has to be present for a m3u8 to be considered valid
@@ -3791,6 +3793,34 @@ class Fragment extends BaseSegment {
3791
3793
  this.urlId = 0;
3792
3794
  this.type = type;
3793
3795
  }
3796
+ get byteLength() {
3797
+ if (this.hasStats) {
3798
+ const total = this.stats.total;
3799
+ if (total) {
3800
+ return total;
3801
+ }
3802
+ }
3803
+ if (this.byteRange) {
3804
+ const start = this.byteRange[0];
3805
+ const end = this.byteRange[1];
3806
+ if (isFiniteNumber(start) && isFiniteNumber(end)) {
3807
+ return end - start;
3808
+ }
3809
+ }
3810
+ return null;
3811
+ }
3812
+ get bitrate() {
3813
+ if (this.byteLength) {
3814
+ return this.byteLength * 8 / this.duration;
3815
+ }
3816
+ if (this._bitrate) {
3817
+ return this._bitrate;
3818
+ }
3819
+ return null;
3820
+ }
3821
+ set bitrate(value) {
3822
+ this._bitrate = value;
3823
+ }
3794
3824
  get decryptdata() {
3795
3825
  const {
3796
3826
  levelkeys
@@ -6918,6 +6948,7 @@ class M3U8Parser {
6918
6948
  let currentPart = 0;
6919
6949
  let totalduration = 0;
6920
6950
  let discontinuityCounter = 0;
6951
+ let currentBitrate = 0;
6921
6952
  let prevFrag = null;
6922
6953
  let frag = new Fragment(type, base);
6923
6954
  let result;
@@ -6938,6 +6969,9 @@ class M3U8Parser {
6938
6969
  frag.start = totalduration;
6939
6970
  frag.sn = currentSN;
6940
6971
  frag.cc = discontinuityCounter;
6972
+ if (currentBitrate) {
6973
+ frag.bitrate = currentBitrate;
6974
+ }
6941
6975
  frag.level = id;
6942
6976
  if (currentInitSegment) {
6943
6977
  frag.initSegment = currentInitSegment;
@@ -7067,6 +7101,12 @@ class M3U8Parser {
7067
7101
  break;
7068
7102
  case 'BITRATE':
7069
7103
  frag.tagList.push([tag, value1]);
7104
+ currentBitrate = parseInt(value1) * 1000;
7105
+ if (isFiniteNumber(currentBitrate)) {
7106
+ frag.bitrate = currentBitrate;
7107
+ } else {
7108
+ currentBitrate = 0;
7109
+ }
7070
7110
  break;
7071
7111
  case 'DATERANGE':
7072
7112
  {
@@ -8246,22 +8286,24 @@ class BaseStreamController extends TaskLoop {
8246
8286
  this.startFragRequested = true;
8247
8287
  this._loadFragForPlayback(frag, level, targetBufferTime);
8248
8288
  }
8249
- _loadFragForPlayback(frag, level, targetBufferTime) {
8289
+ _loadFragForPlayback(fragment, level, targetBufferTime) {
8250
8290
  const progressCallback = data => {
8291
+ const frag = data.frag;
8251
8292
  if (this.fragContextChanged(frag)) {
8252
- this.warn(`Fragment ${frag.sn}${data.part ? ' p: ' + data.part.index : ''} of level ${frag.level} was dropped during download.`);
8293
+ this.warn(`${frag.type} sn: ${frag.sn}${data.part ? ' part: ' + data.part.index : ''} of ${this.fragInfo(frag, false, data.part)}) was dropped during download.`);
8253
8294
  this.fragmentTracker.removeFragment(frag);
8254
8295
  return;
8255
8296
  }
8256
8297
  frag.stats.chunkCount++;
8257
8298
  this._handleFragmentLoadProgress(data);
8258
8299
  };
8259
- this._doFragLoad(frag, level, targetBufferTime, progressCallback).then(data => {
8300
+ this._doFragLoad(fragment, level, targetBufferTime, progressCallback).then(data => {
8260
8301
  if (!data) {
8261
8302
  // if we're here we probably needed to backtrack or are waiting for more parts
8262
8303
  return;
8263
8304
  }
8264
8305
  const state = this.state;
8306
+ const frag = data.frag;
8265
8307
  if (this.fragContextChanged(frag)) {
8266
8308
  if (state === State.FRAG_LOADING || !this.fragCurrent && state === State.PARSING) {
8267
8309
  this.fragmentTracker.removeFragment(frag);
@@ -8281,7 +8323,7 @@ class BaseStreamController extends TaskLoop {
8281
8323
  return;
8282
8324
  }
8283
8325
  this.warn(`Frag error: ${(reason == null ? void 0 : reason.message) || reason}`);
8284
- this.resetFragmentLoading(frag);
8326
+ this.resetFragmentLoading(fragment);
8285
8327
  });
8286
8328
  }
8287
8329
  clearTrackerIfNeeded(frag) {
@@ -8345,9 +8387,10 @@ class BaseStreamController extends TaskLoop {
8345
8387
  };
8346
8388
  this.hls.trigger(Events.BUFFER_FLUSHING, flushScope);
8347
8389
  }
8348
- _loadInitSegment(frag, level) {
8349
- this._doFragLoad(frag, level).then(data => {
8350
- if (!data || this.fragContextChanged(frag) || !this.levels) {
8390
+ _loadInitSegment(fragment, level) {
8391
+ this._doFragLoad(fragment, level).then(data => {
8392
+ const frag = data == null ? void 0 : data.frag;
8393
+ if (!frag || this.fragContextChanged(frag) || !this.levels) {
8351
8394
  throw new Error('init load aborted');
8352
8395
  }
8353
8396
  return data;
@@ -8356,6 +8399,7 @@ class BaseStreamController extends TaskLoop {
8356
8399
  hls
8357
8400
  } = this;
8358
8401
  const {
8402
+ frag,
8359
8403
  payload
8360
8404
  } = data;
8361
8405
  const decryptData = frag.decryptdata;
@@ -8394,7 +8438,7 @@ class BaseStreamController extends TaskLoop {
8394
8438
  return;
8395
8439
  }
8396
8440
  this.warn(reason);
8397
- this.resetFragmentLoading(frag);
8441
+ this.resetFragmentLoading(fragment);
8398
8442
  });
8399
8443
  }
8400
8444
  completeInitSegmentLoad(data) {
@@ -8421,7 +8465,7 @@ class BaseStreamController extends TaskLoop {
8421
8465
  }
8422
8466
  fragBufferedComplete(frag, part) {
8423
8467
  const media = this.mediaBuffer ? this.mediaBuffer : this.media;
8424
- this.log(`Buffered ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag)} > buffer:${media ? TimeRanges.toString(BufferHelper.getBuffered(media)) : '(detached)'})`);
8468
+ 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)'})`);
8425
8469
  if (frag.sn !== 'initSegment') {
8426
8470
  var _this$levels;
8427
8471
  if (frag.type !== PlaylistLevelType.SUBTITLE) {
@@ -8508,7 +8552,8 @@ class BaseStreamController extends TaskLoop {
8508
8552
  const partIndex = this.getNextPart(partList, frag, targetBufferTime);
8509
8553
  if (partIndex > -1) {
8510
8554
  const part = partList[partIndex];
8511
- this.log(`Loading part sn: ${frag.sn} p: ${part.index} cc: ${frag.cc} of playlist [${details.startSN}-${details.endSN}] parts [0-${partIndex}-${partList.length - 1}] ${this.playlistLabel()}: ${frag.level}, target: ${parseFloat(targetBufferTime.toFixed(3))}`);
8555
+ frag = this.fragCurrent = part.fragment;
8556
+ this.log(`Loading ${frag.type} sn: ${frag.sn} part: ${part.index} (${partIndex}/${partList.length - 1}) of ${this.fragInfo(frag, false, part)}) cc: ${frag.cc} [${details.startSN}-${details.endSN}], target: ${parseFloat(targetBufferTime.toFixed(3))}`);
8512
8557
  this.nextLoadPosition = part.start + part.duration;
8513
8558
  this.state = State.FRAG_LOADING;
8514
8559
  let _result;
@@ -9305,7 +9350,7 @@ class BaseStreamController extends TaskLoop {
9305
9350
  // For this error fallthrough. Marking parsed will allow advancing to next fragment.
9306
9351
  }
9307
9352
  this.state = State.PARSED;
9308
- this.log(`Parsed ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag)})`);
9353
+ this.log(`Parsed ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag, false, part)})`);
9309
9354
  this.hls.trigger(Events.FRAG_PARSED, {
9310
9355
  frag,
9311
9356
  part
@@ -9314,9 +9359,9 @@ class BaseStreamController extends TaskLoop {
9314
9359
  playlistLabel() {
9315
9360
  return this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track';
9316
9361
  }
9317
- fragInfo(frag, pts = true) {
9362
+ fragInfo(frag, pts = true, part) {
9318
9363
  var _ref, _ref2;
9319
- return `${this.playlistLabel()} ${frag.level} (frag:[${((_ref = pts ? frag.startPTS : frag.start) != null ? _ref : NaN).toFixed(3)}-${((_ref2 = pts ? frag.endPTS : frag.end) != null ? _ref2 : NaN).toFixed(3)}]`;
9364
+ 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') : ''}`;
9320
9365
  }
9321
9366
  resetTransmuxer() {
9322
9367
  var _this$transmuxer2;
@@ -9729,7 +9774,7 @@ var eventemitter3 = {exports: {}};
9729
9774
  var eventemitter3Exports = eventemitter3.exports;
9730
9775
  var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
9731
9776
 
9732
- const version = "1.6.0-beta.1.0.canary.10750";
9777
+ const version = "1.6.0-beta.1.0.canary.10752";
9733
9778
 
9734
9779
  // ensure the worker ends up in the bundle
9735
9780
  // If the worker should not be included this gets aliased to empty.js
@@ -15468,7 +15513,7 @@ class Transmuxer {
15468
15513
  accurateTimeOffset,
15469
15514
  timeOffset
15470
15515
  } = this.currentTransmuxState;
15471
- this.logger.log(`[transmuxer.ts]: Flushed ${this.id} sn: ${chunkMeta.sn}${chunkMeta.part > -1 ? ' p: ' + chunkMeta.part : ''} of ${this.id === PlaylistLevelType.MAIN ? 'level' : 'track'} ${chunkMeta.level}`);
15516
+ this.logger.log(`[transmuxer.ts]: Flushed ${this.id} sn: ${chunkMeta.sn}${chunkMeta.part > -1 ? ' part: ' + chunkMeta.part : ''} of ${this.id === PlaylistLevelType.MAIN ? 'level' : 'track'} ${chunkMeta.level}`);
15472
15517
  const remuxResult = this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, accurateTimeOffset, true, this.id);
15473
15518
  transmuxResults.push({
15474
15519
  remuxResult,
@@ -15853,7 +15898,7 @@ class TransmuxerInterface {
15853
15898
  const initSegmentChange = !(lastFrag && ((_frag$initSegment = frag.initSegment) == null ? void 0 : _frag$initSegment.url) === ((_lastFrag$initSegment = lastFrag.initSegment) == null ? void 0 : _lastFrag$initSegment.url));
15854
15899
  const state = new TransmuxState(discontinuity, contiguous, accurateTimeOffset, trackSwitch, timeOffset, initSegmentChange);
15855
15900
  if (!contiguous || discontinuity || initSegmentChange) {
15856
- this.hls.logger.log(`[transmuxer-interface, ${frag.type}]: Starting new transmux session for sn: ${chunkMeta.sn} p: ${chunkMeta.part} level: ${chunkMeta.level} id: ${chunkMeta.id}
15901
+ this.hls.logger.log(`[transmuxer-interface]: Starting new transmux session for ${frag.type} sn: ${chunkMeta.sn}${chunkMeta.part > -1 ? ' part: ' + chunkMeta.part : ''} ${this.id === PlaylistLevelType.MAIN ? 'level' : 'track'}: ${chunkMeta.level} id: ${chunkMeta.id}
15857
15902
  discontinuity: ${discontinuity}
15858
15903
  trackSwitch: ${trackSwitch}
15859
15904
  contiguous: ${contiguous}
@@ -31849,13 +31894,14 @@ class StreamController extends BaseStreamController {
31849
31894
  }
31850
31895
  return audioCodec;
31851
31896
  }
31852
- _loadBitrateTestFrag(frag, level) {
31853
- frag.bitrateTest = true;
31854
- this._doFragLoad(frag, level).then(data => {
31897
+ _loadBitrateTestFrag(fragment, level) {
31898
+ fragment.bitrateTest = true;
31899
+ this._doFragLoad(fragment, level).then(data => {
31855
31900
  const {
31856
31901
  hls
31857
31902
  } = this;
31858
- if (!data || this.fragContextChanged(frag)) {
31903
+ const frag = data == null ? void 0 : data.frag;
31904
+ if (!frag || this.fragContextChanged(frag)) {
31859
31905
  return;
31860
31906
  }
31861
31907
  level.fragmentError = 0;