@kenzuya/mediabunny 1.26.0 → 1.28.5

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 (237) hide show
  1. package/README.md +1 -1
  2. package/dist/bundles/{mediabunny.mjs → mediabunny.js} +21963 -21388
  3. package/dist/bundles/mediabunny.min.js +490 -0
  4. package/dist/modules/shared/mp3-misc.d.ts.map +1 -1
  5. package/dist/modules/src/adts/adts-demuxer.d.ts +6 -6
  6. package/dist/modules/src/adts/adts-demuxer.d.ts.map +1 -1
  7. package/dist/modules/src/adts/adts-muxer.d.ts +4 -4
  8. package/dist/modules/src/adts/adts-muxer.d.ts.map +1 -1
  9. package/dist/modules/src/adts/adts-reader.d.ts +1 -1
  10. package/dist/modules/src/adts/adts-reader.d.ts.map +1 -1
  11. package/dist/modules/src/avi/avi-demuxer.d.ts +44 -0
  12. package/dist/modules/src/avi/avi-demuxer.d.ts.map +1 -0
  13. package/dist/modules/src/avi/avi-misc.d.ts +88 -0
  14. package/dist/modules/src/avi/avi-misc.d.ts.map +1 -0
  15. package/dist/modules/src/avi/avi-muxer.d.ts +45 -0
  16. package/dist/modules/src/avi/avi-muxer.d.ts.map +1 -0
  17. package/dist/modules/src/avi/riff-writer.d.ts +26 -0
  18. package/dist/modules/src/avi/riff-writer.d.ts.map +1 -0
  19. package/dist/modules/src/codec-data.d.ts +8 -3
  20. package/dist/modules/src/codec-data.d.ts.map +1 -1
  21. package/dist/modules/src/codec.d.ts +10 -10
  22. package/dist/modules/src/codec.d.ts.map +1 -1
  23. package/dist/modules/src/conversion.d.ts +33 -16
  24. package/dist/modules/src/conversion.d.ts.map +1 -1
  25. package/dist/modules/src/custom-coder.d.ts +8 -8
  26. package/dist/modules/src/custom-coder.d.ts.map +1 -1
  27. package/dist/modules/src/demuxer.d.ts +3 -3
  28. package/dist/modules/src/demuxer.d.ts.map +1 -1
  29. package/dist/modules/src/encode.d.ts +8 -8
  30. package/dist/modules/src/encode.d.ts.map +1 -1
  31. package/dist/modules/src/flac/flac-demuxer.d.ts +7 -7
  32. package/dist/modules/src/flac/flac-demuxer.d.ts.map +1 -1
  33. package/dist/modules/src/flac/flac-misc.d.ts +3 -3
  34. package/dist/modules/src/flac/flac-misc.d.ts.map +1 -1
  35. package/dist/modules/src/flac/flac-muxer.d.ts +5 -5
  36. package/dist/modules/src/flac/flac-muxer.d.ts.map +1 -1
  37. package/dist/modules/src/id3.d.ts +3 -3
  38. package/dist/modules/src/id3.d.ts.map +1 -1
  39. package/dist/modules/src/index.d.ts +20 -20
  40. package/dist/modules/src/index.d.ts.map +1 -1
  41. package/dist/modules/src/input-format.d.ts +22 -0
  42. package/dist/modules/src/input-format.d.ts.map +1 -1
  43. package/dist/modules/src/input-track.d.ts +8 -8
  44. package/dist/modules/src/input-track.d.ts.map +1 -1
  45. package/dist/modules/src/input.d.ts +12 -12
  46. package/dist/modules/src/isobmff/isobmff-boxes.d.ts +2 -2
  47. package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
  48. package/dist/modules/src/isobmff/isobmff-demuxer.d.ts +12 -12
  49. package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
  50. package/dist/modules/src/isobmff/isobmff-misc.d.ts.map +1 -1
  51. package/dist/modules/src/isobmff/isobmff-muxer.d.ts +11 -11
  52. package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
  53. package/dist/modules/src/isobmff/isobmff-reader.d.ts +2 -2
  54. package/dist/modules/src/isobmff/isobmff-reader.d.ts.map +1 -1
  55. package/dist/modules/src/matroska/ebml.d.ts +3 -3
  56. package/dist/modules/src/matroska/ebml.d.ts.map +1 -1
  57. package/dist/modules/src/matroska/matroska-demuxer.d.ts +13 -13
  58. package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
  59. package/dist/modules/src/matroska/matroska-input.d.ts +33 -0
  60. package/dist/modules/src/matroska/matroska-input.d.ts.map +1 -0
  61. package/dist/modules/src/matroska/matroska-misc.d.ts.map +1 -1
  62. package/dist/modules/src/matroska/matroska-muxer.d.ts +5 -5
  63. package/dist/modules/src/matroska/matroska-muxer.d.ts.map +1 -1
  64. package/dist/modules/src/media-sink.d.ts +5 -5
  65. package/dist/modules/src/media-sink.d.ts.map +1 -1
  66. package/dist/modules/src/media-source.d.ts +22 -4
  67. package/dist/modules/src/media-source.d.ts.map +1 -1
  68. package/dist/modules/src/metadata.d.ts +2 -2
  69. package/dist/modules/src/metadata.d.ts.map +1 -1
  70. package/dist/modules/src/misc.d.ts +5 -4
  71. package/dist/modules/src/misc.d.ts.map +1 -1
  72. package/dist/modules/src/mp3/mp3-demuxer.d.ts +7 -7
  73. package/dist/modules/src/mp3/mp3-demuxer.d.ts.map +1 -1
  74. package/dist/modules/src/mp3/mp3-muxer.d.ts +4 -4
  75. package/dist/modules/src/mp3/mp3-muxer.d.ts.map +1 -1
  76. package/dist/modules/src/mp3/mp3-reader.d.ts +2 -2
  77. package/dist/modules/src/mp3/mp3-reader.d.ts.map +1 -1
  78. package/dist/modules/src/mp3/mp3-writer.d.ts +1 -1
  79. package/dist/modules/src/mp3/mp3-writer.d.ts.map +1 -1
  80. package/dist/modules/src/muxer.d.ts +4 -4
  81. package/dist/modules/src/muxer.d.ts.map +1 -1
  82. package/dist/modules/src/node.d.ts +1 -1
  83. package/dist/modules/src/ogg/ogg-demuxer.d.ts +7 -7
  84. package/dist/modules/src/ogg/ogg-demuxer.d.ts.map +1 -1
  85. package/dist/modules/src/ogg/ogg-misc.d.ts +1 -1
  86. package/dist/modules/src/ogg/ogg-misc.d.ts.map +1 -1
  87. package/dist/modules/src/ogg/ogg-muxer.d.ts +5 -5
  88. package/dist/modules/src/ogg/ogg-muxer.d.ts.map +1 -1
  89. package/dist/modules/src/ogg/ogg-reader.d.ts +1 -1
  90. package/dist/modules/src/ogg/ogg-reader.d.ts.map +1 -1
  91. package/dist/modules/src/output-format.d.ts +51 -6
  92. package/dist/modules/src/output-format.d.ts.map +1 -1
  93. package/dist/modules/src/output.d.ts +13 -13
  94. package/dist/modules/src/output.d.ts.map +1 -1
  95. package/dist/modules/src/packet.d.ts +1 -1
  96. package/dist/modules/src/packet.d.ts.map +1 -1
  97. package/dist/modules/src/pcm.d.ts.map +1 -1
  98. package/dist/modules/src/reader.d.ts +2 -2
  99. package/dist/modules/src/reader.d.ts.map +1 -1
  100. package/dist/modules/src/sample.d.ts +57 -15
  101. package/dist/modules/src/sample.d.ts.map +1 -1
  102. package/dist/modules/src/source.d.ts +3 -3
  103. package/dist/modules/src/source.d.ts.map +1 -1
  104. package/dist/modules/src/subtitles.d.ts +1 -1
  105. package/dist/modules/src/subtitles.d.ts.map +1 -1
  106. package/dist/modules/src/target.d.ts +2 -2
  107. package/dist/modules/src/target.d.ts.map +1 -1
  108. package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
  109. package/dist/modules/src/wave/riff-writer.d.ts +1 -1
  110. package/dist/modules/src/wave/riff-writer.d.ts.map +1 -1
  111. package/dist/modules/src/wave/wave-demuxer.d.ts +6 -6
  112. package/dist/modules/src/wave/wave-demuxer.d.ts.map +1 -1
  113. package/dist/modules/src/wave/wave-muxer.d.ts +4 -4
  114. package/dist/modules/src/wave/wave-muxer.d.ts.map +1 -1
  115. package/dist/modules/src/writer.d.ts +1 -1
  116. package/dist/modules/src/writer.d.ts.map +1 -1
  117. package/dist/packages/eac3/eac3.wasm +0 -0
  118. package/dist/packages/eac3/mediabunny-eac3.js +1058 -0
  119. package/dist/packages/eac3/mediabunny-eac3.min.js +44 -0
  120. package/dist/packages/mp3-encoder/mediabunny-mp3-encoder.js +694 -0
  121. package/dist/packages/mp3-encoder/mediabunny-mp3-encoder.min.js +58 -0
  122. package/dist/packages/mpeg4/mediabunny-mpeg4.js +1198 -0
  123. package/dist/packages/mpeg4/mediabunny-mpeg4.min.js +44 -0
  124. package/dist/packages/mpeg4/xvid.wasm +0 -0
  125. package/package.json +18 -57
  126. package/dist/bundles/mediabunny.cjs +0 -26140
  127. package/dist/bundles/mediabunny.min.cjs +0 -147
  128. package/dist/bundles/mediabunny.min.mjs +0 -146
  129. package/dist/mediabunny.d.ts +0 -3319
  130. package/dist/modules/shared/mp3-misc.js +0 -147
  131. package/dist/modules/src/adts/adts-demuxer.js +0 -239
  132. package/dist/modules/src/adts/adts-muxer.js +0 -80
  133. package/dist/modules/src/adts/adts-reader.js +0 -63
  134. package/dist/modules/src/codec-data.js +0 -1730
  135. package/dist/modules/src/codec.js +0 -869
  136. package/dist/modules/src/conversion.js +0 -1459
  137. package/dist/modules/src/custom-coder.js +0 -117
  138. package/dist/modules/src/demuxer.js +0 -12
  139. package/dist/modules/src/encode.js +0 -442
  140. package/dist/modules/src/flac/flac-demuxer.js +0 -504
  141. package/dist/modules/src/flac/flac-misc.js +0 -135
  142. package/dist/modules/src/flac/flac-muxer.js +0 -222
  143. package/dist/modules/src/id3.js +0 -848
  144. package/dist/modules/src/index.js +0 -28
  145. package/dist/modules/src/input-format.js +0 -480
  146. package/dist/modules/src/input-track.js +0 -372
  147. package/dist/modules/src/input.js +0 -188
  148. package/dist/modules/src/isobmff/isobmff-boxes.js +0 -1480
  149. package/dist/modules/src/isobmff/isobmff-demuxer.js +0 -2618
  150. package/dist/modules/src/isobmff/isobmff-misc.js +0 -20
  151. package/dist/modules/src/isobmff/isobmff-muxer.js +0 -966
  152. package/dist/modules/src/isobmff/isobmff-reader.js +0 -72
  153. package/dist/modules/src/matroska/ebml.js +0 -653
  154. package/dist/modules/src/matroska/matroska-demuxer.js +0 -2133
  155. package/dist/modules/src/matroska/matroska-misc.js +0 -20
  156. package/dist/modules/src/matroska/matroska-muxer.js +0 -1017
  157. package/dist/modules/src/media-sink.js +0 -1736
  158. package/dist/modules/src/media-source.js +0 -1825
  159. package/dist/modules/src/metadata.js +0 -193
  160. package/dist/modules/src/misc.js +0 -623
  161. package/dist/modules/src/mp3/mp3-demuxer.js +0 -285
  162. package/dist/modules/src/mp3/mp3-muxer.js +0 -123
  163. package/dist/modules/src/mp3/mp3-reader.js +0 -26
  164. package/dist/modules/src/mp3/mp3-writer.js +0 -78
  165. package/dist/modules/src/muxer.js +0 -50
  166. package/dist/modules/src/node.js +0 -9
  167. package/dist/modules/src/ogg/ogg-demuxer.js +0 -763
  168. package/dist/modules/src/ogg/ogg-misc.js +0 -78
  169. package/dist/modules/src/ogg/ogg-muxer.js +0 -353
  170. package/dist/modules/src/ogg/ogg-reader.js +0 -65
  171. package/dist/modules/src/output-format.js +0 -527
  172. package/dist/modules/src/output.js +0 -300
  173. package/dist/modules/src/packet.js +0 -182
  174. package/dist/modules/src/pcm.js +0 -85
  175. package/dist/modules/src/reader.js +0 -236
  176. package/dist/modules/src/sample.js +0 -1056
  177. package/dist/modules/src/source.js +0 -1182
  178. package/dist/modules/src/subtitles.js +0 -575
  179. package/dist/modules/src/target.js +0 -140
  180. package/dist/modules/src/wave/riff-writer.js +0 -30
  181. package/dist/modules/src/wave/wave-demuxer.js +0 -447
  182. package/dist/modules/src/wave/wave-muxer.js +0 -318
  183. package/dist/modules/src/writer.js +0 -370
  184. package/src/adts/adts-demuxer.ts +0 -331
  185. package/src/adts/adts-muxer.ts +0 -111
  186. package/src/adts/adts-reader.ts +0 -85
  187. package/src/codec-data.ts +0 -2078
  188. package/src/codec.ts +0 -1092
  189. package/src/conversion.ts +0 -2112
  190. package/src/custom-coder.ts +0 -197
  191. package/src/demuxer.ts +0 -24
  192. package/src/encode.ts +0 -739
  193. package/src/flac/flac-demuxer.ts +0 -730
  194. package/src/flac/flac-misc.ts +0 -164
  195. package/src/flac/flac-muxer.ts +0 -320
  196. package/src/id3.ts +0 -925
  197. package/src/index.ts +0 -221
  198. package/src/input-format.ts +0 -541
  199. package/src/input-track.ts +0 -529
  200. package/src/input.ts +0 -235
  201. package/src/isobmff/isobmff-boxes.ts +0 -1719
  202. package/src/isobmff/isobmff-demuxer.ts +0 -3190
  203. package/src/isobmff/isobmff-misc.ts +0 -29
  204. package/src/isobmff/isobmff-muxer.ts +0 -1348
  205. package/src/isobmff/isobmff-reader.ts +0 -91
  206. package/src/matroska/ebml.ts +0 -730
  207. package/src/matroska/matroska-demuxer.ts +0 -2481
  208. package/src/matroska/matroska-misc.ts +0 -29
  209. package/src/matroska/matroska-muxer.ts +0 -1276
  210. package/src/media-sink.ts +0 -2179
  211. package/src/media-source.ts +0 -2243
  212. package/src/metadata.ts +0 -320
  213. package/src/misc.ts +0 -798
  214. package/src/mp3/mp3-demuxer.ts +0 -383
  215. package/src/mp3/mp3-muxer.ts +0 -166
  216. package/src/mp3/mp3-reader.ts +0 -34
  217. package/src/mp3/mp3-writer.ts +0 -120
  218. package/src/muxer.ts +0 -88
  219. package/src/node.ts +0 -11
  220. package/src/ogg/ogg-demuxer.ts +0 -1053
  221. package/src/ogg/ogg-misc.ts +0 -116
  222. package/src/ogg/ogg-muxer.ts +0 -497
  223. package/src/ogg/ogg-reader.ts +0 -93
  224. package/src/output-format.ts +0 -945
  225. package/src/output.ts +0 -488
  226. package/src/packet.ts +0 -263
  227. package/src/pcm.ts +0 -112
  228. package/src/reader.ts +0 -323
  229. package/src/sample.ts +0 -1461
  230. package/src/source.ts +0 -1688
  231. package/src/subtitles.ts +0 -711
  232. package/src/target.ts +0 -204
  233. package/src/tsconfig.json +0 -16
  234. package/src/wave/riff-writer.ts +0 -36
  235. package/src/wave/wave-demuxer.ts +0 -529
  236. package/src/wave/wave-muxer.ts +0 -371
  237. package/src/writer.ts +0 -490
package/src/misc.ts DELETED
@@ -1,798 +0,0 @@
1
- /*!
2
- * Copyright (c) 2025-present, Vanilagy and contributors
3
- *
4
- * This Source Code Form is subject to the terms of the Mozilla Public
5
- * License, v. 2.0. If a copy of the MPL was not distributed with this
6
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
- */
8
-
9
- export function assert(x: unknown): asserts x {
10
- if (!x) {
11
- throw new Error('Assertion failed.');
12
- }
13
- }
14
-
15
- /**
16
- * Represents a clockwise rotation in degrees.
17
- * @group Miscellaneous
18
- * @public
19
- */
20
- export type Rotation = 0 | 90 | 180 | 270;
21
-
22
- export const normalizeRotation = (rotation: number) => {
23
- const mappedRotation = (rotation % 360 + 360) % 360;
24
-
25
- if (mappedRotation === 0 || mappedRotation === 90 || mappedRotation === 180 || mappedRotation === 270) {
26
- return mappedRotation as Rotation;
27
- } else {
28
- throw new Error(`Invalid rotation ${rotation}.`);
29
- }
30
- };
31
-
32
- export type TransformationMatrix = [number, number, number, number, number, number, number, number, number];
33
-
34
- export const last = <T>(arr: T[]) => {
35
- return arr && arr[arr.length - 1];
36
- };
37
-
38
- export const isU32 = (value: number) => {
39
- return value >= 0 && value < 2 ** 32;
40
- };
41
-
42
- export class Bitstream {
43
- /** Current offset in bits. */
44
- pos = 0;
45
-
46
- constructor(public bytes: Uint8Array) {}
47
-
48
- seekToByte(byteOffset: number) {
49
- this.pos = 8 * byteOffset;
50
- }
51
-
52
- private readBit() {
53
- const byteIndex = Math.floor(this.pos / 8);
54
- const byte = this.bytes[byteIndex] ?? 0;
55
- const bitIndex = 0b111 - (this.pos & 0b111);
56
- const bit = (byte & (1 << bitIndex)) >> bitIndex;
57
-
58
- this.pos++;
59
- return bit;
60
- }
61
-
62
- readBits(n: number) {
63
- if (n === 1) {
64
- return this.readBit();
65
- }
66
-
67
- let result = 0;
68
-
69
- for (let i = 0; i < n; i++) {
70
- result <<= 1;
71
- result |= this.readBit();
72
- }
73
-
74
- return result;
75
- }
76
-
77
- writeBits(n: number, value: number) {
78
- const end = this.pos + n;
79
-
80
- for (let i = this.pos; i < end; i++) {
81
- const byteIndex = Math.floor(i / 8);
82
- let byte = this.bytes[byteIndex]!;
83
- const bitIndex = 0b111 - (i & 0b111);
84
-
85
- byte &= ~(1 << bitIndex);
86
- byte |= ((value & (1 << (end - i - 1))) >> (end - i - 1)) << bitIndex;
87
- this.bytes[byteIndex] = byte;
88
- }
89
-
90
- this.pos = end;
91
- };
92
-
93
- readAlignedByte() {
94
- // Ensure we're byte-aligned
95
- if (this.pos % 8 !== 0) {
96
- throw new Error('Bitstream is not byte-aligned.');
97
- }
98
-
99
- const byteIndex = this.pos / 8;
100
- const byte = this.bytes[byteIndex] ?? 0;
101
-
102
- this.pos += 8;
103
- return byte;
104
- }
105
-
106
- skipBits(n: number) {
107
- this.pos += n;
108
- }
109
-
110
- getBitsLeft() {
111
- return this.bytes.length * 8 - this.pos;
112
- }
113
-
114
- clone() {
115
- const clone = new Bitstream(this.bytes);
116
- clone.pos = this.pos;
117
- return clone;
118
- }
119
- }
120
-
121
- /** Reads an exponential-Golomb universal code from a Bitstream. */
122
- export const readExpGolomb = (bitstream: Bitstream) => {
123
- let leadingZeroBits = 0;
124
- while (bitstream.readBits(1) === 0 && leadingZeroBits < 32) {
125
- leadingZeroBits++;
126
- }
127
-
128
- if (leadingZeroBits >= 32) {
129
- throw new Error('Invalid exponential-Golomb code.');
130
- }
131
-
132
- const result = (1 << leadingZeroBits) - 1 + bitstream.readBits(leadingZeroBits);
133
- return result;
134
- };
135
-
136
- /** Reads a signed exponential-Golomb universal code from a Bitstream. */
137
- export const readSignedExpGolomb = (bitstream: Bitstream) => {
138
- const codeNum = readExpGolomb(bitstream);
139
-
140
- return ((codeNum & 1) === 0)
141
- ? -(codeNum >> 1)
142
- : ((codeNum + 1) >> 1);
143
- };
144
-
145
- export const writeBits = (bytes: Uint8Array, start: number, end: number, value: number) => {
146
- for (let i = start; i < end; i++) {
147
- const byteIndex = Math.floor(i / 8);
148
- let byte = bytes[byteIndex]!;
149
- const bitIndex = 0b111 - (i & 0b111);
150
-
151
- byte &= ~(1 << bitIndex);
152
- byte |= ((value & (1 << (end - i - 1))) >> (end - i - 1)) << bitIndex;
153
- bytes[byteIndex] = byte;
154
- }
155
- };
156
-
157
- export const toUint8Array = (source: AllowSharedBufferSource): Uint8Array => {
158
- if (source.constructor === Uint8Array) { // We want a true Uint8Array, not something that extends it like Buffer
159
- return source;
160
- } else if (source instanceof ArrayBuffer) {
161
- return new Uint8Array(source);
162
- } else {
163
- return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
164
- }
165
- };
166
-
167
- export const toDataView = (source: AllowSharedBufferSource) => {
168
- if (source.constructor === DataView) {
169
- return source;
170
- } else if (source instanceof ArrayBuffer) {
171
- return new DataView(source);
172
- } else {
173
- return new DataView(source.buffer, source.byteOffset, source.byteLength);
174
- }
175
- };
176
-
177
- export const textDecoder = /* #__PURE__ */ new TextDecoder();
178
- export const textEncoder = /* #__PURE__ */ new TextEncoder();
179
-
180
- export const isIso88591Compatible = (text: string) => {
181
- for (let i = 0; i < text.length; i++) {
182
- const code = text.charCodeAt(i);
183
- if (code > 255) {
184
- return false;
185
- }
186
- }
187
-
188
- return true;
189
- };
190
-
191
- const invertObject = <K extends PropertyKey, V extends PropertyKey>(object: Record<K, V>) => {
192
- return Object.fromEntries(Object.entries(object).map(([key, value]) => [value, key])) as Record<V, K>;
193
- };
194
-
195
- // For the color space mappings, see Rec. ITU-T H.273.
196
-
197
- export const COLOR_PRIMARIES_MAP = {
198
- bt709: 1, // ITU-R BT.709
199
- bt470bg: 5, // ITU-R BT.470BG
200
- smpte170m: 6, // ITU-R BT.601 525 - SMPTE 170M
201
- bt2020: 9, // ITU-R BT.202
202
- smpte432: 12, // SMPTE EG 432-1
203
- };
204
- export const COLOR_PRIMARIES_MAP_INVERSE = /* #__PURE__ */ invertObject(COLOR_PRIMARIES_MAP);
205
-
206
- export const TRANSFER_CHARACTERISTICS_MAP = {
207
- 'bt709': 1, // ITU-R BT.709
208
- 'smpte170m': 6, // SMPTE 170M
209
- 'linear': 8, // Linear transfer characteristics
210
- 'iec61966-2-1': 13, // IEC 61966-2-1
211
- 'pq': 16, // Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system
212
- 'hlg': 18, // Rec. ITU-R BT.2100-2 hybrid loggamma (HLG) system
213
- };
214
- export const TRANSFER_CHARACTERISTICS_MAP_INVERSE = /* #__PURE__ */ invertObject(TRANSFER_CHARACTERISTICS_MAP);
215
-
216
- export const MATRIX_COEFFICIENTS_MAP = {
217
- 'rgb': 0, // Identity
218
- 'bt709': 1, // ITU-R BT.709
219
- 'bt470bg': 5, // ITU-R BT.470BG
220
- 'smpte170m': 6, // SMPTE 170M
221
- 'bt2020-ncl': 9, // ITU-R BT.2020-2 (non-constant luminance)
222
- };
223
- export const MATRIX_COEFFICIENTS_MAP_INVERSE = /* #__PURE__ */ invertObject(MATRIX_COEFFICIENTS_MAP);
224
-
225
- export type RequiredNonNull<T> = {
226
- [K in keyof T]-?: NonNullable<T[K]>;
227
- };
228
-
229
- export const colorSpaceIsComplete = (
230
- colorSpace: VideoColorSpaceInit | undefined,
231
- ): colorSpace is RequiredNonNull<VideoColorSpaceInit> => {
232
- return (
233
- !!colorSpace
234
- && !!colorSpace.primaries
235
- && !!colorSpace.transfer
236
- && !!colorSpace.matrix
237
- && colorSpace.fullRange !== undefined
238
- );
239
- };
240
-
241
- export const isAllowSharedBufferSource = (x: unknown) => {
242
- return (
243
- x instanceof ArrayBuffer
244
- || (typeof SharedArrayBuffer !== 'undefined' && x instanceof SharedArrayBuffer)
245
- || ArrayBuffer.isView(x)
246
- );
247
- };
248
-
249
- export class AsyncMutex {
250
- currentPromise = Promise.resolve();
251
-
252
- async acquire() {
253
- let resolver: () => void;
254
- const nextPromise = new Promise<void>((resolve) => {
255
- resolver = resolve;
256
- });
257
-
258
- const currentPromiseAlias = this.currentPromise;
259
- this.currentPromise = nextPromise;
260
-
261
- await currentPromiseAlias;
262
-
263
- return resolver!;
264
- }
265
- }
266
-
267
- export const bytesToHexString = (bytes: Uint8Array) => {
268
- return [...bytes].map(x => x.toString(16).padStart(2, '0')).join('');
269
- };
270
-
271
- export const reverseBitsU32 = (x: number): number => {
272
- x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
273
- x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
274
- x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
275
- x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
276
- x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);
277
- return x >>> 0; // Ensure it's treated as an unsigned 32-bit integer
278
- };
279
-
280
- /** Returns the smallest index i such that val[i] === key, or -1 if no such index exists. */
281
- export const binarySearchExact = <T>(arr: T[], key: number, valueGetter: (x: T) => number): number => {
282
- let low = 0;
283
- let high = arr.length - 1;
284
- let ans = -1;
285
-
286
- while (low <= high) {
287
- const mid = (low + high) >> 1;
288
- const midVal = valueGetter(arr[mid]!);
289
-
290
- if (midVal === key) {
291
- ans = mid;
292
- high = mid - 1; // Continue searching left to find the lowest index
293
- } else if (midVal < key) {
294
- low = mid + 1;
295
- } else {
296
- high = mid - 1;
297
- }
298
- }
299
-
300
- return ans;
301
- };
302
-
303
- /** Returns the largest index i such that val[i] <= key, or -1 if no such index exists. */
304
- export const binarySearchLessOrEqual = <T>(arr: T[], key: number, valueGetter: (x: T) => number) => {
305
- let low = 0;
306
- let high = arr.length - 1;
307
- let ans = -1;
308
-
309
- while (low <= high) {
310
- const mid = (low + (high - low + 1) / 2) | 0;
311
- const midVal = valueGetter(arr[mid]!);
312
-
313
- if (midVal <= key) {
314
- ans = mid;
315
- low = mid + 1;
316
- } else {
317
- high = mid - 1;
318
- }
319
- }
320
-
321
- return ans;
322
- };
323
-
324
- /** Assumes the array is already sorted. */
325
- export const insertSorted = <T>(arr: T[], item: T, valueGetter: (x: T) => number) => {
326
- const insertionIndex = binarySearchLessOrEqual(arr, valueGetter(item), valueGetter);
327
- arr.splice(insertionIndex + 1, 0, item); // This even behaves correctly for the -1 case
328
- };
329
-
330
- export const promiseWithResolvers = <T = void>() => {
331
- let resolve: (value: T) => void;
332
- let reject: (reason: unknown) => void;
333
- const promise = new Promise<T>((res, rej) => {
334
- resolve = res;
335
- reject = rej;
336
- });
337
-
338
- return { promise, resolve: resolve!, reject: reject! };
339
- };
340
-
341
- export const removeItem = <T>(arr: T[], item: T) => {
342
- const index = arr.indexOf(item);
343
- if (index !== -1) {
344
- arr.splice(index, 1);
345
- }
346
- };
347
-
348
- export const findLast = <T>(arr: T[], predicate: (x: T) => boolean) => {
349
- for (let i = arr.length - 1; i >= 0; i--) {
350
- if (predicate(arr[i]!)) {
351
- return arr[i];
352
- }
353
- }
354
-
355
- return undefined;
356
- };
357
-
358
- export const findLastIndex = <T>(arr: T[], predicate: (x: T) => boolean) => {
359
- for (let i = arr.length - 1; i >= 0; i--) {
360
- if (predicate(arr[i]!)) {
361
- return i;
362
- }
363
- }
364
-
365
- return -1;
366
- };
367
-
368
- /**
369
- * Sync or async iterable.
370
- * @group Miscellaneous
371
- * @public
372
- */
373
- export type AnyIterable<T> =
374
- | Iterable<T>
375
- | AsyncIterable<T>;
376
-
377
- export const toAsyncIterator = async function* <T>(source: AnyIterable<T>): AsyncGenerator<T, void, unknown> {
378
- if (Symbol.iterator in source) {
379
- // @ts-expect-error Trust me
380
- yield* source[Symbol.iterator]();
381
- } else {
382
- // @ts-expect-error Trust me
383
- yield* source[Symbol.asyncIterator]();
384
- }
385
- };
386
-
387
- export const validateAnyIterable = (iterable: AnyIterable<unknown>) => {
388
- if (!(Symbol.iterator in iterable) && !(Symbol.asyncIterator in iterable)) {
389
- throw new TypeError('Argument must be an iterable or async iterable.');
390
- }
391
- };
392
-
393
- export const assertNever = (x: never) => {
394
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
395
- throw new Error(`Unexpected value: ${x}`);
396
- };
397
-
398
- export const getUint24 = (view: DataView, byteOffset: number, littleEndian: boolean) => {
399
- const byte1 = view.getUint8(byteOffset);
400
- const byte2 = view.getUint8(byteOffset + 1);
401
- const byte3 = view.getUint8(byteOffset + 2);
402
-
403
- if (littleEndian) {
404
- return byte1 | (byte2 << 8) | (byte3 << 16);
405
- } else {
406
- return (byte1 << 16) | (byte2 << 8) | byte3;
407
- }
408
- };
409
-
410
- export const getInt24 = (view: DataView, byteOffset: number, littleEndian: boolean) => {
411
- // The left shift pushes the most significant bit into the sign bit region, and the subsequent right shift
412
- // then correctly interprets the sign bit.
413
- return getUint24(view, byteOffset, littleEndian) << 8 >> 8;
414
- };
415
-
416
- export const setUint24 = (view: DataView, byteOffset: number, value: number, littleEndian: boolean) => {
417
- // Ensure the value is within 24-bit unsigned range (0 to 16777215)
418
- value = value >>> 0; // Convert to unsigned 32-bit
419
- value = value & 0xFFFFFF; // Mask to 24 bits
420
-
421
- if (littleEndian) {
422
- view.setUint8(byteOffset, value & 0xFF);
423
- view.setUint8(byteOffset + 1, (value >>> 8) & 0xFF);
424
- view.setUint8(byteOffset + 2, (value >>> 16) & 0xFF);
425
- } else {
426
- view.setUint8(byteOffset, (value >>> 16) & 0xFF);
427
- view.setUint8(byteOffset + 1, (value >>> 8) & 0xFF);
428
- view.setUint8(byteOffset + 2, value & 0xFF);
429
- }
430
- };
431
-
432
- export const setInt24 = (view: DataView, byteOffset: number, value: number, littleEndian: boolean) => {
433
- // Ensure the value is within 24-bit signed range (-8388608 to 8388607)
434
- value = clamp(value, -8388608, 8388607);
435
-
436
- // Convert negative values to their 24-bit representation
437
- if (value < 0) {
438
- value = (value + 0x1000000) & 0xFFFFFF;
439
- }
440
-
441
- setUint24(view, byteOffset, value, littleEndian);
442
- };
443
-
444
- export const setInt64 = (view: DataView, byteOffset: number, value: number, littleEndian: boolean) => {
445
- if (littleEndian) {
446
- view.setUint32(byteOffset + 0, value, true);
447
- view.setInt32(byteOffset + 4, Math.floor(value / 2 ** 32), true);
448
- } else {
449
- view.setInt32(byteOffset + 0, Math.floor(value / 2 ** 32), true);
450
- view.setUint32(byteOffset + 4, value, true);
451
- }
452
- };
453
-
454
- /**
455
- * Calls a function on each value spat out by an async generator. The reason for writing this manually instead of
456
- * using a generator function is that the generator function queues return() calls - here, we forward them immediately.
457
- */
458
- export const mapAsyncGenerator = <T, U>(
459
- generator: AsyncGenerator<T, void, unknown>,
460
- map: (t: T) => U,
461
- ): AsyncGenerator<U, void, unknown> => {
462
- return {
463
- async next() {
464
- const result = await generator.next();
465
- if (result.done) {
466
- return { value: undefined, done: true };
467
- } else {
468
- return { value: map(result.value), done: false };
469
- }
470
- },
471
- return() {
472
- return generator.return() as ReturnType<AsyncGenerator<U, void, unknown>['return']>;
473
- },
474
- throw(error) {
475
- return generator.throw(error) as ReturnType<AsyncGenerator<U, void, unknown>['throw']>;
476
- },
477
- [Symbol.asyncIterator]() {
478
- return this;
479
- },
480
- };
481
- };
482
-
483
- export const clamp = (value: number, min: number, max: number) => {
484
- return Math.max(min, Math.min(max, value));
485
- };
486
-
487
- export const UNDETERMINED_LANGUAGE = 'und';
488
-
489
- export const roundIfAlmostInteger = (value: number) => {
490
- const rounded = Math.round(value);
491
-
492
- if (Math.abs(value / rounded - 1) < 10 * Number.EPSILON) {
493
- return rounded;
494
- } else {
495
- return value;
496
- }
497
- };
498
-
499
- export const roundToMultiple = (value: number, multiple: number) => {
500
- return Math.round(value / multiple) * multiple;
501
- };
502
-
503
- export const ilog = (x: number) => {
504
- let ret = 0;
505
- while (x) {
506
- ret++;
507
- x >>= 1;
508
- }
509
- return ret;
510
- };
511
-
512
- const ISO_639_2_REGEX = /^[a-z]{3}$/;
513
- export const isIso639Dash2LanguageCode = (x: string) => {
514
- return ISO_639_2_REGEX.test(x);
515
- };
516
-
517
- // Since the result will be truncated, add a bit of eps to compensate for floating point errors
518
- export const SECOND_TO_MICROSECOND_FACTOR = /* #__PURE__ */ 1e6 * (1 + Number.EPSILON);
519
-
520
- /**
521
- * Sets all keys K of T to be required.
522
- * @group Miscellaneous
523
- * @public
524
- */
525
- export type SetRequired<T, K extends keyof T> = T & Required<Pick<T, K>>;
526
-
527
- /**
528
- * Merges two RequestInit objects with special handling for headers.
529
- * Headers are merged case-insensitively, but original casing is preserved.
530
- * init2 headers take precedence and will override case-insensitive matches from init1.
531
- */
532
- export const mergeRequestInit = (init1: RequestInit, init2: RequestInit): RequestInit => {
533
- const merged: RequestInit = { ...init1, ...init2 };
534
-
535
- // Special handling for headers
536
- if (init1.headers || init2.headers) {
537
- const headers1 = init1.headers ? normalizeHeaders(init1.headers) : {};
538
- const headers2 = init2.headers ? normalizeHeaders(init2.headers) : {};
539
-
540
- const mergedHeaders = { ...headers1 };
541
-
542
- // For each header in headers2, check if a case-insensitive match exists in mergedHeaders
543
- Object.entries(headers2).forEach(([key2, value2]) => {
544
- const existingKey = Object.keys(mergedHeaders).find(
545
- key1 => key1.toLowerCase() === key2.toLowerCase(),
546
- );
547
-
548
- if (existingKey) {
549
- delete mergedHeaders[existingKey];
550
- }
551
-
552
- mergedHeaders[key2] = value2;
553
- });
554
-
555
- merged.headers = mergedHeaders;
556
- }
557
-
558
- return merged;
559
- };
560
-
561
- /** Normalizes HeadersInit to a Record<string, string> format. */
562
- const normalizeHeaders = (headers: HeadersInit): Record<string, string> => {
563
- if (headers instanceof Headers) {
564
- const result: Record<string, string> = {};
565
- headers.forEach((value, key) => {
566
- result[key] = value;
567
- });
568
- return result;
569
- }
570
-
571
- if (Array.isArray(headers)) {
572
- const result: Record<string, string> = {};
573
- headers.forEach(([key, value]) => {
574
- result[key] = value;
575
- });
576
- return result;
577
- }
578
-
579
- return headers;
580
- };
581
-
582
- export const retriedFetch = async (
583
- fetchFn: typeof fetch,
584
- url: string | URL | Request,
585
- requestInit: RequestInit,
586
- getRetryDelay: (previousAttempts: number, error: unknown, url: string | URL | Request) => number | null,
587
- ) => {
588
- let attempts = 0;
589
-
590
- while (true) {
591
- try {
592
- return await fetchFn(url, requestInit);
593
- } catch (error) {
594
- attempts++;
595
- const retryDelayInSeconds = getRetryDelay(attempts, error, url);
596
-
597
- if (retryDelayInSeconds === null) {
598
- throw error;
599
- }
600
-
601
- console.error('Retrying failed fetch. Error:', error);
602
-
603
- if (!Number.isFinite(retryDelayInSeconds) || retryDelayInSeconds < 0) {
604
- throw new TypeError('Retry delay must be a non-negative finite number.');
605
- }
606
-
607
- if (retryDelayInSeconds > 0) {
608
- await new Promise(resolve => setTimeout(resolve, 1000 * retryDelayInSeconds));
609
- }
610
- }
611
- }
612
- };
613
-
614
- export const computeRationalApproximation = (x: number, maxDenominator: number) => {
615
- // Handle negative numbers
616
- const sign = x < 0 ? -1 : 1;
617
- x = Math.abs(x);
618
-
619
- let prevNumerator = 0, prevDenominator = 1;
620
- let currNumerator = 1, currDenominator = 0;
621
-
622
- // Continued fraction algorithm
623
- let remainder = x;
624
-
625
- while (true) {
626
- const integer = Math.floor(remainder);
627
-
628
- // Calculate next convergent
629
- const nextNumerator = integer * currNumerator + prevNumerator;
630
- const nextDenominator = integer * currDenominator + prevDenominator;
631
-
632
- if (nextDenominator > maxDenominator) {
633
- return {
634
- numerator: sign * currNumerator,
635
- denominator: currDenominator,
636
- };
637
- }
638
-
639
- prevNumerator = currNumerator;
640
- prevDenominator = currDenominator;
641
- currNumerator = nextNumerator;
642
- currDenominator = nextDenominator;
643
-
644
- remainder = 1 / (remainder - integer);
645
-
646
- // Guard against precision issues
647
- if (!isFinite(remainder)) {
648
- break;
649
- }
650
- }
651
-
652
- return {
653
- numerator: sign * currNumerator,
654
- denominator: currDenominator,
655
- };
656
- };
657
-
658
- export class CallSerializer {
659
- currentPromise = Promise.resolve();
660
-
661
- call(fn: () => Promise<void> | void) {
662
- return this.currentPromise = this.currentPromise.then(fn);
663
- }
664
- }
665
-
666
- let isWebKitCache: boolean | null = null;
667
- export const isWebKit = () => {
668
- if (isWebKitCache !== null) {
669
- return isWebKitCache;
670
- }
671
-
672
- // This even returns true for WebKit-wrapping browsers such as Chrome on iOS
673
- return isWebKitCache = !!(typeof navigator !== 'undefined' && navigator.vendor?.match(/apple/i));
674
- };
675
-
676
- let isFirefoxCache: boolean | null = null;
677
- export const isFirefox = () => {
678
- if (isFirefoxCache !== null) {
679
- return isFirefoxCache;
680
- }
681
-
682
- return isFirefoxCache = typeof navigator !== 'undefined' && navigator.userAgent?.includes('Firefox');
683
- };
684
-
685
- let isChromiumCache: boolean | null = null;
686
- export const isChromium = () => {
687
- if (isChromiumCache !== null) {
688
- return isChromiumCache;
689
- }
690
-
691
- return isChromiumCache = !!(typeof navigator !== 'undefined' && navigator.vendor?.includes('Google Inc'));
692
- };
693
-
694
- /**
695
- * T or a promise that resolves to T.
696
- * @group Miscellaneous
697
- * @public
698
- */
699
- export type MaybePromise<T> = T | Promise<T>;
700
-
701
- /** Acts like `??` except the condition is -1 and not null/undefined. */
702
- export const coalesceIndex = (a: number, b: number) => {
703
- return a !== -1 ? a : b;
704
- };
705
-
706
- export const closedIntervalsOverlap = (startA: number, endA: number, startB: number, endB: number) => {
707
- return startA <= endB && startB <= endA;
708
- };
709
-
710
- type KeyValuePair<T extends Record<string, unknown>> = {
711
- [K in keyof T]-?: {
712
- key: K;
713
- value: T[K] extends infer R | undefined ? R : T[K];
714
- }
715
- }[keyof T];
716
-
717
- export const keyValueIterator = function* <T extends Record<string, unknown>>(object: T) {
718
- for (const key in object) {
719
- const value = object[key];
720
- if (value === undefined) {
721
- continue;
722
- }
723
-
724
- yield { key, value } as KeyValuePair<T>;
725
- }
726
- };
727
-
728
- export const imageMimeTypeToExtension = (mimeType: string) => {
729
- switch (mimeType.toLowerCase()) {
730
- case 'image/jpeg':
731
- case 'image/jpg':
732
- return '.jpg';
733
- case 'image/png':
734
- return '.png';
735
- case 'image/gif':
736
- return '.gif';
737
- case 'image/webp':
738
- return '.webp';
739
- case 'image/bmp':
740
- return '.bmp';
741
- case 'image/svg+xml':
742
- return '.svg';
743
- case 'image/tiff':
744
- return '.tiff';
745
- case 'image/avif':
746
- return '.avif';
747
- case 'image/x-icon':
748
- case 'image/vnd.microsoft.icon':
749
- return '.ico';
750
- default:
751
- return null;
752
- }
753
- };
754
-
755
- export const base64ToBytes = (base64: string) => {
756
- const decoded = atob(base64);
757
- const bytes = new Uint8Array(decoded.length);
758
-
759
- for (let i = 0; i < decoded.length; i++) {
760
- bytes[i] = decoded.charCodeAt(i);
761
- }
762
-
763
- return bytes;
764
- };
765
-
766
- export const bytesToBase64 = (bytes: Uint8Array) => {
767
- let string = '';
768
-
769
- for (let i = 0; i < bytes.length; i++) {
770
- string += String.fromCharCode(bytes[i]!);
771
- }
772
-
773
- return btoa(string);
774
- };
775
-
776
- export const uint8ArraysAreEqual = (a: Uint8Array, b: Uint8Array) => {
777
- if (a.length !== b.length) {
778
- return false;
779
- }
780
-
781
- for (let i = 0; i < a.length; i++) {
782
- if (a[i] !== b[i]) {
783
- return false;
784
- }
785
- }
786
-
787
- return true;
788
- };
789
-
790
- export const polyfillSymbolDispose = () => {
791
- // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html
792
- // @ts-expect-error Readonly
793
- Symbol.dispose ??= Symbol('Symbol.dispose');
794
- };
795
-
796
- export const isNumber = (x: unknown) => {
797
- return typeof x === 'number' && !Number.isNaN(x);
798
- };