@zenvor/hls.js 1.0.0

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 (159) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +472 -0
  3. package/dist/hls-demo.js +26995 -0
  4. package/dist/hls-demo.js.map +1 -0
  5. package/dist/hls.d.mts +4204 -0
  6. package/dist/hls.d.ts +4204 -0
  7. package/dist/hls.js +40050 -0
  8. package/dist/hls.js.d.ts +4204 -0
  9. package/dist/hls.js.map +1 -0
  10. package/dist/hls.light.js +27145 -0
  11. package/dist/hls.light.js.map +1 -0
  12. package/dist/hls.light.min.js +2 -0
  13. package/dist/hls.light.min.js.map +1 -0
  14. package/dist/hls.light.mjs +26392 -0
  15. package/dist/hls.light.mjs.map +1 -0
  16. package/dist/hls.min.js +2 -0
  17. package/dist/hls.min.js.map +1 -0
  18. package/dist/hls.mjs +38956 -0
  19. package/dist/hls.mjs.map +1 -0
  20. package/dist/hls.worker.js +2 -0
  21. package/dist/hls.worker.js.map +1 -0
  22. package/package.json +143 -0
  23. package/src/config.ts +794 -0
  24. package/src/controller/abr-controller.ts +1019 -0
  25. package/src/controller/algo-data-controller.ts +794 -0
  26. package/src/controller/audio-stream-controller.ts +1099 -0
  27. package/src/controller/audio-track-controller.ts +454 -0
  28. package/src/controller/base-playlist-controller.ts +438 -0
  29. package/src/controller/base-stream-controller.ts +2526 -0
  30. package/src/controller/buffer-controller.ts +2015 -0
  31. package/src/controller/buffer-operation-queue.ts +159 -0
  32. package/src/controller/cap-level-controller.ts +367 -0
  33. package/src/controller/cmcd-controller.ts +422 -0
  34. package/src/controller/content-steering-controller.ts +622 -0
  35. package/src/controller/eme-controller.ts +1617 -0
  36. package/src/controller/error-controller.ts +627 -0
  37. package/src/controller/fps-controller.ts +146 -0
  38. package/src/controller/fragment-finders.ts +256 -0
  39. package/src/controller/fragment-tracker.ts +567 -0
  40. package/src/controller/gap-controller.ts +719 -0
  41. package/src/controller/id3-track-controller.ts +488 -0
  42. package/src/controller/interstitial-player.ts +302 -0
  43. package/src/controller/interstitials-controller.ts +2895 -0
  44. package/src/controller/interstitials-schedule.ts +698 -0
  45. package/src/controller/latency-controller.ts +294 -0
  46. package/src/controller/level-controller.ts +776 -0
  47. package/src/controller/stream-controller.ts +1597 -0
  48. package/src/controller/subtitle-stream-controller.ts +508 -0
  49. package/src/controller/subtitle-track-controller.ts +617 -0
  50. package/src/controller/timeline-controller.ts +677 -0
  51. package/src/crypt/aes-crypto.ts +36 -0
  52. package/src/crypt/aes-decryptor.ts +339 -0
  53. package/src/crypt/decrypter-aes-mode.ts +4 -0
  54. package/src/crypt/decrypter.ts +225 -0
  55. package/src/crypt/fast-aes-key.ts +39 -0
  56. package/src/define-plugin.d.ts +17 -0
  57. package/src/demux/audio/aacdemuxer.ts +126 -0
  58. package/src/demux/audio/ac3-demuxer.ts +170 -0
  59. package/src/demux/audio/adts.ts +249 -0
  60. package/src/demux/audio/base-audio-demuxer.ts +205 -0
  61. package/src/demux/audio/dolby.ts +21 -0
  62. package/src/demux/audio/mp3demuxer.ts +85 -0
  63. package/src/demux/audio/mpegaudio.ts +177 -0
  64. package/src/demux/chunk-cache.ts +42 -0
  65. package/src/demux/dummy-demuxed-track.ts +13 -0
  66. package/src/demux/inject-worker.ts +75 -0
  67. package/src/demux/mp4demuxer.ts +234 -0
  68. package/src/demux/sample-aes.ts +198 -0
  69. package/src/demux/transmuxer-interface.ts +449 -0
  70. package/src/demux/transmuxer-worker.ts +221 -0
  71. package/src/demux/transmuxer.ts +560 -0
  72. package/src/demux/tsdemuxer.ts +1256 -0
  73. package/src/demux/video/avc-video-parser.ts +401 -0
  74. package/src/demux/video/base-video-parser.ts +198 -0
  75. package/src/demux/video/exp-golomb.ts +153 -0
  76. package/src/demux/video/hevc-video-parser.ts +736 -0
  77. package/src/empty-es.js +5 -0
  78. package/src/empty.js +3 -0
  79. package/src/errors.ts +107 -0
  80. package/src/events.ts +548 -0
  81. package/src/exports-default.ts +3 -0
  82. package/src/exports-named.ts +81 -0
  83. package/src/hls.ts +1613 -0
  84. package/src/is-supported.ts +54 -0
  85. package/src/loader/date-range.ts +207 -0
  86. package/src/loader/fragment-loader.ts +403 -0
  87. package/src/loader/fragment.ts +487 -0
  88. package/src/loader/interstitial-asset-list.ts +162 -0
  89. package/src/loader/interstitial-event.ts +337 -0
  90. package/src/loader/key-loader.ts +439 -0
  91. package/src/loader/level-details.ts +203 -0
  92. package/src/loader/level-key.ts +259 -0
  93. package/src/loader/load-stats.ts +17 -0
  94. package/src/loader/m3u8-parser.ts +1072 -0
  95. package/src/loader/playlist-loader.ts +839 -0
  96. package/src/polyfills/number.ts +15 -0
  97. package/src/remux/aac-helper.ts +81 -0
  98. package/src/remux/mp4-generator.ts +1380 -0
  99. package/src/remux/mp4-remuxer.ts +1261 -0
  100. package/src/remux/passthrough-remuxer.ts +434 -0
  101. package/src/task-loop.ts +130 -0
  102. package/src/types/algo.ts +44 -0
  103. package/src/types/buffer.ts +105 -0
  104. package/src/types/component-api.ts +20 -0
  105. package/src/types/demuxer.ts +208 -0
  106. package/src/types/events.ts +574 -0
  107. package/src/types/fragment-tracker.ts +23 -0
  108. package/src/types/level.ts +268 -0
  109. package/src/types/loader.ts +198 -0
  110. package/src/types/media-playlist.ts +92 -0
  111. package/src/types/network-details.ts +3 -0
  112. package/src/types/remuxer.ts +104 -0
  113. package/src/types/track.ts +12 -0
  114. package/src/types/transmuxer.ts +46 -0
  115. package/src/types/tuples.ts +6 -0
  116. package/src/types/vtt.ts +11 -0
  117. package/src/utils/arrays.ts +22 -0
  118. package/src/utils/attr-list.ts +192 -0
  119. package/src/utils/binary-search.ts +46 -0
  120. package/src/utils/buffer-helper.ts +173 -0
  121. package/src/utils/cea-608-parser.ts +1413 -0
  122. package/src/utils/chunker.ts +41 -0
  123. package/src/utils/codecs.ts +314 -0
  124. package/src/utils/cues.ts +96 -0
  125. package/src/utils/discontinuities.ts +174 -0
  126. package/src/utils/encryption-methods-util.ts +21 -0
  127. package/src/utils/error-helper.ts +95 -0
  128. package/src/utils/event-listener-helper.ts +16 -0
  129. package/src/utils/ewma-bandwidth-estimator.ts +97 -0
  130. package/src/utils/ewma.ts +43 -0
  131. package/src/utils/fetch-loader.ts +331 -0
  132. package/src/utils/global.ts +2 -0
  133. package/src/utils/hash.ts +10 -0
  134. package/src/utils/hdr.ts +67 -0
  135. package/src/utils/hex.ts +32 -0
  136. package/src/utils/imsc1-ttml-parser.ts +261 -0
  137. package/src/utils/keysystem-util.ts +45 -0
  138. package/src/utils/level-helper.ts +629 -0
  139. package/src/utils/logger.ts +120 -0
  140. package/src/utils/media-option-attributes.ts +49 -0
  141. package/src/utils/mediacapabilities-helper.ts +301 -0
  142. package/src/utils/mediakeys-helper.ts +210 -0
  143. package/src/utils/mediasource-helper.ts +37 -0
  144. package/src/utils/mp4-tools.ts +1473 -0
  145. package/src/utils/number.ts +3 -0
  146. package/src/utils/numeric-encoding-utils.ts +26 -0
  147. package/src/utils/output-filter.ts +46 -0
  148. package/src/utils/rendition-helper.ts +505 -0
  149. package/src/utils/safe-json-stringify.ts +22 -0
  150. package/src/utils/texttrack-utils.ts +164 -0
  151. package/src/utils/time-ranges.ts +17 -0
  152. package/src/utils/timescale-conversion.ts +46 -0
  153. package/src/utils/utf8-utils.ts +18 -0
  154. package/src/utils/variable-substitution.ts +105 -0
  155. package/src/utils/vttcue.ts +384 -0
  156. package/src/utils/vttparser.ts +497 -0
  157. package/src/utils/webvtt-parser.ts +166 -0
  158. package/src/utils/xhr-loader.ts +337 -0
  159. package/src/version.ts +1 -0
@@ -0,0 +1,259 @@
1
+ import { arrayValuesMatch, optionalArrayValuesMatch } from '../utils/arrays';
2
+ import { isFullSegmentEncryption } from '../utils/encryption-methods-util';
3
+ import { hexToArrayBuffer } from '../utils/hex';
4
+ import { convertDataUriToArrayBytes } from '../utils/keysystem-util';
5
+ import { logger } from '../utils/logger';
6
+ import { KeySystemFormats, parsePlayReadyWRM } from '../utils/mediakeys-helper';
7
+ import { mp4pssh, parseMultiPssh } from '../utils/mp4-tools';
8
+
9
+ let keyUriToKeyIdMap: { [uri: string]: Uint8Array<ArrayBuffer> } = {};
10
+
11
+ export interface DecryptData {
12
+ uri: string;
13
+ method: string;
14
+ keyFormat: string;
15
+ keyFormatVersions: number[];
16
+ iv: Uint8Array<ArrayBuffer> | null;
17
+ key: Uint8Array<ArrayBuffer> | null;
18
+ keyId: Uint8Array<ArrayBuffer> | null;
19
+ pssh: Uint8Array<ArrayBuffer> | null;
20
+ encrypted: boolean;
21
+ isCommonEncryption: boolean;
22
+ }
23
+
24
+ export class LevelKey implements DecryptData {
25
+ public readonly uri: string;
26
+ public readonly method: string;
27
+ public readonly keyFormat: string;
28
+ public readonly keyFormatVersions: number[];
29
+ public readonly encrypted: boolean;
30
+ public readonly isCommonEncryption: boolean;
31
+ public iv: Uint8Array<ArrayBuffer> | null = null;
32
+ public key: Uint8Array<ArrayBuffer> | null = null;
33
+ public keyId: Uint8Array<ArrayBuffer> | null = null;
34
+ public pssh: Uint8Array<ArrayBuffer> | null = null;
35
+
36
+ static clearKeyUriToKeyIdMap() {
37
+ keyUriToKeyIdMap = {};
38
+ }
39
+
40
+ static setKeyIdForUri(uri: string, keyId: Uint8Array<ArrayBuffer>) {
41
+ keyUriToKeyIdMap[uri] = keyId;
42
+ }
43
+
44
+ static addKeyIdForUri(uri: string): Uint8Array<ArrayBuffer> {
45
+ const val = Object.keys(keyUriToKeyIdMap).length % Number.MAX_SAFE_INTEGER;
46
+ const keyId = new Uint8Array(16);
47
+ const dv = new DataView(keyId.buffer, 12, 4); // Just set the last 4 bytes
48
+ dv.setUint32(0, val);
49
+ keyUriToKeyIdMap[uri] = keyId;
50
+ return keyId;
51
+ }
52
+
53
+ constructor(
54
+ method: string,
55
+ uri: string,
56
+ format: string,
57
+ formatversions: number[] = [1],
58
+ iv: Uint8Array<ArrayBuffer> | null = null,
59
+ keyId?: string,
60
+ ) {
61
+ this.method = method;
62
+ this.uri = uri;
63
+ this.keyFormat = format;
64
+ this.keyFormatVersions = formatversions;
65
+ this.iv = iv;
66
+ this.encrypted = method ? method !== 'NONE' : false;
67
+ this.isCommonEncryption =
68
+ this.encrypted && !isFullSegmentEncryption(method);
69
+ if (keyId?.startsWith('0x')) {
70
+ this.keyId = new Uint8Array(hexToArrayBuffer(keyId));
71
+ }
72
+ }
73
+
74
+ public matches(key: LevelKey): boolean {
75
+ return (
76
+ key.uri === this.uri &&
77
+ key.method === this.method &&
78
+ key.encrypted === this.encrypted &&
79
+ key.keyFormat === this.keyFormat &&
80
+ arrayValuesMatch(key.keyFormatVersions, this.keyFormatVersions) &&
81
+ optionalArrayValuesMatch(key.iv, this.iv) &&
82
+ optionalArrayValuesMatch(key.keyId, this.keyId)
83
+ );
84
+ }
85
+
86
+ public isSupported(): boolean {
87
+ // If it's Segment encryption or No encryption, just select that key system
88
+ if (this.method) {
89
+ if (isFullSegmentEncryption(this.method) || this.method === 'NONE') {
90
+ return true;
91
+ }
92
+ if (this.keyFormat === 'identity') {
93
+ // Maintain support for clear SAMPLE-AES with MPEG-3 TS
94
+ return this.method === 'SAMPLE-AES';
95
+ } else if (__USE_EME_DRM__) {
96
+ switch (this.keyFormat) {
97
+ case KeySystemFormats.FAIRPLAY:
98
+ case KeySystemFormats.WIDEVINE:
99
+ case KeySystemFormats.PLAYREADY:
100
+ case KeySystemFormats.CLEARKEY:
101
+ return (
102
+ ['SAMPLE-AES', 'SAMPLE-AES-CENC', 'SAMPLE-AES-CTR'].indexOf(
103
+ this.method,
104
+ ) !== -1
105
+ );
106
+ }
107
+ }
108
+ }
109
+ return false;
110
+ }
111
+
112
+ public getDecryptData(
113
+ sn: number | 'initSegment',
114
+ levelKeys?: { [key: string]: LevelKey | undefined },
115
+ ): LevelKey | null {
116
+ if (!this.encrypted || !this.uri) {
117
+ return null;
118
+ }
119
+
120
+ if (isFullSegmentEncryption(this.method)) {
121
+ let iv = this.iv;
122
+ if (!iv) {
123
+ if (typeof sn !== 'number') {
124
+ // We are fetching decryption data for a initialization segment
125
+ // If the segment was encrypted with AES-128/256
126
+ // It must have an IV defined. We cannot substitute the Segment Number in.
127
+ logger.warn(
128
+ `missing IV for initialization segment with method="${this.method}" - compliance issue`,
129
+ );
130
+
131
+ // Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
132
+ sn = 0;
133
+ }
134
+ iv = createInitializationVector(sn);
135
+ }
136
+ const decryptdata = new LevelKey(
137
+ this.method,
138
+ this.uri,
139
+ 'identity',
140
+ this.keyFormatVersions,
141
+ iv,
142
+ );
143
+ return decryptdata;
144
+ }
145
+
146
+ if (!__USE_EME_DRM__) {
147
+ return this;
148
+ }
149
+
150
+ if (this.keyId) {
151
+ // Handle case where key id is changed in KEY_LOADING event handler #7542#issuecomment-3305203929
152
+ const assignedKeyId = keyUriToKeyIdMap[this.uri];
153
+ if (assignedKeyId && !arrayValuesMatch(this.keyId, assignedKeyId)) {
154
+ LevelKey.setKeyIdForUri(this.uri, this.keyId);
155
+ }
156
+
157
+ if (this.pssh) {
158
+ return this;
159
+ }
160
+ }
161
+
162
+ // Key bytes are signalled the KEYID attribute, typically only found on WideVine KEY tags
163
+ // Initialize keyId if possible
164
+ const keyBytes = convertDataUriToArrayBytes(this.uri);
165
+ if (keyBytes) {
166
+ switch (this.keyFormat) {
167
+ case KeySystemFormats.WIDEVINE:
168
+ // Setting `pssh` on this LevelKey/DecryptData allows HLS.js to generate a session using
169
+ // the playlist-key before the "encrypted" event. (Comment out to only use "encrypted" path.)
170
+ this.pssh = keyBytes;
171
+ // In case of Widevine, if KEYID is not in the playlist, assume only two fields in the pssh KEY tag URI.
172
+ if (!this.keyId) {
173
+ const results = parseMultiPssh(keyBytes.buffer);
174
+ if (results.length) {
175
+ const psshData = results[0];
176
+ this.keyId = psshData.kids?.length ? psshData.kids[0] : null;
177
+ }
178
+ }
179
+ if (!this.keyId) {
180
+ this.keyId = getKeyIdFromPlayReadyKey(levelKeys);
181
+ }
182
+ break;
183
+ case KeySystemFormats.PLAYREADY: {
184
+ const PlayReadyKeySystemUUID = new Uint8Array([
185
+ 0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xab, 0x92, 0xe6,
186
+ 0x5b, 0xe0, 0x88, 0x5f, 0x95,
187
+ ]);
188
+
189
+ // Setting `pssh` on this LevelKey/DecryptData allows HLS.js to generate a session using
190
+ // the playlist-key before the "encrypted" event. (Comment out to only use "encrypted" path.)
191
+ this.pssh = mp4pssh(PlayReadyKeySystemUUID, null, keyBytes);
192
+
193
+ this.keyId = parsePlayReadyWRM(keyBytes);
194
+
195
+ break;
196
+ }
197
+ default: {
198
+ let keydata = keyBytes.subarray(0, 16);
199
+ if (keydata.length !== 16) {
200
+ const padded = new Uint8Array(16);
201
+ padded.set(keydata, 16 - keydata.length);
202
+ keydata = padded;
203
+ }
204
+ this.keyId = keydata;
205
+ break;
206
+ }
207
+ }
208
+ }
209
+
210
+ // Default behavior: get keyId from other KEY tag or URI lookup
211
+ if (this.keyId?.byteLength !== 16) {
212
+ let keyId: Uint8Array<ArrayBuffer> | null | undefined;
213
+ keyId = getKeyIdFromWidevineKey(levelKeys);
214
+ if (!keyId) {
215
+ keyId = getKeyIdFromPlayReadyKey(levelKeys);
216
+ if (!keyId) {
217
+ keyId = keyUriToKeyIdMap[this.uri];
218
+ }
219
+ }
220
+ if (keyId) {
221
+ this.keyId = keyId;
222
+ LevelKey.setKeyIdForUri(this.uri, keyId);
223
+ }
224
+ }
225
+
226
+ return this;
227
+ }
228
+ }
229
+
230
+ function getKeyIdFromWidevineKey(
231
+ levelKeys: { [key: string]: LevelKey | undefined } | undefined,
232
+ ) {
233
+ const widevineKey = levelKeys?.[KeySystemFormats.WIDEVINE];
234
+ if (widevineKey) {
235
+ return widevineKey.keyId;
236
+ }
237
+ return null;
238
+ }
239
+
240
+ function getKeyIdFromPlayReadyKey(
241
+ levelKeys: { [key: string]: LevelKey | undefined } | undefined,
242
+ ) {
243
+ const playReadyKey = levelKeys?.[KeySystemFormats.PLAYREADY];
244
+ if (playReadyKey) {
245
+ const playReadyKeyBytes = convertDataUriToArrayBytes(playReadyKey.uri);
246
+ if (playReadyKeyBytes) {
247
+ return parsePlayReadyWRM(playReadyKeyBytes);
248
+ }
249
+ }
250
+ return null;
251
+ }
252
+
253
+ function createInitializationVector(segmentNumber: number) {
254
+ const uint8View = new Uint8Array(16);
255
+ for (let i = 12; i < 16; i++) {
256
+ uint8View[i] = (segmentNumber >> (8 * (15 - i))) & 0xff;
257
+ }
258
+ return uint8View;
259
+ }
@@ -0,0 +1,17 @@
1
+ import type {
2
+ HlsPerformanceTiming,
3
+ HlsProgressivePerformanceTiming,
4
+ LoaderStats,
5
+ } from '../types/loader';
6
+
7
+ export class LoadStats implements LoaderStats {
8
+ aborted: boolean = false;
9
+ loaded: number = 0;
10
+ retry: number = 0;
11
+ total: number = 0;
12
+ chunkCount: number = 0;
13
+ bwEstimate: number = 0;
14
+ loading: HlsProgressivePerformanceTiming = { start: 0, first: 0, end: 0 };
15
+ parsing: HlsPerformanceTiming = { start: 0, end: 0 };
16
+ buffering: HlsProgressivePerformanceTiming = { start: 0, first: 0, end: 0 };
17
+ }