hls.js 1.5.14-0.canary.10517 → 1.5.14

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.
Files changed (107) hide show
  1. package/README.md +3 -4
  2. package/dist/hls-demo.js +38 -41
  3. package/dist/hls-demo.js.map +1 -1
  4. package/dist/hls.js +2903 -4542
  5. package/dist/hls.js.d.ts +112 -186
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +2284 -3295
  8. package/dist/hls.light.js.map +1 -1
  9. package/dist/hls.light.min.js +1 -1
  10. package/dist/hls.light.min.js.map +1 -1
  11. package/dist/hls.light.mjs +1804 -2817
  12. package/dist/hls.light.mjs.map +1 -1
  13. package/dist/hls.min.js +1 -1
  14. package/dist/hls.min.js.map +1 -1
  15. package/dist/hls.mjs +4652 -6293
  16. package/dist/hls.mjs.map +1 -1
  17. package/dist/hls.worker.js +1 -1
  18. package/dist/hls.worker.js.map +1 -1
  19. package/package.json +38 -38
  20. package/src/config.ts +2 -5
  21. package/src/controller/abr-controller.ts +25 -39
  22. package/src/controller/audio-stream-controller.ts +136 -156
  23. package/src/controller/audio-track-controller.ts +1 -1
  24. package/src/controller/base-playlist-controller.ts +10 -27
  25. package/src/controller/base-stream-controller.ts +107 -263
  26. package/src/controller/buffer-controller.ts +98 -252
  27. package/src/controller/buffer-operation-queue.ts +19 -16
  28. package/src/controller/cap-level-controller.ts +2 -3
  29. package/src/controller/cmcd-controller.ts +14 -51
  30. package/src/controller/content-steering-controller.ts +15 -29
  31. package/src/controller/eme-controller.ts +23 -10
  32. package/src/controller/error-controller.ts +22 -28
  33. package/src/controller/fps-controller.ts +3 -8
  34. package/src/controller/fragment-finders.ts +16 -44
  35. package/src/controller/fragment-tracker.ts +25 -58
  36. package/src/controller/gap-controller.ts +16 -43
  37. package/src/controller/id3-track-controller.ts +35 -45
  38. package/src/controller/latency-controller.ts +13 -18
  39. package/src/controller/level-controller.ts +19 -37
  40. package/src/controller/stream-controller.ts +83 -100
  41. package/src/controller/subtitle-stream-controller.ts +47 -35
  42. package/src/controller/subtitle-track-controller.ts +3 -5
  43. package/src/controller/timeline-controller.ts +22 -20
  44. package/src/crypt/aes-crypto.ts +2 -21
  45. package/src/crypt/decrypter.ts +16 -32
  46. package/src/crypt/fast-aes-key.ts +5 -28
  47. package/src/demux/audio/aacdemuxer.ts +5 -5
  48. package/src/demux/audio/ac3-demuxer.ts +4 -5
  49. package/src/demux/audio/adts.ts +4 -9
  50. package/src/demux/audio/base-audio-demuxer.ts +14 -16
  51. package/src/demux/audio/mp3demuxer.ts +3 -4
  52. package/src/demux/audio/mpegaudio.ts +1 -1
  53. package/src/demux/id3.ts +411 -0
  54. package/src/demux/inject-worker.ts +4 -38
  55. package/src/demux/mp4demuxer.ts +7 -7
  56. package/src/demux/sample-aes.ts +0 -2
  57. package/src/demux/transmuxer-interface.ts +83 -106
  58. package/src/demux/transmuxer-worker.ts +77 -111
  59. package/src/demux/transmuxer.ts +22 -46
  60. package/src/demux/tsdemuxer.ts +62 -122
  61. package/src/demux/video/avc-video-parser.ts +121 -210
  62. package/src/demux/video/base-video-parser.ts +2 -135
  63. package/src/demux/video/exp-golomb.ts +208 -0
  64. package/src/errors.ts +0 -2
  65. package/src/events.ts +1 -8
  66. package/src/exports-named.ts +1 -1
  67. package/src/hls.ts +48 -97
  68. package/src/loader/date-range.ts +5 -71
  69. package/src/loader/fragment-loader.ts +21 -23
  70. package/src/loader/fragment.ts +4 -8
  71. package/src/loader/key-loader.ts +1 -3
  72. package/src/loader/level-details.ts +6 -6
  73. package/src/loader/level-key.ts +9 -10
  74. package/src/loader/m3u8-parser.ts +144 -138
  75. package/src/loader/playlist-loader.ts +7 -5
  76. package/src/remux/mp4-generator.ts +1 -196
  77. package/src/remux/mp4-remuxer.ts +84 -55
  78. package/src/remux/passthrough-remuxer.ts +8 -23
  79. package/src/task-loop.ts +2 -5
  80. package/src/types/component-api.ts +1 -3
  81. package/src/types/demuxer.ts +0 -3
  82. package/src/types/events.ts +6 -19
  83. package/src/types/fragment-tracker.ts +2 -2
  84. package/src/types/general.ts +6 -0
  85. package/src/types/media-playlist.ts +1 -9
  86. package/src/types/remuxer.ts +1 -1
  87. package/src/utils/attr-list.ts +9 -96
  88. package/src/utils/buffer-helper.ts +31 -12
  89. package/src/utils/cea-608-parser.ts +3 -1
  90. package/src/utils/codecs.ts +5 -34
  91. package/src/utils/discontinuities.ts +47 -21
  92. package/src/utils/fetch-loader.ts +1 -1
  93. package/src/utils/hdr.ts +7 -4
  94. package/src/utils/imsc1-ttml-parser.ts +1 -1
  95. package/src/utils/keysystem-util.ts +6 -1
  96. package/src/utils/level-helper.ts +44 -71
  97. package/src/utils/logger.ts +23 -58
  98. package/src/utils/mp4-tools.ts +3 -5
  99. package/src/utils/rendition-helper.ts +74 -100
  100. package/src/utils/variable-substitution.ts +19 -0
  101. package/src/utils/webvtt-parser.ts +12 -2
  102. package/src/crypt/decrypter-aes-mode.ts +0 -4
  103. package/src/demux/video/hevc-video-parser.ts +0 -749
  104. package/src/utils/encryption-methods-util.ts +0 -21
  105. package/src/utils/hash.ts +0 -10
  106. package/src/utils/utf8-utils.ts +0 -18
  107. package/src/version.ts +0 -1
package/package.json CHANGED
@@ -58,52 +58,52 @@
58
58
  "test:func:sauce": "SAUCE=1 UA=safari OS='OS X 10.15' BABEL_ENV=development mocha --require @babel/register tests/functional/auto/setup.js --timeout 40000 --exit",
59
59
  "type-check": "tsc --noEmit",
60
60
  "type-check:watch": "npm run type-check -- --watch",
61
- "prepare": "husky"
61
+ "prepare": "husky install"
62
62
  },
63
63
  "devDependencies": {
64
- "@babel/core": "7.25.2",
65
- "@babel/helper-module-imports": "7.24.7",
64
+ "@babel/core": "7.23.7",
65
+ "@babel/helper-module-imports": "7.22.15",
66
66
  "@babel/plugin-proposal-class-properties": "7.18.6",
67
67
  "@babel/plugin-proposal-object-rest-spread": "7.20.7",
68
68
  "@babel/plugin-proposal-optional-chaining": "7.21.0",
69
- "@babel/plugin-transform-object-assign": "7.24.7",
70
- "@babel/preset-env": "7.25.3",
71
- "@babel/preset-typescript": "7.24.7",
72
- "@babel/register": "7.24.6",
73
- "@microsoft/api-documenter": "7.25.9",
74
- "@microsoft/api-extractor": "7.47.4",
69
+ "@babel/plugin-transform-object-assign": "7.23.3",
70
+ "@babel/preset-env": "7.23.7",
71
+ "@babel/preset-typescript": "7.23.3",
72
+ "@babel/register": "7.23.7",
73
+ "@microsoft/api-documenter": "7.23.16",
74
+ "@microsoft/api-extractor": "7.39.1",
75
75
  "@rollup/plugin-alias": "5.1.0",
76
76
  "@rollup/plugin-babel": "6.0.4",
77
- "@rollup/plugin-commonjs": "25.0.8",
77
+ "@rollup/plugin-commonjs": "25.0.7",
78
78
  "@rollup/plugin-node-resolve": "15.2.3",
79
- "@rollup/plugin-replace": "5.0.7",
79
+ "@rollup/plugin-replace": "5.0.5",
80
80
  "@rollup/plugin-terser": "0.4.4",
81
- "@rollup/plugin-typescript": "11.1.6",
82
- "@svta/common-media-library": "0.7.1",
83
- "@types/chai": "4.3.17",
81
+ "@rollup/plugin-typescript": "11.1.5",
82
+ "@svta/common-media-library": "0.6.1",
83
+ "@types/chai": "4.3.11",
84
84
  "@types/chart.js": "2.9.41",
85
- "@types/mocha": "10.0.7",
85
+ "@types/mocha": "10.0.6",
86
86
  "@types/sinon-chai": "3.2.12",
87
- "@typescript-eslint/eslint-plugin": "7.18.0",
88
- "@typescript-eslint/parser": "7.18.0",
87
+ "@typescript-eslint/eslint-plugin": "6.17.0",
88
+ "@typescript-eslint/parser": "6.17.0",
89
89
  "babel-loader": "9.1.3",
90
90
  "babel-plugin-transform-remove-console": "6.9.4",
91
- "chai": "4.5.0",
91
+ "chai": "4.3.10",
92
92
  "chart.js": "2.9.4",
93
- "chromedriver": "127.0.0",
93
+ "chromedriver": "120.0.1",
94
94
  "doctoc": "2.2.1",
95
- "es-check": "7.2.1",
96
- "eslint": "8.57.0",
95
+ "es-check": "7.1.1",
96
+ "eslint": "8.56.0",
97
97
  "eslint-config-prettier": "9.1.0",
98
98
  "eslint-plugin-import": "2.29.1",
99
- "eslint-plugin-mocha": "10.5.0",
100
- "eslint-plugin-n": "17.10.1",
101
- "eslint-plugin-promise": "6.6.0",
99
+ "eslint-plugin-mocha": "10.2.0",
100
+ "eslint-plugin-node": "11.1.0",
101
+ "eslint-plugin-promise": "6.1.1",
102
102
  "eventemitter3": "5.0.1",
103
103
  "http-server": "14.1.1",
104
- "husky": "9.1.4",
104
+ "husky": "8.0.3",
105
105
  "jsonpack": "1.1.5",
106
- "karma": "6.4.4",
106
+ "karma": "6.4.2",
107
107
  "karma-chrome-launcher": "3.2.0",
108
108
  "karma-coverage": "2.2.1",
109
109
  "karma-mocha": "2.0.1",
@@ -111,24 +111,24 @@
111
111
  "karma-rollup-preprocessor": "github:jlmakes/karma-rollup-preprocessor#7a7268d91149307b3cf2888ee4e65ccd079955a3",
112
112
  "karma-sinon-chai": "2.0.2",
113
113
  "karma-sourcemap-loader": "0.4.0",
114
- "lint-staged": "15.2.7",
114
+ "lint-staged": "15.2.0",
115
115
  "markdown-styles": "3.2.0",
116
- "micromatch": "4.0.7",
117
- "mocha": "10.7.0",
116
+ "micromatch": "4.0.5",
117
+ "mocha": "10.2.0",
118
118
  "node-fetch": "3.3.2",
119
- "npm-run-all2": "6.2.2",
120
- "prettier": "3.3.3",
119
+ "npm-run-all": "4.1.5",
120
+ "prettier": "3.1.1",
121
121
  "promise-polyfill": "8.3.0",
122
- "rollup": "4.19.1",
122
+ "rollup": "4.9.4",
123
123
  "rollup-plugin-istanbul": "5.0.0",
124
124
  "sauce-connect-launcher": "1.3.2",
125
- "selenium-webdriver": "4.23.0",
126
- "semver": "7.6.3",
127
- "sinon": "18.0.0",
125
+ "selenium-webdriver": "4.16.0",
126
+ "semver": "7.5.4",
127
+ "sinon": "17.0.1",
128
128
  "sinon-chai": "3.7.0",
129
- "typescript": "5.4.5",
129
+ "typescript": "5.3.3",
130
130
  "url-toolkit": "2.2.5",
131
- "wrangler": "3.67.1"
131
+ "wrangler": "3.22.4"
132
132
  },
133
- "version": "1.5.14-0.canary.10517"
133
+ "version": "1.5.14"
134
134
  }
package/src/config.ts CHANGED
@@ -17,10 +17,10 @@ import XhrLoader from './utils/xhr-loader';
17
17
  import FetchLoader, { fetchSupported } from './utils/fetch-loader';
18
18
  import Cues from './utils/cues';
19
19
  import { requestMediaKeySystemAccess } from './utils/mediakeys-helper';
20
+ import { ILogger, logger } from './utils/logger';
20
21
 
21
22
  import type Hls from './hls';
22
23
  import type { CuesInterface } from './utils/cues';
23
- import type { ILogger } from './utils/logger';
24
24
  import type { MediaKeyFunc, KeySystems } from './utils/mediakeys-helper';
25
25
  import type {
26
26
  FragmentLoaderContext,
@@ -235,7 +235,6 @@ export type LatencyControllerConfig = {
235
235
  liveSyncDuration?: number;
236
236
  liveMaxLatencyDuration?: number;
237
237
  maxLiveSyncPlaybackRate: number;
238
- liveSyncOnStallIncrease: number;
239
238
  };
240
239
 
241
240
  export type MetadataControllerConfig = {
@@ -353,7 +352,6 @@ export const hlsDefaultConfig: HlsConfig = {
353
352
  nudgeMaxRetry: 3, // used by stream-controller
354
353
  maxFragLookUpTolerance: 0.25, // used by stream-controller
355
354
  liveSyncDurationCount: 3, // used by latency-controller
356
- liveSyncOnStallIncrease: 1, // used by latency-controller
357
355
  liveMaxLatencyDurationCount: Infinity, // used by latency-controller
358
356
  liveSyncDuration: undefined, // used by latency-controller
359
357
  liveMaxLatencyDuration: undefined, // used by latency-controller
@@ -560,7 +558,6 @@ function timelineConfig(): TimelineControllerConfig {
560
558
  export function mergeConfig(
561
559
  defaultConfig: HlsConfig,
562
560
  userConfig: Partial<HlsConfig>,
563
- logger: ILogger,
564
561
  ): HlsConfig {
565
562
  if (
566
563
  (userConfig.liveSyncDurationCount ||
@@ -667,7 +664,7 @@ function deepCpy(obj: any): any {
667
664
  /**
668
665
  * @ignore
669
666
  */
670
- export function enableStreamingMode(config: HlsConfig, logger: ILogger) {
667
+ export function enableStreamingMode(config) {
671
668
  const currentLoader = config.loader;
672
669
  if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
673
670
  // If a developer has configured their own loader, respect that choice
@@ -2,7 +2,7 @@ import EwmaBandWidthEstimator from '../utils/ewma-bandwidth-estimator';
2
2
  import { Events } from '../events';
3
3
  import { ErrorDetails } from '../errors';
4
4
  import { PlaylistLevelType } from '../types/loader';
5
- import { Logger } from '../utils/logger';
5
+ import { logger } from '../utils/logger';
6
6
  import {
7
7
  SUPPORTED_INFO_DEFAULT,
8
8
  getMediaDecodingInfoPromise,
@@ -31,7 +31,7 @@ import type {
31
31
  } from '../types/events';
32
32
  import type { AbrComponentAPI } from '../types/component-api';
33
33
 
34
- class AbrController extends Logger implements AbrComponentAPI {
34
+ class AbrController implements AbrComponentAPI {
35
35
  protected hls: Hls;
36
36
  private lastLevelLoadSec: number = 0;
37
37
  private lastLoadedFragLevel: number = -1;
@@ -48,7 +48,6 @@ class AbrController extends Logger implements AbrComponentAPI {
48
48
  public bwEstimator: EwmaBandWidthEstimator;
49
49
 
50
50
  constructor(hls: Hls) {
51
- super('abr', hls.logger);
52
51
  this.hls = hls;
53
52
  this.bwEstimator = this.initEstimator();
54
53
  this.registerListeners();
@@ -56,7 +55,7 @@ class AbrController extends Logger implements AbrComponentAPI {
56
55
 
57
56
  public resetEstimator(abrEwmaDefaultEstimate?: number) {
58
57
  if (abrEwmaDefaultEstimate) {
59
- this.log(`setting initial bwe to ${abrEwmaDefaultEstimate}`);
58
+ logger.log(`setting initial bwe to ${abrEwmaDefaultEstimate}`);
60
59
  this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
61
60
  }
62
61
  this.firstSelection = -1;
@@ -356,7 +355,7 @@ class AbrController extends Logger implements AbrComponentAPI {
356
355
  }
357
356
 
358
357
  this.clearTimer();
359
- this.warn(`Fragment ${frag.sn}${
358
+ logger.warn(`[abr] Fragment ${frag.sn}${
360
359
  part ? ' part ' + part.index : ''
361
360
  } of level ${frag.level} is loading too slowly;
362
361
  Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s
@@ -480,8 +479,8 @@ class AbrController extends Logger implements AbrComponentAPI {
480
479
  }
481
480
  const firstLevel = this.hls.firstLevel;
482
481
  const clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
483
- this.warn(
484
- `Could not find best starting auto level. Defaulting to first in playlist ${firstLevel} clamped to ${clamped}`,
482
+ logger.warn(
483
+ `[abr] Could not find best starting auto level. Defaulting to first in playlist ${firstLevel} clamped to ${clamped}`,
485
484
  );
486
485
  return clamped;
487
486
  }
@@ -539,9 +538,6 @@ class AbrController extends Logger implements AbrComponentAPI {
539
538
 
540
539
  private getNextABRAutoLevel(): number {
541
540
  const { fragCurrent, partCurrent, hls } = this;
542
- if (hls.levels.length <= 1) {
543
- return hls.loadLevel;
544
- }
545
541
  const { maxAutoLevel, config, minAutoLevel } = hls;
546
542
  const currentFragDuration = partCurrent
547
543
  ? partCurrent.duration
@@ -588,8 +584,8 @@ class AbrController extends Logger implements AbrComponentAPI {
588
584
  ? Math.min(currentFragDuration, config.maxLoadingDelay)
589
585
  : config.maxLoadingDelay;
590
586
  maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
591
- this.info(
592
- `bitrate test took ${Math.round(
587
+ logger.info(
588
+ `[abr] bitrate test took ${Math.round(
593
589
  1000 * bitrateTestDelay,
594
590
  )}ms, set first fragment max fetchDuration to ${Math.round(
595
591
  1000 * maxStarvationDelay,
@@ -608,8 +604,8 @@ class AbrController extends Logger implements AbrComponentAPI {
608
604
  bwFactor,
609
605
  bwUpFactor,
610
606
  );
611
- this.info(
612
- `${
607
+ logger.info(
608
+ `[abr] ${
613
609
  bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty'
614
610
  }, optimal quality level ${bestLevel}`,
615
611
  );
@@ -675,7 +671,6 @@ class AbrController extends Logger implements AbrComponentAPI {
675
671
  const audioTracksByGroup =
676
672
  this.audioTracksByGroup ||
677
673
  (this.audioTracksByGroup = getAudioTracksByGroup(allAudioTracks));
678
- let minStartIndex = -1;
679
674
  if (firstSelection) {
680
675
  if (this.firstSelection !== -1) {
681
676
  return this.firstSelection;
@@ -695,22 +690,15 @@ class AbrController extends Logger implements AbrComponentAPI {
695
690
  audioPreference,
696
691
  videoPreference,
697
692
  );
698
- const {
699
- codecSet,
700
- videoRanges,
701
- minFramerate,
702
- minBitrate,
703
- minIndex,
704
- preferHDR,
705
- } = startTier;
706
- minStartIndex = minIndex;
693
+ const { codecSet, videoRanges, minFramerate, minBitrate, preferHDR } =
694
+ startTier;
707
695
  currentCodecSet = codecSet;
708
696
  currentVideoRange = preferHDR
709
697
  ? videoRanges[videoRanges.length - 1]
710
698
  : videoRanges[0];
711
699
  currentFrameRate = minFramerate;
712
700
  currentBw = Math.max(currentBw, minBitrate);
713
- this.log(`picked start tier ${JSON.stringify(startTier)}`);
701
+ logger.log(`[abr] picked start tier ${JSON.stringify(startTier)}`);
714
702
  } else {
715
703
  currentCodecSet = level?.codecSet;
716
704
  currentVideoRange = level?.videoRange;
@@ -763,19 +751,19 @@ class AbrController extends Logger implements AbrComponentAPI {
763
751
  const levels = this.hls.levels;
764
752
  const index = levels.indexOf(levelInfo);
765
753
  if (decodingInfo.error) {
766
- this.warn(
767
- `MediaCapabilities decodingInfo error: "${
754
+ logger.warn(
755
+ `[abr] MediaCapabilities decodingInfo error: "${
768
756
  decodingInfo.error
769
757
  }" for level ${index} ${JSON.stringify(decodingInfo)}`,
770
758
  );
771
759
  } else if (!decodingInfo.supported) {
772
- this.warn(
773
- `Unsupported MediaCapabilities decodingInfo result for level ${index} ${JSON.stringify(
760
+ logger.warn(
761
+ `[abr] Unsupported MediaCapabilities decodingInfo result for level ${index} ${JSON.stringify(
774
762
  decodingInfo,
775
763
  )}`,
776
764
  );
777
765
  if (index > -1 && levels.length > 1) {
778
- this.log(`Removing unsupported level ${index}`);
766
+ logger.log(`[abr] Removing unsupported level ${index}`);
779
767
  this.hls.removeLevel(index);
780
768
  }
781
769
  }
@@ -797,10 +785,8 @@ class AbrController extends Logger implements AbrComponentAPI {
797
785
  (levelInfo.supportedResult &&
798
786
  !levelInfo.supportedResult.decodingInfoResults?.[0].smooth)
799
787
  ) {
800
- if (!firstSelection || i !== minStartIndex) {
801
- levelsSkipped.push(i);
802
- continue;
803
- }
788
+ levelsSkipped.push(i);
789
+ continue;
804
790
  }
805
791
 
806
792
  const levelDetails = levelInfo.details;
@@ -856,8 +842,8 @@ class AbrController extends Logger implements AbrComponentAPI {
856
842
  (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)
857
843
  ) {
858
844
  if (levelsSkipped.length) {
859
- this.trace(
860
- `Skipped level(s) ${levelsSkipped.join(
845
+ logger.trace(
846
+ `[abr] Skipped level(s) ${levelsSkipped.join(
861
847
  ',',
862
848
  )} of ${maxAutoLevel} max with CODECS and VIDEO-RANGE:"${
863
849
  levels[levelsSkipped[0]].codecs
@@ -866,8 +852,8 @@ class AbrController extends Logger implements AbrComponentAPI {
866
852
  }" ${currentVideoRange}`,
867
853
  );
868
854
  }
869
- this.info(
870
- `switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(
855
+ logger.info(
856
+ `[abr] switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(
871
857
  adjustedbw,
872
858
  )})-bitrate=${Math.round(
873
859
  adjustedbw - bitrate,
@@ -879,7 +865,7 @@ class AbrController extends Logger implements AbrComponentAPI {
879
865
  1,
880
866
  )} fetchDuration:${fetchDuration.toFixed(
881
867
  1,
882
- )} firstSelection:${firstSelection} codecSet:${levelInfo.codecSet} videoRange:${levelInfo.videoRange} hls.loadLevel:${loadLevel}`,
868
+ )} firstSelection:${firstSelection} codecSet:${currentCodecSet} videoRange:${currentVideoRange} hls.loadLevel:${loadLevel}`,
883
869
  );
884
870
  }
885
871
  if (firstSelection) {