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.
@@ -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();
@@ -1129,7 +1129,7 @@ class AbrController extends Logger {
1129
1129
  const bwEstimate = this.getBwEstimate();
1130
1130
  const levels = hls.levels;
1131
1131
  const level = levels[frag.level];
1132
- const expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.averageBitrate / 8));
1132
+ const expectedLen = Math.max(stats.loaded, Math.round(duration * (frag.bitrate || level.averageBitrate) / 8));
1133
1133
  let timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
1134
1134
  if (timeStreaming < 1 && loadedFirstByte) {
1135
1135
  timeStreaming = Math.min(timeLoading, stats.loaded * 8 / bwEstimate);
@@ -1662,7 +1662,7 @@ class AbrController extends Logger {
1662
1662
  }
1663
1663
 
1664
1664
  // Use average bitrate when starvation delay (buffer length) is gt or eq two segment durations and rebuffering is not expected (maxStarvationDelay > 0)
1665
- const bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ? levels[i].averageBitrate : levels[i].maxBitrate;
1665
+ const bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ? levelInfo.averageBitrate : levelInfo.maxBitrate;
1666
1666
  const fetchDuration = this.getTimeToLoadFrag(ttfbEstimateSec, adjustedbw, bitrate * avgDuration, levelDetails === undefined);
1667
1667
  const canSwitchWithinTolerance =
1668
1668
  // if adjusted bw is greater than level bitrate AND
@@ -2869,6 +2869,8 @@ class Fragment extends BaseSegment {
2869
2869
  this._decryptdata = null;
2870
2870
  this._programDateTime = null;
2871
2871
  this._ref = null;
2872
+ // Approximate bit rate of the fragment expressed in bits per second (bps) as indicated by the last EXT-X-BITRATE (kbps) tag
2873
+ this._bitrate = void 0;
2872
2874
  this.rawProgramDateTime = null;
2873
2875
  this.tagList = [];
2874
2876
  // EXTINF has to be present for a m3u8 to be considered valid
@@ -2923,6 +2925,34 @@ class Fragment extends BaseSegment {
2923
2925
  this.urlId = 0;
2924
2926
  this.type = type;
2925
2927
  }
2928
+ get byteLength() {
2929
+ if (this.hasStats) {
2930
+ const total = this.stats.total;
2931
+ if (total) {
2932
+ return total;
2933
+ }
2934
+ }
2935
+ if (this.byteRange) {
2936
+ const start = this.byteRange[0];
2937
+ const end = this.byteRange[1];
2938
+ if (isFiniteNumber(start) && isFiniteNumber(end)) {
2939
+ return end - start;
2940
+ }
2941
+ }
2942
+ return null;
2943
+ }
2944
+ get bitrate() {
2945
+ if (this.byteLength) {
2946
+ return this.byteLength * 8 / this.duration;
2947
+ }
2948
+ if (this._bitrate) {
2949
+ return this._bitrate;
2950
+ }
2951
+ return null;
2952
+ }
2953
+ set bitrate(value) {
2954
+ this._bitrate = value;
2955
+ }
2926
2956
  get decryptdata() {
2927
2957
  const {
2928
2958
  levelkeys
@@ -4670,6 +4700,7 @@ class M3U8Parser {
4670
4700
  let currentPart = 0;
4671
4701
  let totalduration = 0;
4672
4702
  let discontinuityCounter = 0;
4703
+ let currentBitrate = 0;
4673
4704
  let prevFrag = null;
4674
4705
  let frag = new Fragment(type, base);
4675
4706
  let result;
@@ -4690,6 +4721,9 @@ class M3U8Parser {
4690
4721
  frag.start = totalduration;
4691
4722
  frag.sn = currentSN;
4692
4723
  frag.cc = discontinuityCounter;
4724
+ if (currentBitrate) {
4725
+ frag.bitrate = currentBitrate;
4726
+ }
4693
4727
  frag.level = id;
4694
4728
  if (currentInitSegment) {
4695
4729
  frag.initSegment = currentInitSegment;
@@ -4819,6 +4853,12 @@ class M3U8Parser {
4819
4853
  break;
4820
4854
  case 'BITRATE':
4821
4855
  frag.tagList.push([tag, value1]);
4856
+ currentBitrate = parseInt(value1) * 1000;
4857
+ if (isFiniteNumber(currentBitrate)) {
4858
+ frag.bitrate = currentBitrate;
4859
+ } else {
4860
+ currentBitrate = 0;
4861
+ }
4822
4862
  break;
4823
4863
  case 'DATERANGE':
4824
4864
  {
@@ -7710,22 +7750,24 @@ class BaseStreamController extends TaskLoop {
7710
7750
  this.startFragRequested = true;
7711
7751
  this._loadFragForPlayback(frag, level, targetBufferTime);
7712
7752
  }
7713
- _loadFragForPlayback(frag, level, targetBufferTime) {
7753
+ _loadFragForPlayback(fragment, level, targetBufferTime) {
7714
7754
  const progressCallback = data => {
7755
+ const frag = data.frag;
7715
7756
  if (this.fragContextChanged(frag)) {
7716
- this.warn(`Fragment ${frag.sn}${data.part ? ' p: ' + data.part.index : ''} of level ${frag.level} was dropped during download.`);
7757
+ this.warn(`${frag.type} sn: ${frag.sn}${data.part ? ' part: ' + data.part.index : ''} of ${this.fragInfo(frag, false, data.part)}) was dropped during download.`);
7717
7758
  this.fragmentTracker.removeFragment(frag);
7718
7759
  return;
7719
7760
  }
7720
7761
  frag.stats.chunkCount++;
7721
7762
  this._handleFragmentLoadProgress(data);
7722
7763
  };
7723
- this._doFragLoad(frag, level, targetBufferTime, progressCallback).then(data => {
7764
+ this._doFragLoad(fragment, level, targetBufferTime, progressCallback).then(data => {
7724
7765
  if (!data) {
7725
7766
  // if we're here we probably needed to backtrack or are waiting for more parts
7726
7767
  return;
7727
7768
  }
7728
7769
  const state = this.state;
7770
+ const frag = data.frag;
7729
7771
  if (this.fragContextChanged(frag)) {
7730
7772
  if (state === State.FRAG_LOADING || !this.fragCurrent && state === State.PARSING) {
7731
7773
  this.fragmentTracker.removeFragment(frag);
@@ -7745,7 +7787,7 @@ class BaseStreamController extends TaskLoop {
7745
7787
  return;
7746
7788
  }
7747
7789
  this.warn(`Frag error: ${(reason == null ? void 0 : reason.message) || reason}`);
7748
- this.resetFragmentLoading(frag);
7790
+ this.resetFragmentLoading(fragment);
7749
7791
  });
7750
7792
  }
7751
7793
  clearTrackerIfNeeded(frag) {
@@ -7809,9 +7851,10 @@ class BaseStreamController extends TaskLoop {
7809
7851
  };
7810
7852
  this.hls.trigger(Events.BUFFER_FLUSHING, flushScope);
7811
7853
  }
7812
- _loadInitSegment(frag, level) {
7813
- this._doFragLoad(frag, level).then(data => {
7814
- if (!data || this.fragContextChanged(frag) || !this.levels) {
7854
+ _loadInitSegment(fragment, level) {
7855
+ this._doFragLoad(fragment, level).then(data => {
7856
+ const frag = data == null ? void 0 : data.frag;
7857
+ if (!frag || this.fragContextChanged(frag) || !this.levels) {
7815
7858
  throw new Error('init load aborted');
7816
7859
  }
7817
7860
  return data;
@@ -7820,6 +7863,7 @@ class BaseStreamController extends TaskLoop {
7820
7863
  hls
7821
7864
  } = this;
7822
7865
  const {
7866
+ frag,
7823
7867
  payload
7824
7868
  } = data;
7825
7869
  const decryptData = frag.decryptdata;
@@ -7858,7 +7902,7 @@ class BaseStreamController extends TaskLoop {
7858
7902
  return;
7859
7903
  }
7860
7904
  this.warn(reason);
7861
- this.resetFragmentLoading(frag);
7905
+ this.resetFragmentLoading(fragment);
7862
7906
  });
7863
7907
  }
7864
7908
  completeInitSegmentLoad(data) {
@@ -7885,7 +7929,7 @@ class BaseStreamController extends TaskLoop {
7885
7929
  }
7886
7930
  fragBufferedComplete(frag, part) {
7887
7931
  const media = this.mediaBuffer ? this.mediaBuffer : this.media;
7888
- this.log(`Buffered ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag)} > buffer:${media ? TimeRanges.toString(BufferHelper.getBuffered(media)) : '(detached)'})`);
7932
+ 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)'})`);
7889
7933
  if (frag.sn !== 'initSegment') {
7890
7934
  var _this$levels;
7891
7935
  if (frag.type !== PlaylistLevelType.SUBTITLE) {
@@ -7972,7 +8016,8 @@ class BaseStreamController extends TaskLoop {
7972
8016
  const partIndex = this.getNextPart(partList, frag, targetBufferTime);
7973
8017
  if (partIndex > -1) {
7974
8018
  const part = partList[partIndex];
7975
- 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))}`);
8019
+ frag = this.fragCurrent = part.fragment;
8020
+ 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))}`);
7976
8021
  this.nextLoadPosition = part.start + part.duration;
7977
8022
  this.state = State.FRAG_LOADING;
7978
8023
  let _result;
@@ -8769,7 +8814,7 @@ class BaseStreamController extends TaskLoop {
8769
8814
  // For this error fallthrough. Marking parsed will allow advancing to next fragment.
8770
8815
  }
8771
8816
  this.state = State.PARSED;
8772
- this.log(`Parsed ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag)})`);
8817
+ this.log(`Parsed ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag, false, part)})`);
8773
8818
  this.hls.trigger(Events.FRAG_PARSED, {
8774
8819
  frag,
8775
8820
  part
@@ -8778,9 +8823,9 @@ class BaseStreamController extends TaskLoop {
8778
8823
  playlistLabel() {
8779
8824
  return this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track';
8780
8825
  }
8781
- fragInfo(frag, pts = true) {
8826
+ fragInfo(frag, pts = true, part) {
8782
8827
  var _ref, _ref2;
8783
- 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)}]`;
8828
+ 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') : ''}`;
8784
8829
  }
8785
8830
  resetTransmuxer() {
8786
8831
  var _this$transmuxer2;
@@ -16408,7 +16453,7 @@ class Transmuxer {
16408
16453
  accurateTimeOffset,
16409
16454
  timeOffset
16410
16455
  } = this.currentTransmuxState;
16411
- 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}`);
16456
+ 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}`);
16412
16457
  const remuxResult = this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, accurateTimeOffset, true, this.id);
16413
16458
  transmuxResults.push({
16414
16459
  remuxResult,
@@ -19038,7 +19083,7 @@ class GapController extends Logger {
19038
19083
  }
19039
19084
  }
19040
19085
 
19041
- const version = "1.6.0-beta.1.0.canary.10750";
19086
+ const version = "1.6.0-beta.1.0.canary.10752";
19042
19087
 
19043
19088
  // ensure the worker ends up in the bundle
19044
19089
  // If the worker should not be included this gets aliased to empty.js
@@ -19314,7 +19359,7 @@ class TransmuxerInterface {
19314
19359
  const initSegmentChange = !(lastFrag && ((_frag$initSegment = frag.initSegment) == null ? void 0 : _frag$initSegment.url) === ((_lastFrag$initSegment = lastFrag.initSegment) == null ? void 0 : _lastFrag$initSegment.url));
19315
19360
  const state = new TransmuxState(discontinuity, contiguous, accurateTimeOffset, trackSwitch, timeOffset, initSegmentChange);
19316
19361
  if (!contiguous || discontinuity || initSegmentChange) {
19317
- 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}
19362
+ 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}
19318
19363
  discontinuity: ${discontinuity}
19319
19364
  trackSwitch: ${trackSwitch}
19320
19365
  contiguous: ${contiguous}
@@ -20322,13 +20367,14 @@ class StreamController extends BaseStreamController {
20322
20367
  }
20323
20368
  return audioCodec;
20324
20369
  }
20325
- _loadBitrateTestFrag(frag, level) {
20326
- frag.bitrateTest = true;
20327
- this._doFragLoad(frag, level).then(data => {
20370
+ _loadBitrateTestFrag(fragment, level) {
20371
+ fragment.bitrateTest = true;
20372
+ this._doFragLoad(fragment, level).then(data => {
20328
20373
  const {
20329
20374
  hls
20330
20375
  } = this;
20331
- if (!data || this.fragContextChanged(frag)) {
20376
+ const frag = data == null ? void 0 : data.frag;
20377
+ if (!frag || this.fragContextChanged(frag)) {
20332
20378
  return;
20333
20379
  }
20334
20380
  level.fragmentError = 0;