hls.js 1.6.0-beta.1.0.canary.10751 → 1.6.0-beta.1.0.canary.10754

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/README.md CHANGED
@@ -86,20 +86,18 @@ For details on the HLS format and these tags' meanings, see https://datatracker.
86
86
  - `#EXT-X-CONTENT-STEERING:<attribute-list>` Content Steering
87
87
  - `#EXT-X-DEFINE:<attribute-list>` Variable Substitution (`NAME,VALUE,QUERYPARAM` attributes)
88
88
 
89
- The following properties are added to their respective variants' attribute list but are not implemented in their selection and playback.
90
-
91
- - `VIDEO-RANGE` (See [#2489](https://github.com/video-dev/hls.js/issues/2489))
92
-
93
89
  #### Media Playlist tags
94
90
 
95
- - `#EXTM3U`
96
- - `#EXT-X-VERSION=<n>`
91
+ - `#EXTM3U` (ignored)
92
+ - `#EXT-X-INDEPENDENT-SEGMENTS` (ignored)
93
+ - `#EXT-X-VERSION=<n>` (value is ignored)
97
94
  - `#EXTINF:<duration>,[<title>]`
98
95
  - `#EXT-X-ENDLIST`
99
96
  - `#EXT-X-MEDIA-SEQUENCE=<n>`
100
97
  - `#EXT-X-TARGETDURATION=<n>`
101
98
  - `#EXT-X-DISCONTINUITY`
102
99
  - `#EXT-X-DISCONTINUITY-SEQUENCE=<n>`
100
+ - `#EXT-X-BITRATE`
103
101
  - `#EXT-X-BYTERANGE=<n>[@<o>]`
104
102
  - `#EXT-X-MAP:<attribute-list>`
105
103
  - `#EXT-X-KEY:<attribute-list>` (`KEYFORMAT="identity",METHOD=SAMPLE-AES` is only supports with MPEG-2 TS segments)
@@ -115,11 +113,7 @@ The following properties are added to their respective variants' attribute list
115
113
  - `#EXT-X-DEFINE:<attribute-list>` Variable Import and Substitution (`NAME,VALUE,IMPORT,QUERYPARAM` attributes)
116
114
  - `#EXT-X-GAP` (Skips loading GAP segments and parts. Skips playback of unbuffered program containing only GAP content and no suitable alternates. See [#2940](https://github.com/video-dev/hls.js/issues/2940))
117
115
 
118
- The following tags are added to their respective fragment's attribute list but are not implemented in streaming and playback.
119
-
120
- - `#EXT-X-BITRATE` (Not used in ABR controller)
121
-
122
- Parsed but missing feature support
116
+ Parsed but missing feature support:
123
117
 
124
118
  - `#EXT-X-PRELOAD-HINT:<attribute-list>` (See [#5074](https://github.com/video-dev/hls.js/issues/3988))
125
119
  - #5074
@@ -129,6 +123,7 @@ Parsed but missing feature support
129
123
  For a complete list of issues, see ["Top priorities" in the Release Planning and Backlog project tab](https://github.com/video-dev/hls.js/projects/6). Codec support is dependent on the runtime environment (for example, not all browsers on the same OS support HEVC).
130
124
 
131
125
  - `#EXT-X-I-FRAME-STREAM-INF` I-frame Media Playlist files
126
+ - `REQ-VIDEO-LAYOUT` is not used in variant filtering or selection
132
127
  - "identity" format `SAMPLE-AES` method keys with fmp4, aac, mp3, vtt... segments (MPEG-2 TS only)
133
128
  - MPEG-2 TS segments with FairPlay Streaming, PlayReady, or Widevine encryption
134
129
  - FairPlay Streaming legacy keys (For com.apple.fps.1_0 use native Safari playback)
package/dist/hls.d.mts CHANGED
@@ -1290,6 +1290,7 @@ export declare class Fragment extends BaseSegment {
1290
1290
  private _decryptdata;
1291
1291
  private _programDateTime;
1292
1292
  private _ref;
1293
+ private _bitrate?;
1293
1294
  rawProgramDateTime: string | null;
1294
1295
  tagList: Array<string[]>;
1295
1296
  duration: number;
@@ -1319,6 +1320,9 @@ export declare class Fragment extends BaseSegment {
1319
1320
  gap?: boolean;
1320
1321
  urlId: number;
1321
1322
  constructor(type: PlaylistLevelType, base: Base | string);
1323
+ get byteLength(): number | null;
1324
+ get bitrate(): number | null;
1325
+ set bitrate(value: number);
1322
1326
  get decryptdata(): LevelKey | null;
1323
1327
  get end(): number;
1324
1328
  get endProgramDateTime(): number | null;
package/dist/hls.d.ts CHANGED
@@ -1290,6 +1290,7 @@ export declare class Fragment extends BaseSegment {
1290
1290
  private _decryptdata;
1291
1291
  private _programDateTime;
1292
1292
  private _ref;
1293
+ private _bitrate?;
1293
1294
  rawProgramDateTime: string | null;
1294
1295
  tagList: Array<string[]>;
1295
1296
  duration: number;
@@ -1319,6 +1320,9 @@ export declare class Fragment extends BaseSegment {
1319
1320
  gap?: boolean;
1320
1321
  urlId: number;
1321
1322
  constructor(type: PlaylistLevelType, base: Base | string);
1323
+ get byteLength(): number | null;
1324
+ get bitrate(): number | null;
1325
+ set bitrate(value: number);
1322
1326
  get decryptdata(): LevelKey | null;
1323
1327
  get end(): number;
1324
1328
  get endProgramDateTime(): number | null;
package/dist/hls.js CHANGED
@@ -1057,7 +1057,7 @@
1057
1057
  // Some browsers don't allow to use bind on console object anyway
1058
1058
  // fallback to default if needed
1059
1059
  try {
1060
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.6.0-beta.1.0.canary.10751");
1060
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.6.0-beta.1.0.canary.10754");
1061
1061
  } catch (e) {
1062
1062
  /* log fn threw an exception. All logger methods are no-ops. */
1063
1063
  return createLogger();
@@ -2115,7 +2115,7 @@
2115
2115
  var bwEstimate = _this.getBwEstimate();
2116
2116
  var levels = hls.levels;
2117
2117
  var level = levels[frag.level];
2118
- var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.averageBitrate / 8));
2118
+ var expectedLen = Math.max(stats.loaded, Math.round(duration * (frag.bitrate || level.averageBitrate) / 8));
2119
2119
  var timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
2120
2120
  if (timeStreaming < 1 && loadedFirstByte) {
2121
2121
  timeStreaming = Math.min(timeLoading, stats.loaded * 8 / bwEstimate);
@@ -2595,7 +2595,7 @@
2595
2595
  }
2596
2596
 
2597
2597
  // Use average bitrate when starvation delay (buffer length) is gt or eq two segment durations and rebuffering is not expected (maxStarvationDelay > 0)
2598
- var bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ? levels[i].averageBitrate : levels[i].maxBitrate;
2598
+ var bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ? levelInfo.averageBitrate : levelInfo.maxBitrate;
2599
2599
  var fetchDuration = _this3.getTimeToLoadFrag(ttfbEstimateSec, adjustedbw, bitrate * avgDuration, levelDetails === undefined);
2600
2600
  var canSwitchWithinTolerance =
2601
2601
  // if adjusted bw is greater than level bitrate AND
@@ -4330,6 +4330,8 @@
4330
4330
  _this._decryptdata = null;
4331
4331
  _this._programDateTime = null;
4332
4332
  _this._ref = null;
4333
+ // Approximate bit rate of the fragment expressed in bits per second (bps) as indicated by the last EXT-X-BITRATE (kbps) tag
4334
+ _this._bitrate = void 0;
4333
4335
  _this.rawProgramDateTime = null;
4334
4336
  _this.tagList = [];
4335
4337
  // EXTINF has to be present for a m3u8 to be considered valid
@@ -4437,6 +4439,38 @@
4437
4439
  info.endDTS = Math.max(info.endDTS, endDTS);
4438
4440
  };
4439
4441
  return _createClass(Fragment, [{
4442
+ key: "byteLength",
4443
+ get: function get() {
4444
+ if (this.hasStats) {
4445
+ var total = this.stats.total;
4446
+ if (total) {
4447
+ return total;
4448
+ }
4449
+ }
4450
+ if (this.byteRange) {
4451
+ var start = this.byteRange[0];
4452
+ var end = this.byteRange[1];
4453
+ if (isFiniteNumber(start) && isFiniteNumber(end)) {
4454
+ return end - start;
4455
+ }
4456
+ }
4457
+ return null;
4458
+ }
4459
+ }, {
4460
+ key: "bitrate",
4461
+ get: function get() {
4462
+ if (this.byteLength) {
4463
+ return this.byteLength * 8 / this.duration;
4464
+ }
4465
+ if (this._bitrate) {
4466
+ return this._bitrate;
4467
+ }
4468
+ return null;
4469
+ },
4470
+ set: function set(value) {
4471
+ this._bitrate = value;
4472
+ }
4473
+ }, {
4440
4474
  key: "decryptdata",
4441
4475
  get: function get() {
4442
4476
  var levelkeys = this.levelkeys;
@@ -7649,6 +7683,7 @@
7649
7683
  var currentPart = 0;
7650
7684
  var totalduration = 0;
7651
7685
  var discontinuityCounter = 0;
7686
+ var currentBitrate = 0;
7652
7687
  var prevFrag = null;
7653
7688
  var frag = new Fragment(type, base);
7654
7689
  var result;
@@ -7669,6 +7704,9 @@
7669
7704
  frag.start = totalduration;
7670
7705
  frag.sn = currentSN;
7671
7706
  frag.cc = discontinuityCounter;
7707
+ if (currentBitrate) {
7708
+ frag.bitrate = currentBitrate;
7709
+ }
7672
7710
  frag.level = id;
7673
7711
  if (currentInitSegment) {
7674
7712
  frag.initSegment = currentInitSegment;
@@ -7798,6 +7836,12 @@
7798
7836
  break;
7799
7837
  case 'BITRATE':
7800
7838
  frag.tagList.push([tag, value1]);
7839
+ currentBitrate = parseInt(value1) * 1000;
7840
+ if (isFiniteNumber(currentBitrate)) {
7841
+ frag.bitrate = currentBitrate;
7842
+ } else {
7843
+ currentBitrate = 0;
7844
+ }
7801
7845
  break;
7802
7846
  case 'DATERANGE':
7803
7847
  {
@@ -16178,7 +16222,7 @@
16178
16222
  return !remuxResult.audio && !remuxResult.video && !remuxResult.text && !remuxResult.id3 && !remuxResult.initSegment;
16179
16223
  }
16180
16224
 
16181
- var version = "1.6.0-beta.1.0.canary.10751";
16225
+ var version = "1.6.0-beta.1.0.canary.10754";
16182
16226
 
16183
16227
  // ensure the worker ends up in the bundle
16184
16228
  // If the worker should not be included this gets aliased to empty.js
@@ -17862,12 +17906,16 @@
17862
17906
  return -1;
17863
17907
  };
17864
17908
  _proto.loadPlaylist = function loadPlaylist(hlsUrlParameters) {
17909
+ var _this$hls$levels$this;
17865
17910
  var audioTrack = this.currentTrack;
17866
- if (this.shouldLoadPlaylist(audioTrack) && audioTrack) {
17911
+ if (!audioTrack) {
17912
+ return;
17913
+ }
17914
+ var url = audioTrack.url;
17915
+ if (this.shouldLoadPlaylist(audioTrack) && url !== ((_this$hls$levels$this = this.hls.levels[this.hls.loadLevel]) == null ? void 0 : _this$hls$levels$this.uri)) {
17867
17916
  _BasePlaylistControll.prototype.loadPlaylist.call(this);
17868
17917
  var id = audioTrack.id;
17869
17918
  var groupId = audioTrack.groupId;
17870
- var url = audioTrack.url;
17871
17919
  if (hlsUrlParameters) {
17872
17920
  try {
17873
17921
  url = hlsUrlParameters.addDirectives(url);
@@ -29851,47 +29899,51 @@
29851
29899
  xhr.onprogress = null;
29852
29900
  var _status = xhr.status;
29853
29901
  // http status between 200 to 299 are all successful
29854
- var useResponse = xhr.responseType !== 'text';
29855
- if (_status >= 200 && _status < 300 && (useResponse && xhr.response || xhr.responseText !== null)) {
29856
- stats.loading.end = Math.max(self.performance.now(), stats.loading.first);
29857
- var data = useResponse ? xhr.response : xhr.responseText;
29858
- var len = xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;
29859
- stats.loaded = stats.total = len;
29860
- stats.bwEstimate = stats.total * 8000 / (stats.loading.end - stats.loading.first);
29861
- if (!this.callbacks) {
29862
- return;
29863
- }
29864
- var onProgress = this.callbacks.onProgress;
29865
- if (onProgress) {
29866
- onProgress(stats, context, data, xhr);
29867
- }
29868
- if (!this.callbacks) {
29902
+ var useResponseText = xhr.responseType === 'text' ? xhr.responseText : null;
29903
+ if (_status >= 200 && _status < 300) {
29904
+ var data = useResponseText != null ? useResponseText : xhr.response;
29905
+ if (data != null) {
29906
+ stats.loading.end = Math.max(self.performance.now(), stats.loading.first);
29907
+ var len = xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;
29908
+ stats.loaded = stats.total = len;
29909
+ stats.bwEstimate = stats.total * 8000 / (stats.loading.end - stats.loading.first);
29910
+ if (!this.callbacks) {
29911
+ return;
29912
+ }
29913
+ var onProgress = this.callbacks.onProgress;
29914
+ if (onProgress) {
29915
+ onProgress(stats, context, data, xhr);
29916
+ }
29917
+ if (!this.callbacks) {
29918
+ return;
29919
+ }
29920
+ var _response = {
29921
+ url: xhr.responseURL,
29922
+ data: data,
29923
+ code: _status
29924
+ };
29925
+ this.callbacks.onSuccess(_response, stats, context, xhr);
29869
29926
  return;
29870
29927
  }
29871
- var response = {
29872
- url: xhr.responseURL,
29873
- data: data,
29874
- code: _status
29875
- };
29876
- this.callbacks.onSuccess(response, stats, context, xhr);
29928
+ }
29929
+
29930
+ // Handle bad status or nullish response
29931
+ var retryConfig = config.loadPolicy.errorRetry;
29932
+ var retryCount = stats.retry;
29933
+ // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
29934
+ var response = {
29935
+ url: context.url,
29936
+ data: undefined,
29937
+ code: _status
29938
+ };
29939
+ if (shouldRetry(retryConfig, retryCount, false, response)) {
29940
+ this.retry(retryConfig);
29877
29941
  } else {
29878
- var retryConfig = config.loadPolicy.errorRetry;
29879
- var retryCount = stats.retry;
29880
- // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
29881
- var _response = {
29882
- url: context.url,
29883
- data: undefined,
29884
- code: _status
29885
- };
29886
- if (shouldRetry(retryConfig, retryCount, false, _response)) {
29887
- this.retry(retryConfig);
29888
- } else {
29889
- logger.error(_status + " while loading " + context.url);
29890
- this.callbacks.onError({
29891
- code: _status,
29892
- text: xhr.statusText
29893
- }, context, xhr, stats);
29894
- }
29942
+ logger.error(_status + " while loading " + context.url);
29943
+ this.callbacks.onError({
29944
+ code: _status,
29945
+ text: xhr.statusText
29946
+ }, context, xhr, stats);
29895
29947
  }
29896
29948
  }
29897
29949
  }
package/dist/hls.js.d.ts CHANGED
@@ -1290,6 +1290,7 @@ export declare class Fragment extends BaseSegment {
1290
1290
  private _decryptdata;
1291
1291
  private _programDateTime;
1292
1292
  private _ref;
1293
+ private _bitrate?;
1293
1294
  rawProgramDateTime: string | null;
1294
1295
  tagList: Array<string[]>;
1295
1296
  duration: number;
@@ -1319,6 +1320,9 @@ export declare class Fragment extends BaseSegment {
1319
1320
  gap?: boolean;
1320
1321
  urlId: number;
1321
1322
  constructor(type: PlaylistLevelType, base: Base | string);
1323
+ get byteLength(): number | null;
1324
+ get bitrate(): number | null;
1325
+ set bitrate(value: number);
1322
1326
  get decryptdata(): LevelKey | null;
1323
1327
  get end(): number;
1324
1328
  get endProgramDateTime(): number | null;