PluginProbe
Gutenberg / 23.6.2
Gutenberg v23.6.2
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / build / modules / video-conversion / worker.min.js

worker.min.js in Gutenberg 23.6.2, at build/modules/video-conversion/worker.min.js

11,033 lines 400.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 var f={APPLY:"apply",CALLBACK:"callback",PING:"ping",PONG:"pong"},b={PROVIDER:"provider",INJECTOR:"injector"},E=e=>{let n=!!e?.type&&Object.values(f).includes(e.type),t=!!e?.id&&typeof e.id=="string",a=!!e?.path&&Array.isArray(e.path)&&e.path.every(p=>typeof p=="string"),i=!!e?.sender&&Object.values(b).includes(e.sender),r=e?.callbackIds===void 0||Array.isArray(e.callbackIds)&&e.callbackIds.every(p=>typeof p=="string"),m=e?.args===void 0||Array.isArray(e.args),s=e?.error===void 0||typeof e.error=="string",o=!!e?.meta&&e.meta!==null&&typeof e.meta=="object",c=!!e?.namespace&&typeof e.namespace=="string",u=!!e?.timeStamp&&typeof e.timeStamp=="number";return n&&t&&a&&i&&r&&m&&s&&o&&c&&u},N=()=>[void 0,void 0,void 0,void 0].map(()=>Math.floor(Math.random()*(2**53-1)).toString(16)).join("-"),C=N,V=(e,n,...t)=>{let a=setTimeout(()=>{clearTimeout(a),e(...t),a=setInterval(e,n,...t)},0);return()=>clearInterval(a)},W=V,H=(e,n)=>n!==void 0&&e instanceof n,d=H,z=e=>{let n=new WeakSet,t=a=>!a||typeof a!="object"||n.has(a)?[]:(n.add(a),d(a,globalThis.ArrayBuffer)||d(a,globalThis.MessagePort)||d(a,globalThis.ImageBitmap)||d(a,globalThis.OffscreenCanvas)||d(a,globalThis.AudioData)||d(a,globalThis.VideoFrame)||d(a,globalThis.RTCDataChannel)||d(a,globalThis.MediaSourceHandle)||d(a,globalThis.MIDIAccess)||d(a,globalThis.MediaStreamTrack)||d(a,globalThis.ReadableStream)||d(a,globalThis.WritableStream)||d(a,globalThis.TransformStream)?[a]:Array.isArray(a)?a.flatMap(t):Object.values(a).flatMap(t));return t(e)},w=z,A=Symbol("PROXY_MARKER"),G=async(e,n)=>{let t,a,i=new Set,r=new Promise((s,o)=>{t=W(async()=>{try{let c=C(),u=await e.onMessage(l=>{if(!E(l))return;let g=l;g.namespace===n.namespace&&g.sender===b.PROVIDER&&g.type===f.PONG&&g.id===c&&s()});u&&i.add(u);let p={type:f.PING,sender:b.INJECTOR,id:c,path:[],meta:{},namespace:n.namespace,timeStamp:Date.now()};e.sendMessage(p,n.transfer?w(p):[])}catch(c){o(c)}},n.heartbeatInterval)}),m=new Promise((s,o)=>{let c=setTimeout(()=>o(Error(`Provider unavailable: heartbeat check timeout ${n.heartbeatTimeout}ms.`)),n.heartbeatTimeout);a=()=>clearTimeout(c)});await Promise.race([r,m]).finally(()=>{t(),a(),i.forEach(s=>s()),i.clear()})},j=(e,n,t)=>(n.onMessage(async a=>{if(!E(a))return;let i=a;if(i.namespace===t.namespace&&i.sender===b.INJECTOR)switch(i.type){case f.PING:{let r={type:f.PONG,sender:b.PROVIDER,id:i.id,path:i.path,meta:i.meta,namespace:t.namespace,timeStamp:Date.now()};n.sendMessage(r,t.transfer?w(r):[]);break}case f.APPLY:{try{let m=i.args?.map(s=>i.callbackIds?.includes(s)?(...o)=>{let c={type:f.CALLBACK,sender:b.PROVIDER,id:s,path:i.path,meta:i.meta,data:o,namespace:t.namespace,timeStamp:Date.now()};n.sendMessage(c,t.transfer?w(c):[])}:s);i.data=await(i.path?.reduce((s,o)=>s[o],e)).apply(e,m||[])}catch(m){i.error=m.message}let r={type:f.APPLY,sender:b.PROVIDER,id:i.id,path:i.path,data:i.data,error:i.error,meta:i.meta,namespace:t.namespace,timeStamp:Date.now()};n.sendMessage(r,t.transfer?w(r):[]);break}}}),e),q=(e,n,t)=>{let a=(i,r)=>new Proxy(i,{get(s,o,c){if(s[A])return Reflect.get(s,o,c);let u=()=>{};return u[A]=!0,a(u,[...r,o])},apply(s,o,c){return new Promise(async(u,p)=>{try{t.heartbeatCheck&&await G(n,t);let l=[],g=c.map(y=>{if(typeof y=="function"){let h=C();return l.push(h),n.onMessage(L=>{if(!E(L))return;let k=L;k.namespace===t.namespace&&k.sender===b.PROVIDER&&k.type===f.CALLBACK&&k.id===h&&y(...k.data)}),h}else return y}),D=C(),U=await n.onMessage(y=>{if(!E(y))return;let h=y;h.namespace===t.namespace&&h.sender===b.PROVIDER&&h.type===f.APPLY&&h.id===D&&(h.error?p(Error(h.error)):u(h.data),U?.())}),M={type:f.APPLY,sender:b.INJECTOR,id:D,path:r,args:g,meta:{},callbackIds:l,timeStamp:Date.now(),namespace:t.namespace};n.sendMessage(M,t.transfer?w(M):[])}catch(l){p(l)}})}});return a(e,[])},$=(e,n)=>{let t;return(a,...i)=>t??=j(e(...i),a,n)},X=(e,n)=>{let t;return a=>t??=q(n.backup?Object.freeze(e()):{},a,n)},P=(e,n)=>{let t={namespace:n?.namespace??"__comctx__",heartbeatCheck:n?.heartbeatCheck??!0,heartbeatInterval:n?.heartbeatInterval??300,heartbeatTimeout:n?.heartbeatTimeout??1e3,transfer:n?.transfer??!1,backup:n?.backup??!1};if(t.heartbeatTimeout<=t.heartbeatInterval)throw Error(`Invalid heartbeat config: timeout (${t.heartbeatTimeout}ms) must exceed interval (${t.heartbeatInterval}ms).`);return[$(e,t),X(e,t)]};var R=Symbol("worker");var Q=class{worker;constructor(e){this.worker=e}sendMessage=(e,n)=>{this.worker.postMessage(e,n)};onMessage=e=>{let n=t=>e(t.data);return this.worker.addEventListener("message",n),()=>this.worker.removeEventListener("message",n)}},S=new WeakMap;function x(e,n){e.failure??=n;for(let t of e.pendingRejects)t(e.failure);e.pendingRejects.clear()}function _(e){let[,n]=P(()=>({}),{namespace:"__wordpress_worker__",heartbeatCheck:!1,transfer:!0}),t=n(new Q(e)),a=s=>{let o=s.message;x(r,new Error(o?`Worker error: ${o}`:"Worker error: the worker crashed or failed to load."))},i=()=>{x(r,new Error("Worker error: a message could not be deserialized."))};e.addEventListener("error",a),e.addEventListener("messageerror",i);let r={worker:e,pendingRejects:new Set,removeListeners:()=>{e.removeEventListener("error",a),e.removeEventListener("messageerror",i)}},m=new Proxy(t,{get(s,o){if(o===R)return e;let c=Reflect.get(s,o);return typeof c!="function"?c:(...u)=>r.failure?Promise.reject(r.failure):new Promise((p,l)=>{r.pendingRejects.add(l),Promise.resolve().then(()=>c(...u)).then(g=>{r.pendingRejects.delete(l),p(g)},g=>{r.pendingRejects.delete(l),l(g)})})}});return S.set(m,r),m}function I(e){let n=S.get(e);n&&(x(n,new Error("Worker was terminated.")),n.removeListeners(),S.delete(e),n.worker.terminate())}var O=`// node_modules/comctx/core/dist/index.js
2 var e = { APPLY: \`apply\`, CALLBACK: \`callback\`, PING: \`ping\`, PONG: \`pong\` };
3 var t = { PROVIDER: \`provider\`, INJECTOR: \`injector\` };
4 var n = (n2) => {
5 let r2 = !!n2?.type && Object.values(e).includes(n2.type), i2 = !!n2?.id && typeof n2.id == \`string\`, a2 = !!n2?.path && Array.isArray(n2.path) && n2.path.every((e2) => typeof e2 == \`string\`), o2 = !!n2?.sender && Object.values(t).includes(n2.sender), s2 = n2?.callbackIds === void 0 || Array.isArray(n2.callbackIds) && n2.callbackIds.every((e2) => typeof e2 == \`string\`), c2 = n2?.args === void 0 || Array.isArray(n2.args), l2 = n2?.error === void 0 || typeof n2.error == \`string\`, u2 = !!n2?.meta && n2.meta !== null && typeof n2.meta == \`object\`, d2 = !!n2?.namespace && typeof n2.namespace == \`string\`, f2 = !!n2?.timeStamp && typeof n2.timeStamp == \`number\`;
6 return r2 && i2 && a2 && o2 && s2 && c2 && l2 && u2 && d2 && f2;
7 };
8 var r = () => [...[, , , ,]].map(() => Math.floor(Math.random() * (2 ** 53 - 1)).toString(16)).join(\`-\`);
9 var i = r;
10 var a = (e2, t2, ...n2) => {
11 let r2 = setTimeout(() => {
12 clearTimeout(r2), e2(...n2), r2 = setInterval(e2, t2, ...n2);
13 }, 0);
14 return () => clearInterval(r2);
15 };
16 var o = a;
17 var s = (e2, t2) => t2 !== void 0 && e2 instanceof t2;
18 var c = s;
19 var l = (e2) => {
20 let t2 = /* @__PURE__ */ new WeakSet(), n2 = (e3) => !e3 || typeof e3 != \`object\` || t2.has(e3) ? [] : (t2.add(e3), c(e3, globalThis.ArrayBuffer) || c(e3, globalThis.MessagePort) || c(e3, globalThis.ImageBitmap) || c(e3, globalThis.OffscreenCanvas) || c(e3, globalThis.AudioData) || c(e3, globalThis.VideoFrame) || c(e3, globalThis.RTCDataChannel) || c(e3, globalThis.MediaSourceHandle) || c(e3, globalThis.MIDIAccess) || c(e3, globalThis.MediaStreamTrack) || c(e3, globalThis.ReadableStream) || c(e3, globalThis.WritableStream) || c(e3, globalThis.TransformStream) ? [e3] : Array.isArray(e3) ? e3.flatMap(n2) : Object.values(e3).flatMap(n2));
21 return n2(e2);
22 };
23 var u = l;
24 var d = /* @__PURE__ */ Symbol(\`PROXY_MARKER\`);
25 var f = async (r2, a2) => {
26 let s2, c2, l2 = /* @__PURE__ */ new Set(), d2 = new Promise((c3, d3) => {
27 s2 = o(async () => {
28 try {
29 let o2 = i(), s3 = await r2.onMessage((r3) => {
30 if (!n(r3)) return;
31 let i2 = r3;
32 i2.namespace === a2.namespace && i2.sender === t.PROVIDER && i2.type === e.PONG && i2.id === o2 && c3();
33 });
34 s3 && l2.add(s3);
35 let d4 = { type: e.PING, sender: t.INJECTOR, id: o2, path: [], meta: {}, namespace: a2.namespace, timeStamp: Date.now() };
36 r2.sendMessage(d4, a2.transfer ? u(d4) : []);
37 } catch (e2) {
38 d3(e2);
39 }
40 }, a2.heartbeatInterval);
41 }), f2 = new Promise((e2, t2) => {
42 let n2 = setTimeout(() => t2(Error(\`Provider unavailable: heartbeat check timeout \${a2.heartbeatTimeout}ms.\`)), a2.heartbeatTimeout);
43 c2 = () => clearTimeout(n2);
44 });
45 await Promise.race([d2, f2]).finally(() => {
46 s2(), c2(), l2.forEach((e2) => e2()), l2.clear();
47 });
48 };
49 var p = (r2, i2, a2) => (i2.onMessage(async (o2) => {
50 if (!n(o2)) return;
51 let s2 = o2;
52 if (s2.namespace === a2.namespace && s2.sender === t.INJECTOR) switch (s2.type) {
53 case e.PING: {
54 let n2 = { type: e.PONG, sender: t.PROVIDER, id: s2.id, path: s2.path, meta: s2.meta, namespace: a2.namespace, timeStamp: Date.now() };
55 i2.sendMessage(n2, a2.transfer ? u(n2) : []);
56 break;
57 }
58 case e.APPLY: {
59 try {
60 let n3 = s2.args?.map((n4) => s2.callbackIds?.includes(n4) ? (...r3) => {
61 let o3 = { type: e.CALLBACK, sender: t.PROVIDER, id: n4, path: s2.path, meta: s2.meta, data: r3, namespace: a2.namespace, timeStamp: Date.now() };
62 i2.sendMessage(o3, a2.transfer ? u(o3) : []);
63 } : n4);
64 s2.data = await (s2.path?.reduce((e2, t2) => e2[t2], r2)).apply(r2, n3 || []);
65 } catch (e2) {
66 s2.error = e2.message;
67 }
68 let n2 = { type: e.APPLY, sender: t.PROVIDER, id: s2.id, path: s2.path, data: s2.data, error: s2.error, meta: s2.meta, namespace: a2.namespace, timeStamp: Date.now() };
69 i2.sendMessage(n2, a2.transfer ? u(n2) : []);
70 break;
71 }
72 }
73 }), r2);
74 var m = (r2, a2, o2) => {
75 let s2 = (r3, c2) => {
76 let l2 = new Proxy(r3, { get(e2, t2, n2) {
77 if (e2[d]) return Reflect.get(e2, t2, n2);
78 let r4 = () => {
79 };
80 return r4[d] = true, s2(r4, [...c2, t2]);
81 }, apply(r4, s3, l3) {
82 return new Promise(async (r5, s4) => {
83 try {
84 o2.heartbeatCheck && await f(a2, o2);
85 let d2 = [], p2 = l3.map((r6) => {
86 if (typeof r6 == \`function\`) {
87 let s5 = i();
88 return d2.push(s5), a2.onMessage((i2) => {
89 if (!n(i2)) return;
90 let a3 = i2;
91 a3.namespace === o2.namespace && a3.sender === t.PROVIDER && a3.type === e.CALLBACK && a3.id === s5 && r6(...a3.data);
92 }), s5;
93 } else return r6;
94 }), m2 = i(), h2 = await a2.onMessage((i2) => {
95 if (!n(i2)) return;
96 let a3 = i2;
97 a3.namespace === o2.namespace && a3.sender === t.PROVIDER && a3.type === e.APPLY && a3.id === m2 && (a3.error ? s4(Error(a3.error)) : r5(a3.data), h2?.());
98 }), g2 = { type: e.APPLY, sender: t.INJECTOR, id: m2, path: c2, args: p2, meta: {}, callbackIds: d2, timeStamp: Date.now(), namespace: o2.namespace };
99 a2.sendMessage(g2, o2.transfer ? u(g2) : []);
100 } catch (e2) {
101 s4(e2);
102 }
103 });
104 } });
105 return l2;
106 };
107 return s2(r2, []);
108 };
109 var h = (e2, t2) => {
110 let n2;
111 return (r2, ...i2) => n2 ??= p(e2(...i2), r2, t2);
112 };
113 var g = (e2, t2) => {
114 let n2;
115 return (r2) => n2 ??= m(t2.backup ? Object.freeze(e2()) : {}, r2, t2);
116 };
117 var _ = (e2, t2) => {
118 let n2 = { namespace: t2?.namespace ?? \`__comctx__\`, heartbeatCheck: t2?.heartbeatCheck ?? true, heartbeatInterval: t2?.heartbeatInterval ?? 300, heartbeatTimeout: t2?.heartbeatTimeout ?? 1e3, transfer: t2?.transfer ?? false, backup: t2?.backup ?? false };
119 if (n2.heartbeatTimeout <= n2.heartbeatInterval) throw Error(\`Invalid heartbeat config: timeout (\${n2.heartbeatTimeout}ms) must exceed interval (\${n2.heartbeatInterval}ms).\`);
120 return [h(e2, n2), g(e2, n2)];
121 };
122
123 // packages/worker-threads/build-module/worker-thread.mjs
124 var WorkerProvideAdapter = class {
125 sendMessage = (message, transfer) => {
126 self.postMessage(message, { transfer });
127 };
128 onMessage = (callback) => {
129 const handler = (event) => callback(event.data);
130 self.addEventListener("message", handler);
131 return () => self.removeEventListener("message", handler);
132 };
133 };
134 function normalizeThrowable(error) {
135 if (error instanceof Error && error.message) {
136 return error;
137 }
138 let message = "";
139 try {
140 message = String(error);
141 } catch {
142 }
143 return new Error(message || "Unknown error in worker thread");
144 }
145 function withNormalizedErrors(target) {
146 const wrapped = {};
147 for (const key of Object.keys(target)) {
148 const value = target[key];
149 if (typeof value !== "function") {
150 wrapped[key] = value;
151 continue;
152 }
153 wrapped[key] = async (...args) => {
154 try {
155 return await value.apply(target, args);
156 } catch (error) {
157 throw normalizeThrowable(error);
158 }
159 };
160 }
161 return wrapped;
162 }
163 function expose(target) {
164 const [provide] = _(() => withNormalizedErrors(target), {
165 namespace: "__wordpress_worker__",
166 heartbeatCheck: false,
167 transfer: true
168 });
169 provide(new WorkerProvideAdapter());
170 }
171
172 // node_modules/mediabunny/dist/modules/src/misc.js
173 function assert(x) {
174 if (!x) {
175 throw new Error("Assertion failed.");
176 }
177 }
178 var normalizeRotation = (rotation) => {
179 const mappedRotation = (rotation % 360 + 360) % 360;
180 if (mappedRotation === 0 || mappedRotation === 90 || mappedRotation === 180 || mappedRotation === 270) {
181 return mappedRotation;
182 } else {
183 throw new Error(\`Invalid rotation \${rotation}.\`);
184 }
185 };
186 var last = (arr) => {
187 return arr && arr[arr.length - 1];
188 };
189 var isU32 = (value) => {
190 return value >= 0 && value < 2 ** 32;
191 };
192 var readExpGolomb = (bitstream) => {
193 let leadingZeroBits = 0;
194 while (bitstream.readBits(1) === 0 && leadingZeroBits < 32) {
195 leadingZeroBits++;
196 }
197 if (leadingZeroBits >= 32) {
198 throw new Error("Invalid exponential-Golomb code.");
199 }
200 const result = (1 << leadingZeroBits) - 1 + bitstream.readBits(leadingZeroBits);
201 return result;
202 };
203 var readSignedExpGolomb = (bitstream) => {
204 const codeNum = readExpGolomb(bitstream);
205 return (codeNum & 1) === 0 ? -(codeNum >> 1) : codeNum + 1 >> 1;
206 };
207 var writeBits = (bytes2, start, end, value) => {
208 for (let i2 = start; i2 < end; i2++) {
209 const byteIndex = Math.floor(i2 / 8);
210 let byte = bytes2[byteIndex];
211 const bitIndex = 7 - (i2 & 7);
212 byte &= ~(1 << bitIndex);
213 byte |= (value & 1 << end - i2 - 1) >> end - i2 - 1 << bitIndex;
214 bytes2[byteIndex] = byte;
215 }
216 };
217 var toUint8Array = (source) => {
218 if (source.constructor === Uint8Array) {
219 return source;
220 } else if (ArrayBuffer.isView(source)) {
221 return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
222 } else {
223 return new Uint8Array(source);
224 }
225 };
226 var toDataView = (source) => {
227 if (source.constructor === DataView) {
228 return source;
229 } else if (ArrayBuffer.isView(source)) {
230 return new DataView(source.buffer, source.byteOffset, source.byteLength);
231 } else {
232 return new DataView(source);
233 }
234 };
235 var textEncoder = /* @__PURE__ */ new TextEncoder();
236 var COLOR_PRIMARIES_MAP = {
237 bt709: 1,
238 // ITU-R BT.709
239 bt470bg: 5,
240 // ITU-R BT.470BG
241 smpte170m: 6,
242 // ITU-R BT.601 525 - SMPTE 170M
243 bt2020: 9,
244 // ITU-R BT.202
245 smpte432: 12
246 // SMPTE EG 432-1
247 };
248 var TRANSFER_CHARACTERISTICS_MAP = {
249 "bt709": 1,
250 // ITU-R BT.709
251 "smpte170m": 6,
252 // SMPTE 170M
253 "linear": 8,
254 // Linear transfer characteristics
255 "iec61966-2-1": 13,
256 // IEC 61966-2-1
257 "pq": 16,
258 // Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system
259 "hlg": 18
260 // Rec. ITU-R BT.2100-2 hybrid loggamma (HLG) system
261 };
262 var MATRIX_COEFFICIENTS_MAP = {
263 "rgb": 0,
264 // Identity
265 "bt709": 1,
266 // ITU-R BT.709
267 "bt470bg": 5,
268 // ITU-R BT.470BG
269 "smpte170m": 6,
270 // SMPTE 170M
271 "bt2020-ncl": 9
272 // ITU-R BT.2020-2 (non-constant luminance)
273 };
274 var colorSpaceIsComplete = (colorSpace) => {
275 return !!colorSpace && !!colorSpace.primaries && !!colorSpace.transfer && !!colorSpace.matrix && colorSpace.fullRange !== void 0;
276 };
277 var isAllowSharedBufferSource = (x) => {
278 return x instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && x instanceof SharedArrayBuffer || ArrayBuffer.isView(x);
279 };
280 var AsyncMutex = class {
281 constructor() {
282 this.currentPromise = Promise.resolve();
283 this.pending = 0;
284 }
285 async acquire() {
286 let resolver;
287 const nextPromise = new Promise((resolve) => {
288 let resolved = false;
289 resolver = () => {
290 if (resolved) {
291 return;
292 }
293 resolve();
294 this.pending--;
295 resolved = true;
296 };
297 });
298 const currentPromiseAlias = this.currentPromise;
299 this.currentPromise = nextPromise;
300 this.pending++;
301 await currentPromiseAlias;
302 return resolver;
303 }
304 };
305 var binarySearchLessOrEqual = (arr, key, valueGetter) => {
306 let low = 0;
307 let high = arr.length - 1;
308 let ans = -1;
309 while (low <= high) {
310 const mid = low + (high - low + 1) / 2 | 0;
311 const midVal = valueGetter(arr[mid]);
312 if (midVal <= key) {
313 ans = mid;
314 low = mid + 1;
315 } else {
316 high = mid - 1;
317 }
318 }
319 return ans;
320 };
321 var promiseWithResolvers = () => {
322 let resolve;
323 let reject;
324 const promise = new Promise((res, rej) => {
325 resolve = res;
326 reject = rej;
327 });
328 return { promise, resolve, reject };
329 };
330 var assertNever = (x) => {
331 throw new Error(\`Unexpected value: \${x}\`);
332 };
333 var getUint24 = (view2, byteOffset, littleEndian) => {
334 const byte1 = view2.getUint8(byteOffset);
335 const byte2 = view2.getUint8(byteOffset + 1);
336 const byte3 = view2.getUint8(byteOffset + 2);
337 if (littleEndian) {
338 return byte1 | byte2 << 8 | byte3 << 16;
339 } else {
340 return byte1 << 16 | byte2 << 8 | byte3;
341 }
342 };
343 var setUint24 = (view2, byteOffset, value, littleEndian) => {
344 value = value >>> 0;
345 value = value & 16777215;
346 if (littleEndian) {
347 view2.setUint8(byteOffset, value & 255);
348 view2.setUint8(byteOffset + 1, value >>> 8 & 255);
349 view2.setUint8(byteOffset + 2, value >>> 16 & 255);
350 } else {
351 view2.setUint8(byteOffset, value >>> 16 & 255);
352 view2.setUint8(byteOffset + 1, value >>> 8 & 255);
353 view2.setUint8(byteOffset + 2, value & 255);
354 }
355 };
356 var UNDETERMINED_LANGUAGE = "und";
357 var roundToMultiple = (value, multiple) => {
358 return Math.round(value / multiple) * multiple;
359 };
360 var roundToDivisor = (value, multiple) => {
361 return Math.round(value * multiple) / multiple;
362 };
363 var floorToDivisor = (value, multiple) => {
364 return Math.floor(value * multiple) / multiple;
365 };
366 var ISO_639_2_REGEX = /^[a-z]{3}$/;
367 var isIso639Dash2LanguageCode = (x) => {
368 return ISO_639_2_REGEX.test(x);
369 };
370 var SECOND_TO_MICROSECOND_FACTOR = 1e6 * (1 + Number.EPSILON);
371 var computeRationalApproximation = (x, maxDenominator) => {
372 const sign = x < 0 ? -1 : 1;
373 x = Math.abs(x);
374 let prevNumerator = 0, prevDenominator = 1;
375 let currNumerator = 1, currDenominator = 0;
376 let remainder = x;
377 while (true) {
378 const integer = Math.floor(remainder);
379 const nextNumerator = integer * currNumerator + prevNumerator;
380 const nextDenominator = integer * currDenominator + prevDenominator;
381 if (nextDenominator > maxDenominator) {
382 return {
383 num: sign * currNumerator,
384 den: currDenominator
385 };
386 }
387 prevNumerator = currNumerator;
388 prevDenominator = currDenominator;
389 currNumerator = nextNumerator;
390 currDenominator = nextDenominator;
391 remainder = 1 / (remainder - integer);
392 if (!isFinite(remainder)) {
393 break;
394 }
395 }
396 return {
397 num: sign * currNumerator,
398 den: currDenominator
399 };
400 };
401 var CallSerializer = class {
402 constructor() {
403 this.currentPromise = Promise.resolve();
404 }
405 call(fn) {
406 return this.currentPromise = this.currentPromise.then(fn);
407 }
408 };
409 var isFirefoxCache = null;
410 var isFirefox = () => {
411 if (isFirefoxCache !== null) {
412 return isFirefoxCache;
413 }
414 return isFirefoxCache = typeof navigator !== "undefined" && navigator.userAgent?.includes("Firefox");
415 };
416 var isChromiumCache = null;
417 var isChromium = () => {
418 if (isChromiumCache !== null) {
419 return isChromiumCache;
420 }
421 return isChromiumCache = !!(typeof navigator !== "undefined" && (navigator.vendor?.includes("Google Inc") || /Chrome/.test(navigator.userAgent)));
422 };
423 var chromiumVersionCache = null;
424 var getChromiumVersion = () => {
425 if (chromiumVersionCache !== null) {
426 return chromiumVersionCache;
427 }
428 if (typeof navigator === "undefined") {
429 return null;
430 }
431 const match = /\\bChrome\\/(\\d+)/.exec(navigator.userAgent);
432 if (!match) {
433 return null;
434 }
435 return chromiumVersionCache = Number(match[1]);
436 };
437 var keyValueIterator = function* (object) {
438 for (const key in object) {
439 const value = object[key];
440 if (value === void 0) {
441 continue;
442 }
443 yield { key, value };
444 }
445 };
446 var imageMimeTypeToExtension = (mimeType) => {
447 switch (mimeType.toLowerCase()) {
448 case "image/jpeg":
449 case "image/jpg":
450 return ".jpg";
451 case "image/png":
452 return ".png";
453 case "image/gif":
454 return ".gif";
455 case "image/webp":
456 return ".webp";
457 case "image/bmp":
458 return ".bmp";
459 case "image/svg+xml":
460 return ".svg";
461 case "image/tiff":
462 return ".tiff";
463 case "image/avif":
464 return ".avif";
465 case "image/x-icon":
466 case "image/vnd.microsoft.icon":
467 return ".ico";
468 default:
469 return null;
470 }
471 };
472 var uint8ArraysAreEqual = (a2, b) => {
473 if (a2.length !== b.length) {
474 return false;
475 }
476 for (let i2 = 0; i2 < a2.length; i2++) {
477 if (a2[i2] !== b[i2]) {
478 return false;
479 }
480 }
481 return true;
482 };
483 var polyfillSymbolDispose = () => {
484 Symbol.dispose ??= /* @__PURE__ */ Symbol("Symbol.dispose");
485 };
486 var arrayArgmin = (array, getValue) => {
487 let minIndex = -1;
488 let minValue = Infinity;
489 for (let i2 = 0; i2 < array.length; i2++) {
490 const value = getValue(array[i2]);
491 if (value < minValue) {
492 minValue = value;
493 minIndex = i2;
494 }
495 }
496 return minIndex;
497 };
498 var simplifyRational = (rational) => {
499 assert(Number.isInteger(rational.num));
500 assert(Number.isInteger(rational.den));
501 assert(rational.den !== 0);
502 let a2 = Math.abs(rational.num);
503 let b = Math.abs(rational.den);
504 while (b !== 0) {
505 const t2 = a2 % b;
506 a2 = b;
507 b = t2;
508 }
509 const gcd = a2 || 1;
510 return {
511 num: rational.num / gcd,
512 den: rational.den / gcd
513 };
514 };
515 var validateRectangle = (rect, propertyPath) => {
516 if (typeof rect !== "object" || !rect) {
517 throw new TypeError(\`\${propertyPath} must be an object.\`);
518 }
519 if (!Number.isInteger(rect.left) || rect.left < 0) {
520 throw new TypeError(\`\${propertyPath}.left must be a non-negative integer.\`);
521 }
522 if (!Number.isInteger(rect.top) || rect.top < 0) {
523 throw new TypeError(\`\${propertyPath}.top must be a non-negative integer.\`);
524 }
525 if (!Number.isInteger(rect.width) || rect.width < 0) {
526 throw new TypeError(\`\${propertyPath}.width must be a non-negative integer.\`);
527 }
528 if (!Number.isInteger(rect.height) || rect.height < 0) {
529 throw new TypeError(\`\${propertyPath}.height must be a non-negative integer.\`);
530 }
531 };
532 var toArray = (x) => {
533 if (Array.isArray(x)) {
534 return x;
535 } else {
536 return [x];
537 }
538 };
539 var EventEmitter = class {
540 constructor() {
541 this._listeners = /* @__PURE__ */ new Map();
542 }
543 /** Registers a listener for the given event. Returns a function that, when called, removes the listener again. */
544 on(event, listener, options) {
545 if (!this._listeners.has(event)) {
546 this._listeners.set(event, /* @__PURE__ */ new Set());
547 }
548 const entry = { fn: listener, once: options?.once ?? false };
549 this._listeners.get(event).add(entry);
550 return () => {
551 this._listeners.get(event)?.delete(entry);
552 };
553 }
554 /** @internal */
555 _emit(...args) {
556 const [event, data] = args;
557 const listeners = this._listeners.get(event);
558 if (!listeners) {
559 return;
560 }
561 for (const entry of listeners) {
562 try {
563 entry.fn(data);
564 } catch (error) {
565 console.error(error);
566 }
567 if (entry.once) {
568 listeners.delete(entry);
569 }
570 }
571 }
572 };
573 var isRecordStringString = (value) => {
574 return value !== null && typeof value === "object" && Object.getPrototypeOf(value) === Object.prototype && Object.values(value).every((x) => typeof x === "string");
575 };
576
577 // node_modules/mediabunny/dist/modules/src/logging.js
578 var LogLevel;
579 (function(LogLevel2) {
580 LogLevel2[LogLevel2["Silent"] = 0] = "Silent";
581 LogLevel2[LogLevel2["Errors"] = 1] = "Errors";
582 LogLevel2[LogLevel2["Warnings"] = 2] = "Warnings";
583 LogLevel2[LogLevel2["Info"] = 3] = "Info";
584 })(LogLevel || (LogLevel = {}));
585 var Logging = class _Logging {
586 constructor() {
587 }
588 /** The current log level. Defaults to {@link LogLevel.Info}. */
589 static get level() {
590 return _Logging._level;
591 }
592 static set level(value) {
593 if (value !== LogLevel.Silent && value !== LogLevel.Errors && value !== LogLevel.Warnings && value !== LogLevel.Info) {
594 throw new TypeError("Invalid log level. Use one of the values of the LogLevel enum.");
595 }
596 _Logging._level = value;
597 }
598 /** @internal */
599 static get _emitter() {
600 return _Logging._emitterInstance ??= new EventEmitter();
601 }
602 /** Registers a listener for a log event. Returns a function that, when called, removes the listener again. */
603 static on(event, listener, options) {
604 return _Logging._emitter.on(event, listener, options);
605 }
606 /** @internal */
607 static _error(...args) {
608 _Logging._emitter._emit("error", args);
609 if (_Logging._level >= LogLevel.Errors) {
610 console.error(...args);
611 }
612 }
613 /** @internal */
614 static _warn(...args) {
615 _Logging._emitter._emit("warn", args);
616 if (_Logging._level >= LogLevel.Warnings) {
617 console.warn(...args);
618 }
619 }
620 /** @internal */
621 static _info(...args) {
622 _Logging._emitter._emit("info", args);
623 if (_Logging._level >= LogLevel.Info) {
624 console.info(...args);
625 }
626 }
627 };
628 Logging._level = LogLevel.Info;
629 Logging._emitterInstance = null;
630
631 // node_modules/mediabunny/dist/modules/src/metadata.js
632 var RichImageData = class {
633 /** Creates a new {@link RichImageData}. */
634 constructor(data, mimeType) {
635 this.data = data;
636 this.mimeType = mimeType;
637 if (!(data instanceof Uint8Array)) {
638 throw new TypeError("data must be a Uint8Array.");
639 }
640 if (typeof mimeType !== "string") {
641 throw new TypeError("mimeType must be a string.");
642 }
643 }
644 };
645 var AttachedFile = class {
646 /** Creates a new {@link AttachedFile}. */
647 constructor(data, mimeType, name, description) {
648 this.data = data;
649 this.mimeType = mimeType;
650 this.name = name;
651 this.description = description;
652 if (!(data instanceof Uint8Array)) {
653 throw new TypeError("data must be a Uint8Array.");
654 }
655 if (mimeType !== void 0 && typeof mimeType !== "string") {
656 throw new TypeError("mimeType, when provided, must be a string.");
657 }
658 if (name !== void 0 && typeof name !== "string") {
659 throw new TypeError("name, when provided, must be a string.");
660 }
661 if (description !== void 0 && typeof description !== "string") {
662 throw new TypeError("description, when provided, must be a string.");
663 }
664 }
665 };
666 var validateMetadataTags = (tags) => {
667 if (!tags || typeof tags !== "object") {
668 throw new TypeError("tags must be an object.");
669 }
670 if (tags.title !== void 0 && typeof tags.title !== "string") {
671 throw new TypeError("tags.title, when provided, must be a string.");
672 }
673 if (tags.description !== void 0 && typeof tags.description !== "string") {
674 throw new TypeError("tags.description, when provided, must be a string.");
675 }
676 if (tags.artist !== void 0 && typeof tags.artist !== "string") {
677 throw new TypeError("tags.artist, when provided, must be a string.");
678 }
679 if (tags.album !== void 0 && typeof tags.album !== "string") {
680 throw new TypeError("tags.album, when provided, must be a string.");
681 }
682 if (tags.albumArtist !== void 0 && typeof tags.albumArtist !== "string") {
683 throw new TypeError("tags.albumArtist, when provided, must be a string.");
684 }
685 if (tags.trackNumber !== void 0 && (!Number.isInteger(tags.trackNumber) || tags.trackNumber <= 0)) {
686 throw new TypeError("tags.trackNumber, when provided, must be a positive integer.");
687 }
688 if (tags.tracksTotal !== void 0 && (!Number.isInteger(tags.tracksTotal) || tags.tracksTotal <= 0)) {
689 throw new TypeError("tags.tracksTotal, when provided, must be a positive integer.");
690 }
691 if (tags.discNumber !== void 0 && (!Number.isInteger(tags.discNumber) || tags.discNumber <= 0)) {
692 throw new TypeError("tags.discNumber, when provided, must be a positive integer.");
693 }
694 if (tags.discsTotal !== void 0 && (!Number.isInteger(tags.discsTotal) || tags.discsTotal <= 0)) {
695 throw new TypeError("tags.discsTotal, when provided, must be a positive integer.");
696 }
697 if (tags.genre !== void 0 && typeof tags.genre !== "string") {
698 throw new TypeError("tags.genre, when provided, must be a string.");
699 }
700 if (tags.date !== void 0 && (!(tags.date instanceof Date) || Number.isNaN(tags.date.getTime()))) {
701 throw new TypeError("tags.date, when provided, must be a valid Date.");
702 }
703 if (tags.lyrics !== void 0 && typeof tags.lyrics !== "string") {
704 throw new TypeError("tags.lyrics, when provided, must be a string.");
705 }
706 if (tags.images !== void 0) {
707 if (!Array.isArray(tags.images)) {
708 throw new TypeError("tags.images, when provided, must be an array.");
709 }
710 for (const image of tags.images) {
711 if (!image || typeof image !== "object") {
712 throw new TypeError("Each image in tags.images must be an object.");
713 }
714 if (!(image.data instanceof Uint8Array)) {
715 throw new TypeError("Each image.data must be a Uint8Array.");
716 }
717 if (typeof image.mimeType !== "string") {
718 throw new TypeError("Each image.mimeType must be a string.");
719 }
720 if (!["coverFront", "coverBack", "unknown"].includes(image.kind)) {
721 throw new TypeError("Each image.kind must be 'coverFront', 'coverBack', or 'unknown'.");
722 }
723 }
724 }
725 if (tags.comment !== void 0 && typeof tags.comment !== "string") {
726 throw new TypeError("tags.comment, when provided, must be a string.");
727 }
728 if (tags.raw !== void 0) {
729 if (!tags.raw || typeof tags.raw !== "object") {
730 throw new TypeError("tags.raw, when provided, must be an object.");
731 }
732 for (const value of Object.values(tags.raw)) {
733 if (value !== null && typeof value !== "string" && !(value instanceof Uint8Array) && !(value instanceof RichImageData) && !(value instanceof AttachedFile) && !isRecordStringString(value)) {
734 throw new TypeError("Each value in tags.raw must be a string, Uint8Array, RichImageData, AttachedFile, Record<string, string>, or null.");
735 }
736 }
737 }
738 };
739 var validateTrackDisposition = (disposition) => {
740 if (!disposition || typeof disposition !== "object") {
741 throw new TypeError("disposition must be an object.");
742 }
743 if (disposition.default !== void 0 && typeof disposition.default !== "boolean") {
744 throw new TypeError("disposition.default must be a boolean.");
745 }
746 if (disposition.primary !== void 0 && typeof disposition.primary !== "boolean") {
747 throw new TypeError("disposition.primary must be a boolean.");
748 }
749 if (disposition.forced !== void 0 && typeof disposition.forced !== "boolean") {
750 throw new TypeError("disposition.forced must be a boolean.");
751 }
752 if (disposition.original !== void 0 && typeof disposition.original !== "boolean") {
753 throw new TypeError("disposition.original must be a boolean.");
754 }
755 if (disposition.commentary !== void 0 && typeof disposition.commentary !== "boolean") {
756 throw new TypeError("disposition.commentary must be a boolean.");
757 }
758 if (disposition.hearingImpaired !== void 0 && typeof disposition.hearingImpaired !== "boolean") {
759 throw new TypeError("disposition.hearingImpaired must be a boolean.");
760 }
761 if (disposition.visuallyImpaired !== void 0 && typeof disposition.visuallyImpaired !== "boolean") {
762 throw new TypeError("disposition.visuallyImpaired must be a boolean.");
763 }
764 };
765
766 // node_modules/mediabunny/dist/modules/shared/bitstream.js
767 var Bitstream = class _Bitstream {
768 constructor(bytes2) {
769 this.bytes = bytes2;
770 this.pos = 0;
771 }
772 seekToByte(byteOffset) {
773 this.pos = 8 * byteOffset;
774 }
775 readBit() {
776 const byteIndex = Math.floor(this.pos / 8);
777 const byte = this.bytes[byteIndex] ?? 0;
778 const bitIndex = 7 - (this.pos & 7);
779 const bit = (byte & 1 << bitIndex) >> bitIndex;
780 this.pos++;
781 return bit;
782 }
783 readBits(n2) {
784 if (n2 === 1) {
785 return this.readBit();
786 }
787 let result = 0;
788 for (let i2 = 0; i2 < n2; i2++) {
789 result <<= 1;
790 result |= this.readBit();
791 }
792 return result;
793 }
794 writeBits(n2, value) {
795 const end = this.pos + n2;
796 for (let i2 = this.pos; i2 < end; i2++) {
797 const byteIndex = Math.floor(i2 / 8);
798 let byte = this.bytes[byteIndex];
799 const bitIndex = 7 - (i2 & 7);
800 byte &= ~(1 << bitIndex);
801 byte |= (value & 1 << end - i2 - 1) >> end - i2 - 1 << bitIndex;
802 this.bytes[byteIndex] = byte;
803 }
804 this.pos = end;
805 }
806 readAlignedByte() {
807 if (this.pos % 8 !== 0) {
808 throw new Error("Bitstream is not byte-aligned.");
809 }
810 const byteIndex = this.pos / 8;
811 const byte = this.bytes[byteIndex] ?? 0;
812 this.pos += 8;
813 return byte;
814 }
815 skipBits(n2) {
816 this.pos += n2;
817 }
818 getBitsLeft() {
819 return this.bytes.length * 8 - this.pos;
820 }
821 clone() {
822 const clone = new _Bitstream(this.bytes);
823 clone.pos = this.pos;
824 return clone;
825 }
826 };
827
828 // node_modules/mediabunny/dist/modules/shared/aac-misc.js
829 var aacFrequencyTable = [
830 96e3,
831 88200,
832 64e3,
833 48e3,
834 44100,
835 32e3,
836 24e3,
837 22050,
838 16e3,
839 12e3,
840 11025,
841 8e3,
842 7350
843 ];
844 var aacChannelMap = [-1, 1, 2, 3, 4, 5, 6, 8];
845 var buildAacAudioSpecificConfig = (config) => {
846 let frequencyIndex = aacFrequencyTable.indexOf(config.sampleRate);
847 let customSampleRate = null;
848 if (frequencyIndex === -1) {
849 frequencyIndex = 15;
850 customSampleRate = config.sampleRate;
851 }
852 const channelConfiguration = aacChannelMap.indexOf(config.numberOfChannels);
853 if (channelConfiguration === -1) {
854 throw new TypeError(\`Unsupported number of channels: \${config.numberOfChannels}\`);
855 }
856 let bitCount = 5 + 4 + 4;
857 if (config.objectType >= 32) {
858 bitCount += 6;
859 }
860 if (frequencyIndex === 15) {
861 bitCount += 24;
862 }
863 const byteCount = Math.ceil(bitCount / 8);
864 const bytes2 = new Uint8Array(byteCount);
865 const bitstream = new Bitstream(bytes2);
866 if (config.objectType < 32) {
867 bitstream.writeBits(5, config.objectType);
868 } else {
869 bitstream.writeBits(5, 31);
870 bitstream.writeBits(6, config.objectType - 32);
871 }
872 bitstream.writeBits(4, frequencyIndex);
873 if (frequencyIndex === 15) {
874 bitstream.writeBits(24, customSampleRate);
875 }
876 bitstream.writeBits(4, channelConfiguration);
877 return bytes2;
878 };
879
880 // node_modules/mediabunny/dist/modules/src/codec.js
881 var VIDEO_CODECS = [
882 "avc",
883 "hevc",
884 "vp9",
885 "av1",
886 "vp8"
887 ];
888 var PCM_AUDIO_CODECS = [
889 "pcm-s16",
890 // We don't prefix 'le' so we're compatible with the WebCodecs-registered PCM codec strings
891 "pcm-s16be",
892 "pcm-s24",
893 "pcm-s24be",
894 "pcm-s32",
895 "pcm-s32be",
896 "pcm-f32",
897 "pcm-f32be",
898 "pcm-f64",
899 "pcm-f64be",
900 "pcm-u8",
901 "pcm-s8",
902 "ulaw",
903 "alaw"
904 ];
905 var NON_PCM_AUDIO_CODECS = [
906 "aac",
907 "opus",
908 "mp3",
909 "vorbis",
910 "flac",
911 "ac3",
912 "eac3"
913 ];
914 var AUDIO_CODECS = [
915 ...NON_PCM_AUDIO_CODECS,
916 ...PCM_AUDIO_CODECS
917 ];
918 var SUBTITLE_CODECS = [
919 "webvtt"
920 ];
921 var AVC_LEVEL_TABLE = [
922 { maxMacroblocks: 99, maxBitrate: 64e3, maxDpbMbs: 396, level: 10 },
923 // Level 1
924 { maxMacroblocks: 396, maxBitrate: 192e3, maxDpbMbs: 900, level: 11 },
925 // Level 1.1
926 { maxMacroblocks: 396, maxBitrate: 384e3, maxDpbMbs: 2376, level: 12 },
927 // Level 1.2
928 { maxMacroblocks: 396, maxBitrate: 768e3, maxDpbMbs: 2376, level: 13 },
929 // Level 1.3
930 { maxMacroblocks: 396, maxBitrate: 2e6, maxDpbMbs: 2376, level: 20 },
931 // Level 2
932 { maxMacroblocks: 792, maxBitrate: 4e6, maxDpbMbs: 4752, level: 21 },
933 // Level 2.1
934 { maxMacroblocks: 1620, maxBitrate: 4e6, maxDpbMbs: 8100, level: 22 },
935 // Level 2.2
936 { maxMacroblocks: 1620, maxBitrate: 1e7, maxDpbMbs: 8100, level: 30 },
937 // Level 3
938 { maxMacroblocks: 3600, maxBitrate: 14e6, maxDpbMbs: 18e3, level: 31 },
939 // Level 3.1
940 { maxMacroblocks: 5120, maxBitrate: 2e7, maxDpbMbs: 20480, level: 32 },
941 // Level 3.2
942 { maxMacroblocks: 8192, maxBitrate: 2e7, maxDpbMbs: 32768, level: 40 },
943 // Level 4
944 { maxMacroblocks: 8192, maxBitrate: 5e7, maxDpbMbs: 32768, level: 41 },
945 // Level 4.1
946 { maxMacroblocks: 8704, maxBitrate: 5e7, maxDpbMbs: 34816, level: 42 },
947 // Level 4.2
948 { maxMacroblocks: 22080, maxBitrate: 135e6, maxDpbMbs: 110400, level: 50 },
949 // Level 5
950 { maxMacroblocks: 36864, maxBitrate: 24e7, maxDpbMbs: 184320, level: 51 },
951 // Level 5.1
952 { maxMacroblocks: 36864, maxBitrate: 24e7, maxDpbMbs: 184320, level: 52 },
953 // Level 5.2
954 { maxMacroblocks: 139264, maxBitrate: 24e7, maxDpbMbs: 696320, level: 60 },
955 // Level 6
956 { maxMacroblocks: 139264, maxBitrate: 48e7, maxDpbMbs: 696320, level: 61 },
957 // Level 6.1
958 { maxMacroblocks: 139264, maxBitrate: 8e8, maxDpbMbs: 696320, level: 62 }
959 // Level 6.2
960 ];
961 var HEVC_LEVEL_TABLE = [
962 { maxPictureSize: 36864, maxBitrate: 128e3, tier: "L", level: 30 },
963 // Level 1 (Low Tier)
964 { maxPictureSize: 122880, maxBitrate: 15e5, tier: "L", level: 60 },
965 // Level 2 (Low Tier)
966 { maxPictureSize: 245760, maxBitrate: 3e6, tier: "L", level: 63 },
967 // Level 2.1 (Low Tier)
968 { maxPictureSize: 552960, maxBitrate: 6e6, tier: "L", level: 90 },
969 // Level 3 (Low Tier)
970 { maxPictureSize: 983040, maxBitrate: 1e7, tier: "L", level: 93 },
971 // Level 3.1 (Low Tier)
972 { maxPictureSize: 2228224, maxBitrate: 12e6, tier: "L", level: 120 },
973 // Level 4 (Low Tier)
974 { maxPictureSize: 2228224, maxBitrate: 3e7, tier: "H", level: 120 },
975 // Level 4 (High Tier)
976 { maxPictureSize: 2228224, maxBitrate: 2e7, tier: "L", level: 123 },
977 // Level 4.1 (Low Tier)
978 { maxPictureSize: 2228224, maxBitrate: 5e7, tier: "H", level: 123 },
979 // Level 4.1 (High Tier)
980 { maxPictureSize: 8912896, maxBitrate: 25e6, tier: "L", level: 150 },
981 // Level 5 (Low Tier)
982 { maxPictureSize: 8912896, maxBitrate: 1e8, tier: "H", level: 150 },
983 // Level 5 (High Tier)
984 { maxPictureSize: 8912896, maxBitrate: 4e7, tier: "L", level: 153 },
985 // Level 5.1 (Low Tier)
986 { maxPictureSize: 8912896, maxBitrate: 16e7, tier: "H", level: 153 },
987 // Level 5.1 (High Tier)
988 { maxPictureSize: 8912896, maxBitrate: 6e7, tier: "L", level: 156 },
989 // Level 5.2 (Low Tier)
990 { maxPictureSize: 8912896, maxBitrate: 24e7, tier: "H", level: 156 },
991 // Level 5.2 (High Tier)
992 { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "L", level: 180 },
993 // Level 6 (Low Tier)
994 { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 180 },
995 // Level 6 (High Tier)
996 { maxPictureSize: 35651584, maxBitrate: 12e7, tier: "L", level: 183 },
997 // Level 6.1 (Low Tier)
998 { maxPictureSize: 35651584, maxBitrate: 48e7, tier: "H", level: 183 },
999 // Level 6.1 (High Tier)
1000 { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "L", level: 186 },
1001 // Level 6.2 (Low Tier)
1002 { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 186 }
1003 // Level 6.2 (High Tier)
1004 ];
1005 var VP9_LEVEL_TABLE = [
1006 { maxPictureSize: 36864, maxBitrate: 2e5, level: 10 },
1007 // Level 1
1008 { maxPictureSize: 73728, maxBitrate: 8e5, level: 11 },
1009 // Level 1.1
1010 { maxPictureSize: 122880, maxBitrate: 18e5, level: 20 },
1011 // Level 2
1012 { maxPictureSize: 245760, maxBitrate: 36e5, level: 21 },
1013 // Level 2.1
1014 { maxPictureSize: 552960, maxBitrate: 72e5, level: 30 },
1015 // Level 3
1016 { maxPictureSize: 983040, maxBitrate: 12e6, level: 31 },
1017 // Level 3.1
1018 { maxPictureSize: 2228224, maxBitrate: 18e6, level: 40 },
1019 // Level 4
1020 { maxPictureSize: 2228224, maxBitrate: 3e7, level: 41 },
1021 // Level 4.1
1022 { maxPictureSize: 8912896, maxBitrate: 6e7, level: 50 },
1023 // Level 5
1024 { maxPictureSize: 8912896, maxBitrate: 12e7, level: 51 },
1025 // Level 5.1
1026 { maxPictureSize: 8912896, maxBitrate: 18e7, level: 52 },
1027 // Level 5.2
1028 { maxPictureSize: 35651584, maxBitrate: 18e7, level: 60 },
1029 // Level 6
1030 { maxPictureSize: 35651584, maxBitrate: 24e7, level: 61 },
1031 // Level 6.1
1032 { maxPictureSize: 35651584, maxBitrate: 48e7, level: 62 }
1033 // Level 6.2
1034 ];
1035 var AV1_LEVEL_TABLE = [
1036 { maxPictureSize: 147456, maxBitrate: 15e5, tier: "M", level: 0 },
1037 // Level 2.0 (Main Tier)
1038 { maxPictureSize: 278784, maxBitrate: 3e6, tier: "M", level: 1 },
1039 // Level 2.1 (Main Tier)
1040 { maxPictureSize: 665856, maxBitrate: 6e6, tier: "M", level: 4 },
1041 // Level 3.0 (Main Tier)
1042 { maxPictureSize: 1065024, maxBitrate: 1e7, tier: "M", level: 5 },
1043 // Level 3.1 (Main Tier)
1044 { maxPictureSize: 2359296, maxBitrate: 12e6, tier: "M", level: 8 },
1045 // Level 4.0 (Main Tier)
1046 { maxPictureSize: 2359296, maxBitrate: 3e7, tier: "H", level: 8 },
1047 // Level 4.0 (High Tier)
1048 { maxPictureSize: 2359296, maxBitrate: 2e7, tier: "M", level: 9 },
1049 // Level 4.1 (Main Tier)
1050 { maxPictureSize: 2359296, maxBitrate: 5e7, tier: "H", level: 9 },
1051 // Level 4.1 (High Tier)
1052 { maxPictureSize: 8912896, maxBitrate: 3e7, tier: "M", level: 12 },
1053 // Level 5.0 (Main Tier)
1054 { maxPictureSize: 8912896, maxBitrate: 1e8, tier: "H", level: 12 },
1055 // Level 5.0 (High Tier)
1056 { maxPictureSize: 8912896, maxBitrate: 4e7, tier: "M", level: 13 },
1057 // Level 5.1 (Main Tier)
1058 { maxPictureSize: 8912896, maxBitrate: 16e7, tier: "H", level: 13 },
1059 // Level 5.1 (High Tier)
1060 { maxPictureSize: 8912896, maxBitrate: 6e7, tier: "M", level: 14 },
1061 // Level 5.2 (Main Tier)
1062 { maxPictureSize: 8912896, maxBitrate: 24e7, tier: "H", level: 14 },
1063 // Level 5.2 (High Tier)
1064 { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "M", level: 15 },
1065 // Level 5.3 (Main Tier)
1066 { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 15 },
1067 // Level 5.3 (High Tier)
1068 { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "M", level: 16 },
1069 // Level 6.0 (Main Tier)
1070 { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 16 },
1071 // Level 6.0 (High Tier)
1072 { maxPictureSize: 35651584, maxBitrate: 1e8, tier: "M", level: 17 },
1073 // Level 6.1 (Main Tier)
1074 { maxPictureSize: 35651584, maxBitrate: 48e7, tier: "H", level: 17 },
1075 // Level 6.1 (High Tier)
1076 { maxPictureSize: 35651584, maxBitrate: 16e7, tier: "M", level: 18 },
1077 // Level 6.2 (Main Tier)
1078 { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 18 },
1079 // Level 6.2 (High Tier)
1080 { maxPictureSize: 35651584, maxBitrate: 16e7, tier: "M", level: 19 },
1081 // Level 6.3 (Main Tier)
1082 { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 19 }
1083 // Level 6.3 (High Tier)
1084 ];
1085 var buildVideoCodecString = (codec, width, height, bitrate) => {
1086 if (codec === "avc") {
1087 const profileIndication = 100;
1088 const totalMacroblocks = Math.ceil(width / 16) * Math.ceil(height / 16);
1089 const levelInfo = AVC_LEVEL_TABLE.find((level) => totalMacroblocks <= level.maxMacroblocks && bitrate <= level.maxBitrate) ?? last(AVC_LEVEL_TABLE);
1090 const levelIndication = levelInfo ? levelInfo.level : 0;
1091 const hexProfileIndication = profileIndication.toString(16).padStart(2, "0");
1092 const hexProfileCompatibility = "00";
1093 const hexLevelIndication = levelIndication.toString(16).padStart(2, "0");
1094 return \`avc1.\${hexProfileIndication}\${hexProfileCompatibility}\${hexLevelIndication}\`;
1095 } else if (codec === "hevc") {
1096 const profilePrefix = "";
1097 const profileIdc = 1;
1098 const compatibilityFlags = "6";
1099 const pictureSize = width * height;
1100 const levelInfo = HEVC_LEVEL_TABLE.find((level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate) ?? last(HEVC_LEVEL_TABLE);
1101 const constraintFlags = "B0";
1102 return \`hev1.\${profilePrefix}\${profileIdc}.\${compatibilityFlags}.\${levelInfo.tier}\${levelInfo.level}.\${constraintFlags}\`;
1103 } else if (codec === "vp8") {
1104 return "vp8";
1105 } else if (codec === "vp9") {
1106 const profile = "00";
1107 const pictureSize = width * height;
1108 const levelInfo = VP9_LEVEL_TABLE.find((level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate) ?? last(VP9_LEVEL_TABLE);
1109 const bitDepth = "08";
1110 return \`vp09.\${profile}.\${levelInfo.level.toString().padStart(2, "0")}.\${bitDepth}\`;
1111 } else if (codec === "av1") {
1112 const profile = 0;
1113 const pictureSize = width * height;
1114 const levelInfo = AV1_LEVEL_TABLE.find((level2) => pictureSize <= level2.maxPictureSize && bitrate <= level2.maxBitrate) ?? last(AV1_LEVEL_TABLE);
1115 const level = levelInfo.level.toString().padStart(2, "0");
1116 const bitDepth = "08";
1117 return \`av01.\${profile}.\${level}\${levelInfo.tier}.\${bitDepth}\`;
1118 }
1119 throw new TypeError(\`Unhandled codec '\${codec}'.\`);
1120 };
1121 var generateVp9CodecConfigurationFromCodecString = (codecString) => {
1122 const parts = codecString.split(".");
1123 const profile = Number(parts[1]);
1124 const level = Number(parts[2]);
1125 const bitDepth = Number(parts[3]);
1126 const chromaSubsampling = parts[4] ? Number(parts[4]) : 1;
1127 return [
1128 1,
1129 1,
1130 profile,
1131 2,
1132 1,
1133 level,
1134 3,
1135 1,
1136 bitDepth,
1137 4,
1138 1,
1139 chromaSubsampling
1140 ];
1141 };
1142 var generateAv1CodecConfigurationFromCodecString = (codecString) => {
1143 const parts = codecString.split(".");
1144 const marker = 1;
1145 const version = 1;
1146 const firstByte = (marker << 7) + version;
1147 const profile = Number(parts[1]);
1148 const levelAndTier = parts[2];
1149 const level = Number(levelAndTier.slice(0, -1));
1150 const secondByte = (profile << 5) + level;
1151 const tier = levelAndTier.slice(-1) === "H" ? 1 : 0;
1152 const bitDepth = Number(parts[3]);
1153 const highBitDepth = bitDepth === 8 ? 0 : 1;
1154 const twelveBit = 0;
1155 const monochrome = parts[4] ? Number(parts[4]) : 0;
1156 const chromaSubsamplingX = parts[5] ? Number(parts[5][0]) : 1;
1157 const chromaSubsamplingY = parts[5] ? Number(parts[5][1]) : 1;
1158 const chromaSamplePosition = parts[5] ? Number(parts[5][2]) : 0;
1159 const thirdByte = (tier << 7) + (highBitDepth << 6) + (twelveBit << 5) + (monochrome << 4) + (chromaSubsamplingX << 3) + (chromaSubsamplingY << 2) + chromaSamplePosition;
1160 const initialPresentationDelayPresent = 0;
1161 const fourthByte = initialPresentationDelayPresent;
1162 return [firstByte, secondByte, thirdByte, fourthByte];
1163 };
1164 var OPUS_SAMPLE_RATE = 48e3;
1165 var PCM_CODEC_REGEX = /^pcm-([usf])(\\d+)(be)?$/;
1166 var parsePcmCodec = (codec) => {
1167 assert(PCM_AUDIO_CODECS.includes(codec));
1168 if (codec === "ulaw") {
1169 return { dataType: "ulaw", sampleSize: 1, littleEndian: true, silentValue: 255 };
1170 } else if (codec === "alaw") {
1171 return { dataType: "alaw", sampleSize: 1, littleEndian: true, silentValue: 213 };
1172 }
1173 const match = PCM_CODEC_REGEX.exec(codec);
1174 assert(match);
1175 let dataType;
1176 if (match[1] === "u") {
1177 dataType = "unsigned";
1178 } else if (match[1] === "s") {
1179 dataType = "signed";
1180 } else {
1181 dataType = "float";
1182 }
1183 const sampleSize = Number(match[2]) / 8;
1184 const littleEndian = match[3] !== "be";
1185 const silentValue = codec === "pcm-u8" ? 2 ** 7 : 0;
1186 return { dataType, sampleSize, littleEndian, silentValue };
1187 };
1188 var inferCodecFromCodecString = (codecString) => {
1189 if (codecString.startsWith("avc1") || codecString.startsWith("avc3")) {
1190 return "avc";
1191 } else if (codecString.startsWith("hev1") || codecString.startsWith("hvc1")) {
1192 return "hevc";
1193 } else if (codecString === "vp8") {
1194 return "vp8";
1195 } else if (codecString.startsWith("vp09")) {
1196 return "vp9";
1197 } else if (codecString.startsWith("av01")) {
1198 return "av1";
1199 }
1200 if (codecString === "mp3" || codecString === "mp4a.69" || codecString === "mp4a.6B" || codecString === "mp4a.6b" || codecString === "mp4a.40.34") {
1201 return "mp3";
1202 } else if (codecString.startsWith("mp4a.40.") || codecString === "mp4a.67") {
1203 return "aac";
1204 } else if (codecString === "opus") {
1205 return "opus";
1206 } else if (codecString === "vorbis") {
1207 return "vorbis";
1208 } else if (codecString === "flac") {
1209 return "flac";
1210 } else if (codecString === "ac-3" || codecString === "ac3") {
1211 return "ac3";
1212 } else if (codecString === "ec-3" || codecString === "eac3") {
1213 return "eac3";
1214 } else if (codecString === "ulaw") {
1215 return "ulaw";
1216 } else if (codecString === "alaw") {
1217 return "alaw";
1218 } else if (PCM_CODEC_REGEX.test(codecString)) {
1219 return codecString;
1220 }
1221 if (codecString === "webvtt") {
1222 return "webvtt";
1223 }
1224 return null;
1225 };
1226 var getVideoEncoderConfigExtension = (codec) => {
1227 if (codec === "avc") {
1228 return {
1229 avc: {
1230 format: "avc"
1231 // Ensure the format is not Annex B
1232 }
1233 };
1234 } else if (codec === "hevc") {
1235 return {
1236 hevc: {
1237 format: "hevc"
1238 // Ensure the format is not Annex B
1239 }
1240 };
1241 }
1242 return {};
1243 };
1244 var VALID_VIDEO_CODEC_STRING_PREFIXES = ["avc1", "avc3", "hev1", "hvc1", "vp8", "vp09", "av01"];
1245 var AVC_CODEC_STRING_REGEX = /^(avc1|avc3)\\.[0-9a-fA-F]{6}$/;
1246 var HEVC_CODEC_STRING_REGEX = /^(hev1|hvc1)\\.(?:[ABC]?\\d+)\\.[0-9a-fA-F]{1,8}\\.[LH]\\d+(?:\\.[0-9a-fA-F]{1,2}){0,6}$/;
1247 var VP9_CODEC_STRING_REGEX = /^vp09(?:\\.\\d{2}){3}(?:(?:\\.\\d{2}){5})?$/;
1248 var AV1_CODEC_STRING_REGEX = /^av01\\.\\d\\.\\d{2}[MH]\\.\\d{2}(?:\\.\\d\\.\\d{3}\\.\\d{2}\\.\\d{2}\\.\\d{2}\\.\\d)?$/;
1249 var validateVideoChunkMetadata = (metadata) => {
1250 if (!metadata) {
1251 throw new TypeError("Video chunk metadata must be provided.");
1252 }
1253 if (typeof metadata !== "object") {
1254 throw new TypeError("Video chunk metadata must be an object.");
1255 }
1256 if (!metadata.decoderConfig) {
1257 throw new TypeError("Video chunk metadata must include a decoder configuration.");
1258 }
1259 if (typeof metadata.decoderConfig !== "object") {
1260 throw new TypeError("Video chunk metadata decoder configuration must be an object.");
1261 }
1262 if (typeof metadata.decoderConfig.codec !== "string") {
1263 throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");
1264 }
1265 if (!VALID_VIDEO_CODEC_STRING_PREFIXES.some((prefix) => metadata.decoderConfig.codec.startsWith(prefix))) {
1266 throw new TypeError("Video chunk metadata decoder configuration codec string must be a valid video codec string as specified in the Mediabunny Codec Registry.");
1267 }
1268 if (!Number.isInteger(metadata.decoderConfig.codedWidth) || metadata.decoderConfig.codedWidth <= 0) {
1269 throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");
1270 }
1271 if (!Number.isInteger(metadata.decoderConfig.codedHeight) || metadata.decoderConfig.codedHeight <= 0) {
1272 throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");
1273 }
1274 if (metadata.decoderConfig.displayAspectWidth !== void 0 && (!Number.isInteger(metadata.decoderConfig.displayAspectWidth) || metadata.decoderConfig.displayAspectWidth <= 0)) {
1275 throw new TypeError("Video chunk metadata decoder configuration displayAspectWidth, when defined, must be a positive integer.");
1276 }
1277 if (metadata.decoderConfig.displayAspectHeight !== void 0 && (!Number.isInteger(metadata.decoderConfig.displayAspectHeight) || metadata.decoderConfig.displayAspectHeight <= 0)) {
1278 throw new TypeError("Video chunk metadata decoder configuration displayAspectHeight, when defined, must be a positive integer.");
1279 }
1280 if (metadata.decoderConfig.displayAspectWidth !== void 0 !== (metadata.decoderConfig.displayAspectHeight !== void 0)) {
1281 throw new TypeError("Video chunk metadata decoder configuration must specify both displayAspectWidth and displayAspectHeight, or neither.");
1282 }
1283 if (metadata.decoderConfig.description !== void 0) {
1284 if (!isAllowSharedBufferSource(metadata.decoderConfig.description)) {
1285 throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");
1286 }
1287 }
1288 if (metadata.decoderConfig.colorSpace !== void 0) {
1289 const { colorSpace } = metadata.decoderConfig;
1290 if (typeof colorSpace !== "object") {
1291 throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");
1292 }
1293 const primariesValues = Object.keys(COLOR_PRIMARIES_MAP);
1294 if (colorSpace.primaries != null && !primariesValues.includes(colorSpace.primaries)) {
1295 throw new TypeError(\`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of \${primariesValues.join(", ")}.\`);
1296 }
1297 const transferValues = Object.keys(TRANSFER_CHARACTERISTICS_MAP);
1298 if (colorSpace.transfer != null && !transferValues.includes(colorSpace.transfer)) {
1299 throw new TypeError(\`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of \${transferValues.join(", ")}.\`);
1300 }
1301 const matrixValues = Object.keys(MATRIX_COEFFICIENTS_MAP);
1302 if (colorSpace.matrix != null && !matrixValues.includes(colorSpace.matrix)) {
1303 throw new TypeError(\`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of \${matrixValues.join(", ")}.\`);
1304 }
1305 if (colorSpace.fullRange != null && typeof colorSpace.fullRange !== "boolean") {
1306 throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.");
1307 }
1308 }
1309 if (metadata.decoderConfig.codec.startsWith("avc1") || metadata.decoderConfig.codec.startsWith("avc3")) {
1310 if (!AVC_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {
1311 throw new TypeError("Video chunk metadata decoder configuration codec string for AVC must be a valid AVC codec string as specified in Section 3.4 of RFC 6381.");
1312 }
1313 } else if (metadata.decoderConfig.codec.startsWith("hev1") || metadata.decoderConfig.codec.startsWith("hvc1")) {
1314 if (!HEVC_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {
1315 throw new TypeError("Video chunk metadata decoder configuration codec string for HEVC must be a valid HEVC codec string as specified in Section E.3 of ISO 14496-15.");
1316 }
1317 } else if (metadata.decoderConfig.codec.startsWith("vp8")) {
1318 if (metadata.decoderConfig.codec !== "vp8") {
1319 throw new TypeError('Video chunk metadata decoder configuration codec string for VP8 must be "vp8".');
1320 }
1321 } else if (metadata.decoderConfig.codec.startsWith("vp09")) {
1322 if (!VP9_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {
1323 throw new TypeError('Video chunk metadata decoder configuration codec string for VP9 must be a valid VP9 codec string as specified in Section "Codecs Parameter String" of https://www.webmproject.org/vp9/mp4/.');
1324 }
1325 } else if (metadata.decoderConfig.codec.startsWith("av01")) {
1326 if (!AV1_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {
1327 throw new TypeError('Video chunk metadata decoder configuration codec string for AV1 must be a valid AV1 codec string as specified in Section "Codecs Parameter String" of https://aomediacodec.github.io/av1-isobmff/.');
1328 }
1329 }
1330 };
1331 var VALID_AUDIO_CODEC_STRING_PREFIXES = [
1332 "mp4a",
1333 "mp3",
1334 "opus",
1335 "vorbis",
1336 "flac",
1337 "ulaw",
1338 "alaw",
1339 "pcm",
1340 "ac-3",
1341 "ec-3"
1342 ];
1343 var validateAudioChunkMetadata = (metadata) => {
1344 if (!metadata) {
1345 throw new TypeError("Audio chunk metadata must be provided.");
1346 }
1347 if (typeof metadata !== "object") {
1348 throw new TypeError("Audio chunk metadata must be an object.");
1349 }
1350 if (!metadata.decoderConfig) {
1351 throw new TypeError("Audio chunk metadata must include a decoder configuration.");
1352 }
1353 if (typeof metadata.decoderConfig !== "object") {
1354 throw new TypeError("Audio chunk metadata decoder configuration must be an object.");
1355 }
1356 if (typeof metadata.decoderConfig.codec !== "string") {
1357 throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");
1358 }
1359 if (!VALID_AUDIO_CODEC_STRING_PREFIXES.some((prefix) => metadata.decoderConfig.codec.startsWith(prefix))) {
1360 throw new TypeError("Audio chunk metadata decoder configuration codec string must be a valid audio codec string as specified in the Mediabunny Codec Registry.");
1361 }
1362 if (!Number.isInteger(metadata.decoderConfig.sampleRate) || metadata.decoderConfig.sampleRate <= 0) {
1363 throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");
1364 }
1365 if (!Number.isInteger(metadata.decoderConfig.numberOfChannels) || metadata.decoderConfig.numberOfChannels <= 0) {
1366 throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");
1367 }
1368 if (metadata.decoderConfig.description !== void 0) {
1369 if (!isAllowSharedBufferSource(metadata.decoderConfig.description)) {
1370 throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");
1371 }
1372 }
1373 if (metadata.decoderConfig.codec.startsWith("mp4a") && metadata.decoderConfig.codec !== "mp4a.69" && metadata.decoderConfig.codec !== "mp4a.6B" && metadata.decoderConfig.codec !== "mp4a.6b") {
1374 const validStrings = ["mp4a.40.2", "mp4a.40.02", "mp4a.40.5", "mp4a.40.05", "mp4a.40.29", "mp4a.67"];
1375 if (!validStrings.includes(metadata.decoderConfig.codec)) {
1376 throw new TypeError("Audio chunk metadata decoder configuration codec string for AAC must be a valid AAC codec string as specified in https://www.w3.org/TR/webcodecs-aac-codec-registration/.");
1377 }
1378 } else if (metadata.decoderConfig.codec.startsWith("mp3") || metadata.decoderConfig.codec.startsWith("mp4a")) {
1379 if (metadata.decoderConfig.codec !== "mp3" && metadata.decoderConfig.codec !== "mp4a.69" && metadata.decoderConfig.codec !== "mp4a.6B" && metadata.decoderConfig.codec !== "mp4a.6b") {
1380 throw new TypeError('Audio chunk metadata decoder configuration codec string for MP3 must be "mp3", "mp4a.69" or "mp4a.6B".');
1381 }
1382 } else if (metadata.decoderConfig.codec.startsWith("opus")) {
1383 if (metadata.decoderConfig.codec !== "opus") {
1384 throw new TypeError('Audio chunk metadata decoder configuration codec string for Opus must be "opus".');
1385 }
1386 if (metadata.decoderConfig.description && metadata.decoderConfig.description.byteLength < 18) {
1387 throw new TypeError("Audio chunk metadata decoder configuration description, when specified, is expected to be an Identification Header as specified in Section 5.1 of RFC 7845.");
1388 }
1389 } else if (metadata.decoderConfig.codec.startsWith("vorbis")) {
1390 if (metadata.decoderConfig.codec !== "vorbis") {
1391 throw new TypeError('Audio chunk metadata decoder configuration codec string for Vorbis must be "vorbis".');
1392 }
1393 if (!metadata.decoderConfig.description) {
1394 throw new TypeError("Audio chunk metadata decoder configuration for Vorbis must include a description, which is expected to adhere to the format described in https://www.w3.org/TR/webcodecs-vorbis-codec-registration/.");
1395 }
1396 } else if (metadata.decoderConfig.codec.startsWith("flac")) {
1397 if (metadata.decoderConfig.codec !== "flac") {
1398 throw new TypeError('Audio chunk metadata decoder configuration codec string for FLAC must be "flac".');
1399 }
1400 const minDescriptionSize = 4 + 4 + 34;
1401 if (!metadata.decoderConfig.description || metadata.decoderConfig.description.byteLength < minDescriptionSize) {
1402 throw new TypeError("Audio chunk metadata decoder configuration for FLAC must include a description, which is expected to adhere to the format described in https://www.w3.org/TR/webcodecs-flac-codec-registration/.");
1403 }
1404 } else if (metadata.decoderConfig.codec.startsWith("ac-3") || metadata.decoderConfig.codec.startsWith("ac3")) {
1405 if (metadata.decoderConfig.codec !== "ac-3") {
1406 throw new TypeError('Audio chunk metadata decoder configuration codec string for AC-3 must be "ac-3".');
1407 }
1408 } else if (metadata.decoderConfig.codec.startsWith("ec-3") || metadata.decoderConfig.codec.startsWith("eac3")) {
1409 if (metadata.decoderConfig.codec !== "ec-3") {
1410 throw new TypeError('Audio chunk metadata decoder configuration codec string for EC-3 must be "ec-3".');
1411 }
1412 } else if (metadata.decoderConfig.codec.startsWith("pcm") || metadata.decoderConfig.codec.startsWith("ulaw") || metadata.decoderConfig.codec.startsWith("alaw")) {
1413 if (!PCM_AUDIO_CODECS.includes(metadata.decoderConfig.codec)) {
1414 throw new TypeError(\`Audio chunk metadata decoder configuration codec string for PCM must be one of the supported PCM codecs (\${PCM_AUDIO_CODECS.join(", ")}).\`);
1415 }
1416 }
1417 };
1418 var validateSubtitleMetadata = (metadata) => {
1419 if (!metadata) {
1420 throw new TypeError("Subtitle metadata must be provided.");
1421 }
1422 if (typeof metadata !== "object") {
1423 throw new TypeError("Subtitle metadata must be an object.");
1424 }
1425 if (!metadata.config) {
1426 throw new TypeError("Subtitle metadata must include a config object.");
1427 }
1428 if (typeof metadata.config !== "object") {
1429 throw new TypeError("Subtitle metadata config must be an object.");
1430 }
1431 if (typeof metadata.config.description !== "string") {
1432 throw new TypeError("Subtitle metadata config description must be a string.");
1433 }
1434 };
1435
1436 // node_modules/mediabunny/dist/modules/shared/ac3-misc.js
1437 var AC3_SAMPLE_RATES = [48e3, 44100, 32e3];
1438 var EAC3_REDUCED_SAMPLE_RATES = [24e3, 22050, 16e3];
1439
1440 // node_modules/mediabunny/dist/modules/src/codec-data.js
1441 var AvcNalUnitType;
1442 (function(AvcNalUnitType2) {
1443 AvcNalUnitType2[AvcNalUnitType2["NON_IDR_SLICE"] = 1] = "NON_IDR_SLICE";
1444 AvcNalUnitType2[AvcNalUnitType2["SLICE_DPA"] = 2] = "SLICE_DPA";
1445 AvcNalUnitType2[AvcNalUnitType2["SLICE_DPB"] = 3] = "SLICE_DPB";
1446 AvcNalUnitType2[AvcNalUnitType2["SLICE_DPC"] = 4] = "SLICE_DPC";
1447 AvcNalUnitType2[AvcNalUnitType2["IDR"] = 5] = "IDR";
1448 AvcNalUnitType2[AvcNalUnitType2["SEI"] = 6] = "SEI";
1449 AvcNalUnitType2[AvcNalUnitType2["SPS"] = 7] = "SPS";
1450 AvcNalUnitType2[AvcNalUnitType2["PPS"] = 8] = "PPS";
1451 AvcNalUnitType2[AvcNalUnitType2["AUD"] = 9] = "AUD";
1452 AvcNalUnitType2[AvcNalUnitType2["SPS_EXT"] = 13] = "SPS_EXT";
1453 })(AvcNalUnitType || (AvcNalUnitType = {}));
1454 var HevcNalUnitType;
1455 (function(HevcNalUnitType2) {
1456 HevcNalUnitType2[HevcNalUnitType2["RASL_N"] = 8] = "RASL_N";
1457 HevcNalUnitType2[HevcNalUnitType2["RASL_R"] = 9] = "RASL_R";
1458 HevcNalUnitType2[HevcNalUnitType2["BLA_W_LP"] = 16] = "BLA_W_LP";
1459 HevcNalUnitType2[HevcNalUnitType2["RSV_IRAP_VCL23"] = 23] = "RSV_IRAP_VCL23";
1460 HevcNalUnitType2[HevcNalUnitType2["VPS_NUT"] = 32] = "VPS_NUT";
1461 HevcNalUnitType2[HevcNalUnitType2["SPS_NUT"] = 33] = "SPS_NUT";
1462 HevcNalUnitType2[HevcNalUnitType2["PPS_NUT"] = 34] = "PPS_NUT";
1463 HevcNalUnitType2[HevcNalUnitType2["AUD_NUT"] = 35] = "AUD_NUT";
1464 HevcNalUnitType2[HevcNalUnitType2["PREFIX_SEI_NUT"] = 39] = "PREFIX_SEI_NUT";
1465 HevcNalUnitType2[HevcNalUnitType2["SUFFIX_SEI_NUT"] = 40] = "SUFFIX_SEI_NUT";
1466 })(HevcNalUnitType || (HevcNalUnitType = {}));
1467 var iterateNalUnitsInAnnexB = function* (packetData) {
1468 let i2 = 0;
1469 let nalStart = -1;
1470 while (i2 < packetData.length - 2) {
1471 const zeroIndex = packetData.indexOf(0, i2);
1472 if (zeroIndex === -1 || zeroIndex >= packetData.length - 2) {
1473 break;
1474 }
1475 i2 = zeroIndex;
1476 let startCodeLength = 0;
1477 if (i2 + 3 < packetData.length && packetData[i2 + 1] === 0 && packetData[i2 + 2] === 0 && packetData[i2 + 3] === 1) {
1478 startCodeLength = 4;
1479 } else if (packetData[i2 + 1] === 0 && packetData[i2 + 2] === 1) {
1480 startCodeLength = 3;
1481 }
1482 if (startCodeLength === 0) {
1483 i2++;
1484 continue;
1485 }
1486 if (nalStart !== -1 && i2 > nalStart) {
1487 yield {
1488 offset: nalStart,
1489 length: i2 - nalStart
1490 };
1491 }
1492 nalStart = i2 + startCodeLength;
1493 i2 = nalStart;
1494 }
1495 if (nalStart !== -1 && nalStart < packetData.length) {
1496 yield {
1497 offset: nalStart,
1498 length: packetData.length - nalStart
1499 };
1500 }
1501 };
1502 var iterateNalUnitsInLengthPrefixed = function* (packetData, lengthSize) {
1503 let offset = 0;
1504 const dataView = new DataView(packetData.buffer, packetData.byteOffset, packetData.byteLength);
1505 while (offset + lengthSize <= packetData.length) {
1506 let nalUnitLength;
1507 if (lengthSize === 1) {
1508 nalUnitLength = dataView.getUint8(offset);
1509 } else if (lengthSize === 2) {
1510 nalUnitLength = dataView.getUint16(offset, false);
1511 } else if (lengthSize === 3) {
1512 nalUnitLength = getUint24(dataView, offset, false);
1513 } else {
1514 assert(lengthSize === 4);
1515 nalUnitLength = dataView.getUint32(offset, false);
1516 }
1517 offset += lengthSize;
1518 yield {
1519 offset,
1520 length: nalUnitLength
1521 };
1522 offset += nalUnitLength;
1523 }
1524 };
1525 var iterateAvcNalUnits = (packetData, decoderConfig) => {
1526 if (decoderConfig.description) {
1527 const bytes2 = toUint8Array(decoderConfig.description);
1528 const lengthSizeMinusOne = bytes2[4] & 3;
1529 const lengthSize = lengthSizeMinusOne + 1;
1530 return iterateNalUnitsInLengthPrefixed(packetData, lengthSize);
1531 } else {
1532 return iterateNalUnitsInAnnexB(packetData);
1533 }
1534 };
1535 var extractNalUnitTypeForAvc = (byte) => {
1536 return byte & 31;
1537 };
1538 var removeEmulationPreventionBytes = (data) => {
1539 const result = [];
1540 const len = data.length;
1541 for (let i2 = 0; i2 < len; i2++) {
1542 if (i2 + 2 < len && data[i2] === 0 && data[i2 + 1] === 0 && data[i2 + 2] === 3) {
1543 result.push(0, 0);
1544 i2 += 2;
1545 } else {
1546 result.push(data[i2]);
1547 }
1548 }
1549 return new Uint8Array(result);
1550 };
1551 var ANNEX_B_START_CODE = new Uint8Array([0, 0, 0, 1]);
1552 var concatNalUnitsInLengthPrefixed = (nalUnits, lengthSize) => {
1553 const totalLength = nalUnits.reduce((a2, b) => a2 + lengthSize + b.byteLength, 0);
1554 const result = new Uint8Array(totalLength);
1555 let offset = 0;
1556 for (const nalUnit of nalUnits) {
1557 const dataView = new DataView(result.buffer, result.byteOffset, result.byteLength);
1558 switch (lengthSize) {
1559 case 1:
1560 dataView.setUint8(offset, nalUnit.byteLength);
1561 break;
1562 case 2:
1563 dataView.setUint16(offset, nalUnit.byteLength, false);
1564 break;
1565 case 3:
1566 setUint24(dataView, offset, nalUnit.byteLength, false);
1567 break;
1568 case 4:
1569 dataView.setUint32(offset, nalUnit.byteLength, false);
1570 break;
1571 }
1572 offset += lengthSize;
1573 result.set(nalUnit, offset);
1574 offset += nalUnit.byteLength;
1575 }
1576 return result;
1577 };
1578 var extractAvcDecoderConfigurationRecord = (packetData) => {
1579 try {
1580 const spsUnits = [];
1581 const ppsUnits = [];
1582 const spsExtUnits = [];
1583 for (const loc of iterateNalUnitsInAnnexB(packetData)) {
1584 const nalUnit = packetData.subarray(loc.offset, loc.offset + loc.length);
1585 const type = extractNalUnitTypeForAvc(nalUnit[0]);
1586 if (type === AvcNalUnitType.SPS) {
1587 spsUnits.push(nalUnit);
1588 } else if (type === AvcNalUnitType.PPS) {
1589 ppsUnits.push(nalUnit);
1590 } else if (type === AvcNalUnitType.SPS_EXT) {
1591 spsExtUnits.push(nalUnit);
1592 }
1593 }
1594 if (spsUnits.length === 0) {
1595 return null;
1596 }
1597 if (ppsUnits.length === 0) {
1598 return null;
1599 }
1600 const spsData = spsUnits[0];
1601 const spsInfo = parseAvcSps(spsData);
1602 assert(spsInfo !== null);
1603 const hasExtendedData = spsInfo.profileIdc === 100 || spsInfo.profileIdc === 110 || spsInfo.profileIdc === 122 || spsInfo.profileIdc === 144;
1604 return {
1605 configurationVersion: 1,
1606 avcProfileIndication: spsInfo.profileIdc,
1607 profileCompatibility: spsInfo.constraintFlags,
1608 avcLevelIndication: spsInfo.levelIdc,
1609 lengthSizeMinusOne: 3,
1610 // Typically 4 bytes for length field
1611 sequenceParameterSets: spsUnits,
1612 pictureParameterSets: ppsUnits,
1613 chromaFormat: hasExtendedData ? spsInfo.chromaFormatIdc : null,
1614 bitDepthLumaMinus8: hasExtendedData ? spsInfo.bitDepthLumaMinus8 : null,
1615 bitDepthChromaMinus8: hasExtendedData ? spsInfo.bitDepthChromaMinus8 : null,
1616 sequenceParameterSetExt: hasExtendedData ? spsExtUnits : null
1617 };
1618 } catch (error) {
1619 Logging._error("Error building AVC Decoder Configuration Record:", error);
1620 return null;
1621 }
1622 };
1623 var serializeAvcDecoderConfigurationRecord = (record) => {
1624 const bytes2 = [];
1625 bytes2.push(record.configurationVersion);
1626 bytes2.push(record.avcProfileIndication);
1627 bytes2.push(record.profileCompatibility);
1628 bytes2.push(record.avcLevelIndication);
1629 bytes2.push(252 | record.lengthSizeMinusOne & 3);
1630 bytes2.push(224 | record.sequenceParameterSets.length & 31);
1631 for (const sps of record.sequenceParameterSets) {
1632 const length = sps.byteLength;
1633 bytes2.push(length >> 8);
1634 bytes2.push(length & 255);
1635 for (let i2 = 0; i2 < length; i2++) {
1636 bytes2.push(sps[i2]);
1637 }
1638 }
1639 bytes2.push(record.pictureParameterSets.length);
1640 for (const pps of record.pictureParameterSets) {
1641 const length = pps.byteLength;
1642 bytes2.push(length >> 8);
1643 bytes2.push(length & 255);
1644 for (let i2 = 0; i2 < length; i2++) {
1645 bytes2.push(pps[i2]);
1646 }
1647 }
1648 if (record.avcProfileIndication === 100 || record.avcProfileIndication === 110 || record.avcProfileIndication === 122 || record.avcProfileIndication === 144) {
1649 assert(record.chromaFormat !== null);
1650 assert(record.bitDepthLumaMinus8 !== null);
1651 assert(record.bitDepthChromaMinus8 !== null);
1652 assert(record.sequenceParameterSetExt !== null);
1653 bytes2.push(252 | record.chromaFormat & 3);
1654 bytes2.push(248 | record.bitDepthLumaMinus8 & 7);
1655 bytes2.push(248 | record.bitDepthChromaMinus8 & 7);
1656 bytes2.push(record.sequenceParameterSetExt.length);
1657 for (const spsExt of record.sequenceParameterSetExt) {
1658 const length = spsExt.byteLength;
1659 bytes2.push(length >> 8);
1660 bytes2.push(length & 255);
1661 for (let i2 = 0; i2 < length; i2++) {
1662 bytes2.push(spsExt[i2]);
1663 }
1664 }
1665 }
1666 return new Uint8Array(bytes2);
1667 };
1668 var AVC_HEVC_ASPECT_RATIO_IDC_TABLE = {
1669 1: { num: 1, den: 1 },
1670 2: { num: 12, den: 11 },
1671 3: { num: 10, den: 11 },
1672 4: { num: 16, den: 11 },
1673 5: { num: 40, den: 33 },
1674 6: { num: 24, den: 11 },
1675 7: { num: 20, den: 11 },
1676 8: { num: 32, den: 11 },
1677 9: { num: 80, den: 33 },
1678 10: { num: 18, den: 11 },
1679 11: { num: 15, den: 11 },
1680 12: { num: 64, den: 33 },
1681 13: { num: 160, den: 99 },
1682 14: { num: 4, den: 3 },
1683 15: { num: 3, den: 2 },
1684 16: { num: 2, den: 1 }
1685 };
1686 var parseAvcSps = (sps) => {
1687 try {
1688 const bitstream = new Bitstream(removeEmulationPreventionBytes(sps));
1689 bitstream.skipBits(1);
1690 bitstream.skipBits(2);
1691 const nalUnitType = bitstream.readBits(5);
1692 if (nalUnitType !== 7) {
1693 return null;
1694 }
1695 const profileIdc = bitstream.readAlignedByte();
1696 const constraintFlags = bitstream.readAlignedByte();
1697 const levelIdc = bitstream.readAlignedByte();
1698 readExpGolomb(bitstream);
1699 let chromaFormatIdc = 1;
1700 let bitDepthLumaMinus8 = 0;
1701 let bitDepthChromaMinus8 = 0;
1702 let separateColourPlaneFlag = 0;
1703 if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
1704 chromaFormatIdc = readExpGolomb(bitstream);
1705 if (chromaFormatIdc === 3) {
1706 separateColourPlaneFlag = bitstream.readBits(1);
1707 }
1708 bitDepthLumaMinus8 = readExpGolomb(bitstream);
1709 bitDepthChromaMinus8 = readExpGolomb(bitstream);
1710 bitstream.skipBits(1);
1711 const seqScalingMatrixPresentFlag = bitstream.readBits(1);
1712 if (seqScalingMatrixPresentFlag) {
1713 for (let i2 = 0; i2 < (chromaFormatIdc !== 3 ? 8 : 12); i2++) {
1714 const seqScalingListPresentFlag = bitstream.readBits(1);
1715 if (seqScalingListPresentFlag) {
1716 const sizeOfScalingList = i2 < 6 ? 16 : 64;
1717 let lastScale = 8;
1718 let nextScale = 8;
1719 for (let j = 0; j < sizeOfScalingList; j++) {
1720 if (nextScale !== 0) {
1721 const deltaScale = readSignedExpGolomb(bitstream);
1722 nextScale = (lastScale + deltaScale + 256) % 256;
1723 }
1724 lastScale = nextScale === 0 ? lastScale : nextScale;
1725 }
1726 }
1727 }
1728 }
1729 }
1730 readExpGolomb(bitstream);
1731 const picOrderCntType = readExpGolomb(bitstream);
1732 if (picOrderCntType === 0) {
1733 readExpGolomb(bitstream);
1734 } else if (picOrderCntType === 1) {
1735 bitstream.skipBits(1);
1736 readSignedExpGolomb(bitstream);
1737 readSignedExpGolomb(bitstream);
1738 const numRefFramesInPicOrderCntCycle = readExpGolomb(bitstream);
1739 for (let i2 = 0; i2 < numRefFramesInPicOrderCntCycle; i2++) {
1740 readSignedExpGolomb(bitstream);
1741 }
1742 }
1743 readExpGolomb(bitstream);
1744 bitstream.skipBits(1);
1745 const picWidthInMbsMinus1 = readExpGolomb(bitstream);
1746 const picHeightInMapUnitsMinus1 = readExpGolomb(bitstream);
1747 const codedWidth = 16 * (picWidthInMbsMinus1 + 1);
1748 const codedHeight = 16 * (picHeightInMapUnitsMinus1 + 1);
1749 let displayWidth = codedWidth;
1750 let displayHeight = codedHeight;
1751 const frameMbsOnlyFlag = bitstream.readBits(1);
1752 if (!frameMbsOnlyFlag) {
1753 bitstream.skipBits(1);
1754 }
1755 bitstream.skipBits(1);
1756 const frameCroppingFlag = bitstream.readBits(1);
1757 if (frameCroppingFlag) {
1758 const frameCropLeftOffset = readExpGolomb(bitstream);
1759 const frameCropRightOffset = readExpGolomb(bitstream);
1760 const frameCropTopOffset = readExpGolomb(bitstream);
1761 const frameCropBottomOffset = readExpGolomb(bitstream);
1762 let cropUnitX;
1763 let cropUnitY;
1764 const chromaArrayType = separateColourPlaneFlag === 0 ? chromaFormatIdc : 0;
1765 if (chromaArrayType === 0) {
1766 cropUnitX = 1;
1767 cropUnitY = 2 - frameMbsOnlyFlag;
1768 } else {
1769 const subWidthC = chromaFormatIdc === 3 ? 1 : 2;
1770 const subHeightC = chromaFormatIdc === 1 ? 2 : 1;
1771 cropUnitX = subWidthC;
1772 cropUnitY = subHeightC * (2 - frameMbsOnlyFlag);
1773 }
1774 displayWidth -= cropUnitX * (frameCropLeftOffset + frameCropRightOffset);
1775 displayHeight -= cropUnitY * (frameCropTopOffset + frameCropBottomOffset);
1776 }
1777 let colourPrimaries = 2;
1778 let transferCharacteristics = 2;
1779 let matrixCoefficients = 2;
1780 let fullRangeFlag = 0;
1781 let pixelAspectRatio = { num: 1, den: 1 };
1782 let numReorderFrames = null;
1783 let maxDecFrameBuffering = null;
1784 const vuiParametersPresentFlag = bitstream.readBits(1);
1785 if (vuiParametersPresentFlag) {
1786 const aspectRatioInfoPresentFlag = bitstream.readBits(1);
1787 if (aspectRatioInfoPresentFlag) {
1788 const aspectRatioIdc = bitstream.readBits(8);
1789 if (aspectRatioIdc === 255) {
1790 pixelAspectRatio = {
1791 num: bitstream.readBits(16),
1792 den: bitstream.readBits(16)
1793 };
1794 } else {
1795 const aspectRatio = AVC_HEVC_ASPECT_RATIO_IDC_TABLE[aspectRatioIdc];
1796 if (aspectRatio) {
1797 pixelAspectRatio = aspectRatio;
1798 }
1799 }
1800 }
1801 const overscanInfoPresentFlag = bitstream.readBits(1);
1802 if (overscanInfoPresentFlag) {
1803 bitstream.skipBits(1);
1804 }
1805 const videoSignalTypePresentFlag = bitstream.readBits(1);
1806 if (videoSignalTypePresentFlag) {
1807 bitstream.skipBits(3);
1808 fullRangeFlag = bitstream.readBits(1);
1809 const colourDescriptionPresentFlag = bitstream.readBits(1);
1810 if (colourDescriptionPresentFlag) {
1811 colourPrimaries = bitstream.readBits(8);
1812 transferCharacteristics = bitstream.readBits(8);
1813 matrixCoefficients = bitstream.readBits(8);
1814 }
1815 }
1816 const chromaLocInfoPresentFlag = bitstream.readBits(1);
1817 if (chromaLocInfoPresentFlag) {
1818 readExpGolomb(bitstream);
1819 readExpGolomb(bitstream);
1820 }
1821 const timingInfoPresentFlag = bitstream.readBits(1);
1822 if (timingInfoPresentFlag) {
1823 bitstream.skipBits(32);
1824 bitstream.skipBits(32);
1825 bitstream.skipBits(1);
1826 }
1827 const nalHrdParametersPresentFlag = bitstream.readBits(1);
1828 if (nalHrdParametersPresentFlag) {
1829 skipAvcHrdParameters(bitstream);
1830 }
1831 const vclHrdParametersPresentFlag = bitstream.readBits(1);
1832 if (vclHrdParametersPresentFlag) {
1833 skipAvcHrdParameters(bitstream);
1834 }
1835 if (nalHrdParametersPresentFlag || vclHrdParametersPresentFlag) {
1836 bitstream.skipBits(1);
1837 }
1838 bitstream.skipBits(1);
1839 const bitstreamRestrictionFlag = bitstream.readBits(1);
1840 if (bitstreamRestrictionFlag) {
1841 bitstream.skipBits(1);
1842 readExpGolomb(bitstream);
1843 readExpGolomb(bitstream);
1844 readExpGolomb(bitstream);
1845 readExpGolomb(bitstream);
1846 numReorderFrames = readExpGolomb(bitstream);
1847 maxDecFrameBuffering = readExpGolomb(bitstream);
1848 }
1849 }
1850 if (numReorderFrames === null) {
1851 assert(maxDecFrameBuffering === null);
1852 const constraintSet3Flag = constraintFlags & 16;
1853 if ((profileIdc === 44 || profileIdc === 86 || profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244) && constraintSet3Flag) {
1854 numReorderFrames = 0;
1855 maxDecFrameBuffering = 0;
1856 } else {
1857 const picWidthInMbs = picWidthInMbsMinus1 + 1;
1858 const picHeightInMapUnits = picHeightInMapUnitsMinus1 + 1;
1859 const frameHeightInMbs = (2 - frameMbsOnlyFlag) * picHeightInMapUnits;
1860 const levelInfo = AVC_LEVEL_TABLE.find((x) => x.level >= levelIdc) ?? last(AVC_LEVEL_TABLE);
1861 const maxDpbFrames = Math.min(Math.floor(levelInfo.maxDpbMbs / (picWidthInMbs * frameHeightInMbs)), 16);
1862 numReorderFrames = maxDpbFrames;
1863 maxDecFrameBuffering = maxDpbFrames;
1864 }
1865 }
1866 assert(maxDecFrameBuffering !== null);
1867 return {
1868 profileIdc,
1869 constraintFlags,
1870 levelIdc,
1871 frameMbsOnlyFlag,
1872 chromaFormatIdc,
1873 bitDepthLumaMinus8,
1874 bitDepthChromaMinus8,
1875 codedWidth,
1876 codedHeight,
1877 displayWidth,
1878 displayHeight,
1879 pixelAspectRatio,
1880 colourPrimaries,
1881 matrixCoefficients,
1882 transferCharacteristics,
1883 fullRangeFlag,
1884 numReorderFrames,
1885 maxDecFrameBuffering
1886 };
1887 } catch (error) {
1888 Logging._error("Error parsing AVC SPS:", error);
1889 return null;
1890 }
1891 };
1892 var skipAvcHrdParameters = (bitstream) => {
1893 const cpb_cnt_minus1 = readExpGolomb(bitstream);
1894 bitstream.skipBits(4);
1895 bitstream.skipBits(4);
1896 for (let i2 = 0; i2 <= cpb_cnt_minus1; i2++) {
1897 readExpGolomb(bitstream);
1898 readExpGolomb(bitstream);
1899 bitstream.skipBits(1);
1900 }
1901 bitstream.skipBits(5);
1902 bitstream.skipBits(5);
1903 bitstream.skipBits(5);
1904 bitstream.skipBits(5);
1905 };
1906 var iterateHevcNalUnits = (packetData, decoderConfig) => {
1907 if (decoderConfig.description) {
1908 const bytes2 = toUint8Array(decoderConfig.description);
1909 const lengthSizeMinusOne = bytes2[21] & 3;
1910 const lengthSize = lengthSizeMinusOne + 1;
1911 return iterateNalUnitsInLengthPrefixed(packetData, lengthSize);
1912 } else {
1913 return iterateNalUnitsInAnnexB(packetData);
1914 }
1915 };
1916 var extractNalUnitTypeForHevc = (byte) => {
1917 return byte >> 1 & 63;
1918 };
1919 var parseHevcSps = (sps) => {
1920 try {
1921 const bitstream = new Bitstream(removeEmulationPreventionBytes(sps));
1922 bitstream.skipBits(16);
1923 bitstream.readBits(4);
1924 const spsMaxSubLayersMinus1 = bitstream.readBits(3);
1925 const spsTemporalIdNestingFlag = bitstream.readBits(1);
1926 const { general_profile_space, general_tier_flag, general_profile_idc, general_profile_compatibility_flags, general_constraint_indicator_flags, general_level_idc } = parseProfileTierLevel(bitstream, spsMaxSubLayersMinus1);
1927 readExpGolomb(bitstream);
1928 const chromaFormatIdc = readExpGolomb(bitstream);
1929 let separateColourPlaneFlag = 0;
1930 if (chromaFormatIdc === 3) {
1931 separateColourPlaneFlag = bitstream.readBits(1);
1932 }
1933 const picWidthInLumaSamples = readExpGolomb(bitstream);
1934 const picHeightInLumaSamples = readExpGolomb(bitstream);
1935 let displayWidth = picWidthInLumaSamples;
1936 let displayHeight = picHeightInLumaSamples;
1937 if (bitstream.readBits(1)) {
1938 const confWinLeftOffset = readExpGolomb(bitstream);
1939 const confWinRightOffset = readExpGolomb(bitstream);
1940 const confWinTopOffset = readExpGolomb(bitstream);
1941 const confWinBottomOffset = readExpGolomb(bitstream);
1942 let subWidthC = 1;
1943 let subHeightC = 1;
1944 const chromaArrayType = separateColourPlaneFlag === 0 ? chromaFormatIdc : 0;
1945 if (chromaArrayType === 1) {
1946 subWidthC = 2;
1947 subHeightC = 2;
1948 } else if (chromaArrayType === 2) {
1949 subWidthC = 2;
1950 subHeightC = 1;
1951 }
1952 displayWidth -= (confWinLeftOffset + confWinRightOffset) * subWidthC;
1953 displayHeight -= (confWinTopOffset + confWinBottomOffset) * subHeightC;
1954 }
1955 const bitDepthLumaMinus8 = readExpGolomb(bitstream);
1956 const bitDepthChromaMinus8 = readExpGolomb(bitstream);
1957 readExpGolomb(bitstream);
1958 const spsSubLayerOrderingInfoPresentFlag = bitstream.readBits(1);
1959 const startI = spsSubLayerOrderingInfoPresentFlag ? 0 : spsMaxSubLayersMinus1;
1960 let spsMaxNumReorderPics = 0;
1961 for (let i2 = startI; i2 <= spsMaxSubLayersMinus1; i2++) {
1962 readExpGolomb(bitstream);
1963 spsMaxNumReorderPics = readExpGolomb(bitstream);
1964 readExpGolomb(bitstream);
1965 }
1966 readExpGolomb(bitstream);
1967 readExpGolomb(bitstream);
1968 readExpGolomb(bitstream);
1969 readExpGolomb(bitstream);
1970 readExpGolomb(bitstream);
1971 readExpGolomb(bitstream);
1972 if (bitstream.readBits(1)) {
1973 if (bitstream.readBits(1)) {
1974 skipScalingListData(bitstream);
1975 }
1976 }
1977 bitstream.skipBits(1);
1978 bitstream.skipBits(1);
1979 if (bitstream.readBits(1)) {
1980 bitstream.skipBits(4);
1981 bitstream.skipBits(4);
1982 readExpGolomb(bitstream);
1983 readExpGolomb(bitstream);
1984 bitstream.skipBits(1);
1985 }
1986 const numShortTermRefPicSets = readExpGolomb(bitstream);
1987 skipAllStRefPicSets(bitstream, numShortTermRefPicSets);
1988 if (bitstream.readBits(1)) {
1989 const numLongTermRefPicsSps = readExpGolomb(bitstream);
1990 for (let i2 = 0; i2 < numLongTermRefPicsSps; i2++) {
1991 readExpGolomb(bitstream);
1992 bitstream.skipBits(1);
1993 }
1994 }
1995 bitstream.skipBits(1);
1996 bitstream.skipBits(1);
1997 let colourPrimaries = 2;
1998 let transferCharacteristics = 2;
1999 let matrixCoefficients = 2;
2000 let fullRangeFlag = 0;
2001 let minSpatialSegmentationIdc = 0;
2002 let pixelAspectRatio = { num: 1, den: 1 };
2003 if (bitstream.readBits(1)) {
2004 const vui = parseHevcVui(bitstream, spsMaxSubLayersMinus1);
2005 pixelAspectRatio = vui.pixelAspectRatio;
2006 colourPrimaries = vui.colourPrimaries;
2007 transferCharacteristics = vui.transferCharacteristics;
2008 matrixCoefficients = vui.matrixCoefficients;
2009 fullRangeFlag = vui.fullRangeFlag;
2010 minSpatialSegmentationIdc = vui.minSpatialSegmentationIdc;
2011 }
2012 return {
2013 displayWidth,
2014 displayHeight,
2015 pixelAspectRatio,
2016 colourPrimaries,
2017 transferCharacteristics,
2018 matrixCoefficients,
2019 fullRangeFlag,
2020 maxDecFrameBuffering: spsMaxNumReorderPics + 1,
2021 spsMaxSubLayersMinus1,
2022 spsTemporalIdNestingFlag,
2023 generalProfileSpace: general_profile_space,
2024 generalTierFlag: general_tier_flag,
2025 generalProfileIdc: general_profile_idc,
2026 generalProfileCompatibilityFlags: general_profile_compatibility_flags,
2027 generalConstraintIndicatorFlags: general_constraint_indicator_flags,
2028 generalLevelIdc: general_level_idc,
2029 chromaFormatIdc,
2030 bitDepthLumaMinus8,
2031 bitDepthChromaMinus8,
2032 minSpatialSegmentationIdc
2033 };
2034 } catch (error) {
2035 Logging._error("Error parsing HEVC SPS:", error);
2036 return null;
2037 }
2038 };
2039 var extractHevcDecoderConfigurationRecord = (packetData) => {
2040 try {
2041 const vpsUnits = [];
2042 const spsUnits = [];
2043 const ppsUnits = [];
2044 const seiUnits = [];
2045 for (const loc of iterateNalUnitsInAnnexB(packetData)) {
2046 const nalUnit = packetData.subarray(loc.offset, loc.offset + loc.length);
2047 const type = extractNalUnitTypeForHevc(nalUnit[0]);
2048 if (type === HevcNalUnitType.VPS_NUT) {
2049 vpsUnits.push(nalUnit);
2050 } else if (type === HevcNalUnitType.SPS_NUT) {
2051 spsUnits.push(nalUnit);
2052 } else if (type === HevcNalUnitType.PPS_NUT) {
2053 ppsUnits.push(nalUnit);
2054 } else if (type === HevcNalUnitType.PREFIX_SEI_NUT || type === HevcNalUnitType.SUFFIX_SEI_NUT) {
2055 seiUnits.push(nalUnit);
2056 }
2057 }
2058 if (spsUnits.length === 0 || ppsUnits.length === 0)
2059 return null;
2060 const spsInfo = parseHevcSps(spsUnits[0]);
2061 if (!spsInfo)
2062 return null;
2063 let parallelismType = 0;
2064 if (ppsUnits.length > 0) {
2065 const pps = ppsUnits[0];
2066 const ppsBitstream = new Bitstream(removeEmulationPreventionBytes(pps));
2067 ppsBitstream.skipBits(16);
2068 readExpGolomb(ppsBitstream);
2069 readExpGolomb(ppsBitstream);
2070 ppsBitstream.skipBits(1);
2071 ppsBitstream.skipBits(1);
2072 ppsBitstream.skipBits(3);
2073 ppsBitstream.skipBits(1);
2074 ppsBitstream.skipBits(1);
2075 readExpGolomb(ppsBitstream);
2076 readExpGolomb(ppsBitstream);
2077 readSignedExpGolomb(ppsBitstream);
2078 ppsBitstream.skipBits(1);
2079 ppsBitstream.skipBits(1);
2080 if (ppsBitstream.readBits(1)) {
2081 readExpGolomb(ppsBitstream);
2082 }
2083 readSignedExpGolomb(ppsBitstream);
2084 readSignedExpGolomb(ppsBitstream);
2085 ppsBitstream.skipBits(1);
2086 ppsBitstream.skipBits(1);
2087 ppsBitstream.skipBits(1);
2088 ppsBitstream.skipBits(1);
2089 const tiles_enabled_flag = ppsBitstream.readBits(1);
2090 const entropy_coding_sync_enabled_flag = ppsBitstream.readBits(1);
2091 if (!tiles_enabled_flag && !entropy_coding_sync_enabled_flag)
2092 parallelismType = 0;
2093 else if (tiles_enabled_flag && !entropy_coding_sync_enabled_flag)
2094 parallelismType = 2;
2095 else if (!tiles_enabled_flag && entropy_coding_sync_enabled_flag)
2096 parallelismType = 3;
2097 else
2098 parallelismType = 0;
2099 }
2100 const arrays = [
2101 ...vpsUnits.length ? [
2102 {
2103 arrayCompleteness: 1,
2104 nalUnitType: HevcNalUnitType.VPS_NUT,
2105 nalUnits: vpsUnits
2106 }
2107 ] : [],
2108 ...spsUnits.length ? [
2109 {
2110 arrayCompleteness: 1,
2111 nalUnitType: HevcNalUnitType.SPS_NUT,
2112 nalUnits: spsUnits
2113 }
2114 ] : [],
2115 ...ppsUnits.length ? [
2116 {
2117 arrayCompleteness: 1,
2118 nalUnitType: HevcNalUnitType.PPS_NUT,
2119 nalUnits: ppsUnits
2120 }
2121 ] : [],
2122 ...seiUnits.length ? [
2123 {
2124 arrayCompleteness: 1,
2125 nalUnitType: extractNalUnitTypeForHevc(seiUnits[0][0]),
2126 nalUnits: seiUnits
2127 }
2128 ] : []
2129 ];
2130 const record = {
2131 configurationVersion: 1,
2132 generalProfileSpace: spsInfo.generalProfileSpace,
2133 generalTierFlag: spsInfo.generalTierFlag,
2134 generalProfileIdc: spsInfo.generalProfileIdc,
2135 generalProfileCompatibilityFlags: spsInfo.generalProfileCompatibilityFlags,
2136 generalConstraintIndicatorFlags: spsInfo.generalConstraintIndicatorFlags,
2137 generalLevelIdc: spsInfo.generalLevelIdc,
2138 minSpatialSegmentationIdc: spsInfo.minSpatialSegmentationIdc,
2139 parallelismType,
2140 chromaFormatIdc: spsInfo.chromaFormatIdc,
2141 bitDepthLumaMinus8: spsInfo.bitDepthLumaMinus8,
2142 bitDepthChromaMinus8: spsInfo.bitDepthChromaMinus8,
2143 avgFrameRate: 0,
2144 constantFrameRate: 0,
2145 numTemporalLayers: spsInfo.spsMaxSubLayersMinus1 + 1,
2146 temporalIdNested: spsInfo.spsTemporalIdNestingFlag,
2147 lengthSizeMinusOne: 3,
2148 arrays
2149 };
2150 return record;
2151 } catch (error) {
2152 Logging._error("Error building HEVC Decoder Configuration Record:", error);
2153 return null;
2154 }
2155 };
2156 var parseProfileTierLevel = (bitstream, maxNumSubLayersMinus1) => {
2157 const general_profile_space = bitstream.readBits(2);
2158 const general_tier_flag = bitstream.readBits(1);
2159 const general_profile_idc = bitstream.readBits(5);
2160 let general_profile_compatibility_flags = 0;
2161 for (let i2 = 0; i2 < 32; i2++) {
2162 general_profile_compatibility_flags = general_profile_compatibility_flags << 1 | bitstream.readBits(1);
2163 }
2164 const general_constraint_indicator_flags = new Uint8Array(6);
2165 for (let i2 = 0; i2 < 6; i2++) {
2166 general_constraint_indicator_flags[i2] = bitstream.readBits(8);
2167 }
2168 const general_level_idc = bitstream.readBits(8);
2169 const sub_layer_profile_present_flag = [];
2170 const sub_layer_level_present_flag = [];
2171 for (let i2 = 0; i2 < maxNumSubLayersMinus1; i2++) {
2172 sub_layer_profile_present_flag.push(bitstream.readBits(1));
2173 sub_layer_level_present_flag.push(bitstream.readBits(1));
2174 }
2175 if (maxNumSubLayersMinus1 > 0) {
2176 for (let i2 = maxNumSubLayersMinus1; i2 < 8; i2++) {
2177 bitstream.skipBits(2);
2178 }
2179 }
2180 for (let i2 = 0; i2 < maxNumSubLayersMinus1; i2++) {
2181 if (sub_layer_profile_present_flag[i2])
2182 bitstream.skipBits(88);
2183 if (sub_layer_level_present_flag[i2])
2184 bitstream.skipBits(8);
2185 }
2186 return {
2187 general_profile_space,
2188 general_tier_flag,
2189 general_profile_idc,
2190 general_profile_compatibility_flags,
2191 general_constraint_indicator_flags,
2192 general_level_idc
2193 };
2194 };
2195 var skipScalingListData = (bitstream) => {
2196 for (let sizeId = 0; sizeId < 4; sizeId++) {
2197 for (let matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
2198 const scaling_list_pred_mode_flag = bitstream.readBits(1);
2199 if (!scaling_list_pred_mode_flag) {
2200 readExpGolomb(bitstream);
2201 } else {
2202 const coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
2203 if (sizeId > 1) {
2204 readSignedExpGolomb(bitstream);
2205 }
2206 for (let i2 = 0; i2 < coefNum; i2++) {
2207 readSignedExpGolomb(bitstream);
2208 }
2209 }
2210 }
2211 }
2212 };
2213 var skipAllStRefPicSets = (bitstream, num_short_term_ref_pic_sets) => {
2214 const NumDeltaPocs = [];
2215 for (let stRpsIdx = 0; stRpsIdx < num_short_term_ref_pic_sets; stRpsIdx++) {
2216 NumDeltaPocs[stRpsIdx] = skipStRefPicSet(bitstream, stRpsIdx, num_short_term_ref_pic_sets, NumDeltaPocs);
2217 }
2218 };
2219 var skipStRefPicSet = (bitstream, stRpsIdx, num_short_term_ref_pic_sets, NumDeltaPocs) => {
2220 let NumDeltaPocsThis = 0;
2221 let inter_ref_pic_set_prediction_flag = 0;
2222 let RefRpsIdx = 0;
2223 if (stRpsIdx !== 0) {
2224 inter_ref_pic_set_prediction_flag = bitstream.readBits(1);
2225 }
2226 if (inter_ref_pic_set_prediction_flag) {
2227 if (stRpsIdx === num_short_term_ref_pic_sets) {
2228 const delta_idx_minus1 = readExpGolomb(bitstream);
2229 RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1);
2230 } else {
2231 RefRpsIdx = stRpsIdx - 1;
2232 }
2233 bitstream.readBits(1);
2234 readExpGolomb(bitstream);
2235 const numDelta = NumDeltaPocs[RefRpsIdx] ?? 0;
2236 for (let j = 0; j <= numDelta; j++) {
2237 const used_by_curr_pic_flag = bitstream.readBits(1);
2238 if (!used_by_curr_pic_flag) {
2239 bitstream.readBits(1);
2240 }
2241 }
2242 NumDeltaPocsThis = NumDeltaPocs[RefRpsIdx];
2243 } else {
2244 const num_negative_pics = readExpGolomb(bitstream);
2245 const num_positive_pics = readExpGolomb(bitstream);
2246 for (let i2 = 0; i2 < num_negative_pics; i2++) {
2247 readExpGolomb(bitstream);
2248 bitstream.readBits(1);
2249 }
2250 for (let i2 = 0; i2 < num_positive_pics; i2++) {
2251 readExpGolomb(bitstream);
2252 bitstream.readBits(1);
2253 }
2254 NumDeltaPocsThis = num_negative_pics + num_positive_pics;
2255 }
2256 return NumDeltaPocsThis;
2257 };
2258 var parseHevcVui = (bitstream, sps_max_sub_layers_minus1) => {
2259 let colourPrimaries = 2;
2260 let transferCharacteristics = 2;
2261 let matrixCoefficients = 2;
2262 let fullRangeFlag = 0;
2263 let minSpatialSegmentationIdc = 0;
2264 let pixelAspectRatio = { num: 1, den: 1 };
2265 if (bitstream.readBits(1)) {
2266 const aspect_ratio_idc = bitstream.readBits(8);
2267 if (aspect_ratio_idc === 255) {
2268 pixelAspectRatio = {
2269 num: bitstream.readBits(16),
2270 den: bitstream.readBits(16)
2271 };
2272 } else {
2273 const aspectRatio = AVC_HEVC_ASPECT_RATIO_IDC_TABLE[aspect_ratio_idc];
2274 if (aspectRatio) {
2275 pixelAspectRatio = aspectRatio;
2276 }
2277 }
2278 }
2279 if (bitstream.readBits(1)) {
2280 bitstream.readBits(1);
2281 }
2282 if (bitstream.readBits(1)) {
2283 bitstream.readBits(3);
2284 fullRangeFlag = bitstream.readBits(1);
2285 if (bitstream.readBits(1)) {
2286 colourPrimaries = bitstream.readBits(8);
2287 transferCharacteristics = bitstream.readBits(8);
2288 matrixCoefficients = bitstream.readBits(8);
2289 }
2290 }
2291 if (bitstream.readBits(1)) {
2292 readExpGolomb(bitstream);
2293 readExpGolomb(bitstream);
2294 }
2295 bitstream.readBits(1);
2296 bitstream.readBits(1);
2297 bitstream.readBits(1);
2298 if (bitstream.readBits(1)) {
2299 readExpGolomb(bitstream);
2300 readExpGolomb(bitstream);
2301 readExpGolomb(bitstream);
2302 readExpGolomb(bitstream);
2303 }
2304 if (bitstream.readBits(1)) {
2305 bitstream.readBits(32);
2306 bitstream.readBits(32);
2307 if (bitstream.readBits(1)) {
2308 readExpGolomb(bitstream);
2309 }
2310 if (bitstream.readBits(1)) {
2311 skipHevcHrdParameters(bitstream, true, sps_max_sub_layers_minus1);
2312 }
2313 }
2314 if (bitstream.readBits(1)) {
2315 bitstream.readBits(1);
2316 bitstream.readBits(1);
2317 bitstream.readBits(1);
2318 minSpatialSegmentationIdc = readExpGolomb(bitstream);
2319 readExpGolomb(bitstream);
2320 readExpGolomb(bitstream);
2321 readExpGolomb(bitstream);
2322 readExpGolomb(bitstream);
2323 }
2324 return {
2325 pixelAspectRatio,
2326 colourPrimaries,
2327 transferCharacteristics,
2328 matrixCoefficients,
2329 fullRangeFlag,
2330 minSpatialSegmentationIdc
2331 };
2332 };
2333 var skipHevcHrdParameters = (bitstream, commonInfPresentFlag, maxNumSubLayersMinus1) => {
2334 let nal_hrd_parameters_present_flag = false;
2335 let vcl_hrd_parameters_present_flag = false;
2336 let sub_pic_hrd_params_present_flag = false;
2337 if (commonInfPresentFlag) {
2338 nal_hrd_parameters_present_flag = bitstream.readBits(1) === 1;
2339 vcl_hrd_parameters_present_flag = bitstream.readBits(1) === 1;
2340 if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
2341 sub_pic_hrd_params_present_flag = bitstream.readBits(1) === 1;
2342 if (sub_pic_hrd_params_present_flag) {
2343 bitstream.readBits(8);
2344 bitstream.readBits(5);
2345 bitstream.readBits(1);
2346 bitstream.readBits(5);
2347 }
2348 bitstream.readBits(4);
2349 bitstream.readBits(4);
2350 if (sub_pic_hrd_params_present_flag) {
2351 bitstream.readBits(4);
2352 }
2353 bitstream.readBits(5);
2354 bitstream.readBits(5);
2355 bitstream.readBits(5);
2356 }
2357 }
2358 for (let i2 = 0; i2 <= maxNumSubLayersMinus1; i2++) {
2359 const fixed_pic_rate_general_flag = bitstream.readBits(1) === 1;
2360 let fixed_pic_rate_within_cvs_flag = true;
2361 if (!fixed_pic_rate_general_flag) {
2362 fixed_pic_rate_within_cvs_flag = bitstream.readBits(1) === 1;
2363 }
2364 let low_delay_hrd_flag = false;
2365 if (fixed_pic_rate_within_cvs_flag) {
2366 readExpGolomb(bitstream);
2367 } else {
2368 low_delay_hrd_flag = bitstream.readBits(1) === 1;
2369 }
2370 let CpbCnt = 1;
2371 if (!low_delay_hrd_flag) {
2372 const cpb_cnt_minus1 = readExpGolomb(bitstream);
2373 CpbCnt = cpb_cnt_minus1 + 1;
2374 }
2375 if (nal_hrd_parameters_present_flag) {
2376 skipSubLayerHrdParameters(bitstream, CpbCnt, sub_pic_hrd_params_present_flag);
2377 }
2378 if (vcl_hrd_parameters_present_flag) {
2379 skipSubLayerHrdParameters(bitstream, CpbCnt, sub_pic_hrd_params_present_flag);
2380 }
2381 }
2382 };
2383 var skipSubLayerHrdParameters = (bitstream, CpbCnt, sub_pic_hrd_params_present_flag) => {
2384 for (let i2 = 0; i2 < CpbCnt; i2++) {
2385 readExpGolomb(bitstream);
2386 readExpGolomb(bitstream);
2387 if (sub_pic_hrd_params_present_flag) {
2388 readExpGolomb(bitstream);
2389 readExpGolomb(bitstream);
2390 }
2391 bitstream.readBits(1);
2392 }
2393 };
2394 var serializeHevcDecoderConfigurationRecord = (record) => {
2395 const bytes2 = [];
2396 bytes2.push(record.configurationVersion);
2397 bytes2.push((record.generalProfileSpace & 3) << 6 | (record.generalTierFlag & 1) << 5 | record.generalProfileIdc & 31);
2398 bytes2.push(record.generalProfileCompatibilityFlags >>> 24 & 255);
2399 bytes2.push(record.generalProfileCompatibilityFlags >>> 16 & 255);
2400 bytes2.push(record.generalProfileCompatibilityFlags >>> 8 & 255);
2401 bytes2.push(record.generalProfileCompatibilityFlags & 255);
2402 bytes2.push(...record.generalConstraintIndicatorFlags);
2403 bytes2.push(record.generalLevelIdc & 255);
2404 bytes2.push(240 | record.minSpatialSegmentationIdc >> 8 & 15);
2405 bytes2.push(record.minSpatialSegmentationIdc & 255);
2406 bytes2.push(252 | record.parallelismType & 3);
2407 bytes2.push(252 | record.chromaFormatIdc & 3);
2408 bytes2.push(248 | record.bitDepthLumaMinus8 & 7);
2409 bytes2.push(248 | record.bitDepthChromaMinus8 & 7);
2410 bytes2.push(record.avgFrameRate >> 8 & 255);
2411 bytes2.push(record.avgFrameRate & 255);
2412 bytes2.push((record.constantFrameRate & 3) << 6 | (record.numTemporalLayers & 7) << 3 | (record.temporalIdNested & 1) << 2 | record.lengthSizeMinusOne & 3);
2413 bytes2.push(record.arrays.length & 255);
2414 for (const arr of record.arrays) {
2415 bytes2.push((arr.arrayCompleteness & 1) << 7 | 0 << 6 | arr.nalUnitType & 63);
2416 bytes2.push(arr.nalUnits.length >> 8 & 255);
2417 bytes2.push(arr.nalUnits.length & 255);
2418 for (const nal of arr.nalUnits) {
2419 bytes2.push(nal.length >> 8 & 255);
2420 bytes2.push(nal.length & 255);
2421 for (let i2 = 0; i2 < nal.length; i2++) {
2422 bytes2.push(nal[i2]);
2423 }
2424 }
2425 }
2426 return new Uint8Array(bytes2);
2427 };
2428 var HevcNaluOrderState;
2429 (function(HevcNaluOrderState2) {
2430 HevcNaluOrderState2[HevcNaluOrderState2["audAllowed"] = 0] = "audAllowed";
2431 HevcNaluOrderState2[HevcNaluOrderState2["beforeFirstVcl"] = 1] = "beforeFirstVcl";
2432 HevcNaluOrderState2[HevcNaluOrderState2["afterFirstVcl"] = 2] = "afterFirstVcl";
2433 HevcNaluOrderState2[HevcNaluOrderState2["eoBitstreamAllowed"] = 3] = "eoBitstreamAllowed";
2434 HevcNaluOrderState2[HevcNaluOrderState2["noMoreDataAllowed"] = 4] = "noMoreDataAllowed";
2435 })(HevcNaluOrderState || (HevcNaluOrderState = {}));
2436 var iterateAv1PacketObus = function* (packet) {
2437 const bitstream = new Bitstream(packet);
2438 const readLeb128 = () => {
2439 let value = 0;
2440 for (let i2 = 0; i2 < 8; i2++) {
2441 const byte = bitstream.readAlignedByte();
2442 value |= (byte & 127) << i2 * 7;
2443 if (!(byte & 128)) {
2444 break;
2445 }
2446 if (i2 === 7 && byte & 128) {
2447 return null;
2448 }
2449 }
2450 if (value >= 2 ** 32 - 1) {
2451 return null;
2452 }
2453 return value;
2454 };
2455 while (bitstream.getBitsLeft() >= 8) {
2456 bitstream.skipBits(1);
2457 const obuType = bitstream.readBits(4);
2458 const obuExtension = bitstream.readBits(1);
2459 const obuHasSizeField = bitstream.readBits(1);
2460 bitstream.skipBits(1);
2461 if (obuExtension) {
2462 bitstream.skipBits(8);
2463 }
2464 let obuSize;
2465 if (obuHasSizeField) {
2466 const obuSizeValue = readLeb128();
2467 if (obuSizeValue === null)
2468 return;
2469 obuSize = obuSizeValue;
2470 } else {
2471 obuSize = Math.floor(bitstream.getBitsLeft() / 8);
2472 }
2473 assert(bitstream.pos % 8 === 0);
2474 yield {
2475 type: obuType,
2476 data: packet.subarray(bitstream.pos / 8, bitstream.pos / 8 + obuSize)
2477 };
2478 bitstream.skipBits(obuSize * 8);
2479 }
2480 };
2481 var parseOpusIdentificationHeader = (bytes2) => {
2482 const view2 = toDataView(bytes2);
2483 const outputChannelCount = view2.getUint8(9);
2484 const preSkip = view2.getUint16(10, true);
2485 const inputSampleRate = view2.getUint32(12, true);
2486 const outputGain = view2.getInt16(16, true);
2487 const channelMappingFamily = view2.getUint8(18);
2488 let channelMappingTable = null;
2489 if (channelMappingFamily) {
2490 channelMappingTable = bytes2.subarray(19, 19 + 2 + outputChannelCount);
2491 }
2492 return {
2493 outputChannelCount,
2494 preSkip,
2495 inputSampleRate,
2496 outputGain,
2497 channelMappingFamily,
2498 channelMappingTable
2499 };
2500 };
2501 var determineVideoPacketType = (codec, decoderConfig, packetData) => {
2502 switch (codec) {
2503 case "avc":
2504 {
2505 for (const loc of iterateAvcNalUnits(packetData, decoderConfig)) {
2506 const nalTypeByte = packetData[loc.offset];
2507 const type = extractNalUnitTypeForAvc(nalTypeByte);
2508 if (type >= AvcNalUnitType.NON_IDR_SLICE && type <= AvcNalUnitType.SLICE_DPC) {
2509 return "delta";
2510 }
2511 if (type === AvcNalUnitType.IDR) {
2512 return "key";
2513 }
2514 if (type === AvcNalUnitType.SEI && (!isChromium() || getChromiumVersion() >= 144)) {
2515 const nalUnit = packetData.subarray(loc.offset, loc.offset + loc.length);
2516 const bytes2 = removeEmulationPreventionBytes(nalUnit);
2517 let pos = 1;
2518 do {
2519 let payloadType = 0;
2520 while (true) {
2521 const nextByte = bytes2[pos++];
2522 if (nextByte === void 0)
2523 break;
2524 payloadType += nextByte;
2525 if (nextByte < 255) {
2526 break;
2527 }
2528 }
2529 let payloadSize = 0;
2530 while (true) {
2531 const nextByte = bytes2[pos++];
2532 if (nextByte === void 0)
2533 break;
2534 payloadSize += nextByte;
2535 if (nextByte < 255) {
2536 break;
2537 }
2538 }
2539 const PAYLOAD_TYPE_RECOVERY_POINT = 6;
2540 if (payloadType === PAYLOAD_TYPE_RECOVERY_POINT) {
2541 const bitstream = new Bitstream(bytes2);
2542 bitstream.pos = 8 * pos;
2543 const recoveryFrameCount = readExpGolomb(bitstream);
2544 const exactMatchFlag = bitstream.readBits(1);
2545 if (recoveryFrameCount === 0 && exactMatchFlag === 1) {
2546 return "key";
2547 }
2548 }
2549 pos += payloadSize;
2550 } while (pos < bytes2.length - 1);
2551 }
2552 }
2553 return "delta";
2554 }
2555 ;
2556 case "hevc":
2557 {
2558 for (const loc of iterateHevcNalUnits(packetData, decoderConfig)) {
2559 const type = extractNalUnitTypeForHevc(packetData[loc.offset]);
2560 if (type < HevcNalUnitType.BLA_W_LP) {
2561 return "delta";
2562 }
2563 if (type <= HevcNalUnitType.RSV_IRAP_VCL23) {
2564 return "key";
2565 }
2566 }
2567 return "delta";
2568 }
2569 ;
2570 case "vp8":
2571 {
2572 const frameType = packetData[0] & 1;
2573 return frameType === 0 ? "key" : "delta";
2574 }
2575 ;
2576 case "vp9":
2577 {
2578 const bitstream = new Bitstream(packetData);
2579 if (bitstream.readBits(2) !== 2) {
2580 return null;
2581 }
2582 ;
2583 const profileLowBit = bitstream.readBits(1);
2584 const profileHighBit = bitstream.readBits(1);
2585 const profile = (profileHighBit << 1) + profileLowBit;
2586 if (profile === 3) {
2587 bitstream.skipBits(1);
2588 }
2589 const showExistingFrame = bitstream.readBits(1);
2590 if (showExistingFrame) {
2591 return null;
2592 }
2593 const frameType = bitstream.readBits(1);
2594 return frameType === 0 ? "key" : "delta";
2595 }
2596 ;
2597 case "av1":
2598 {
2599 let reducedStillPictureHeader = false;
2600 for (const { type, data } of iterateAv1PacketObus(packetData)) {
2601 if (type === 1) {
2602 const bitstream = new Bitstream(data);
2603 bitstream.skipBits(4);
2604 reducedStillPictureHeader = !!bitstream.readBits(1);
2605 } else if (type === 3 || type === 6 || type === 7) {
2606 if (reducedStillPictureHeader) {
2607 return "key";
2608 }
2609 const bitstream = new Bitstream(data);
2610 const showExistingFrame = bitstream.readBits(1);
2611 if (showExistingFrame) {
2612 return null;
2613 }
2614 const frameType = bitstream.readBits(2);
2615 return frameType === 0 ? "key" : "delta";
2616 }
2617 }
2618 return null;
2619 }
2620 ;
2621 default:
2622 {
2623 assertNever(codec);
2624 assert(false);
2625 }
2626 ;
2627 }
2628 };
2629 var FlacBlockType;
2630 (function(FlacBlockType2) {
2631 FlacBlockType2[FlacBlockType2["STREAMINFO"] = 0] = "STREAMINFO";
2632 FlacBlockType2[FlacBlockType2["VORBIS_COMMENT"] = 4] = "VORBIS_COMMENT";
2633 FlacBlockType2[FlacBlockType2["PICTURE"] = 6] = "PICTURE";
2634 })(FlacBlockType || (FlacBlockType = {}));
2635 var parseAc3SyncFrame = (data) => {
2636 if (data.length < 7) {
2637 return null;
2638 }
2639 if (data[0] !== 11 || data[1] !== 119) {
2640 return null;
2641 }
2642 const bitstream = new Bitstream(data);
2643 bitstream.skipBits(16);
2644 bitstream.skipBits(16);
2645 const fscod = bitstream.readBits(2);
2646 if (fscod === 3) {
2647 return null;
2648 }
2649 const frmsizecod = bitstream.readBits(6);
2650 const bsid = bitstream.readBits(5);
2651 if (bsid > 8) {
2652 return null;
2653 }
2654 const bsmod = bitstream.readBits(3);
2655 const acmod = bitstream.readBits(3);
2656 if ((acmod & 1) !== 0 && acmod !== 1) {
2657 bitstream.skipBits(2);
2658 }
2659 if ((acmod & 4) !== 0) {
2660 bitstream.skipBits(2);
2661 }
2662 if (acmod === 2) {
2663 bitstream.skipBits(2);
2664 }
2665 const lfeon = bitstream.readBits(1);
2666 const bitRateCode = Math.floor(frmsizecod / 2);
2667 return { fscod, bsid, bsmod, acmod, lfeon, bitRateCode };
2668 };
2669 var AC3_FRAME_SIZES = [
2670 // frmsizecod, [48kHz, 44.1kHz, 32kHz] in bytes
2671 64 * 2,
2672 69 * 2,
2673 96 * 2,
2674 64 * 2,
2675 70 * 2,
2676 96 * 2,
2677 80 * 2,
2678 87 * 2,
2679 120 * 2,
2680 80 * 2,
2681 88 * 2,
2682 120 * 2,
2683 96 * 2,
2684 104 * 2,
2685 144 * 2,
2686 96 * 2,
2687 105 * 2,
2688 144 * 2,
2689 112 * 2,
2690 121 * 2,
2691 168 * 2,
2692 112 * 2,
2693 122 * 2,
2694 168 * 2,
2695 128 * 2,
2696 139 * 2,
2697 192 * 2,
2698 128 * 2,
2699 140 * 2,
2700 192 * 2,
2701 160 * 2,
2702 174 * 2,
2703 240 * 2,
2704 160 * 2,
2705 175 * 2,
2706 240 * 2,
2707 192 * 2,
2708 208 * 2,
2709 288 * 2,
2710 192 * 2,
2711 209 * 2,
2712 288 * 2,
2713 224 * 2,
2714 243 * 2,
2715 336 * 2,
2716 224 * 2,
2717 244 * 2,
2718 336 * 2,
2719 256 * 2,
2720 278 * 2,
2721 384 * 2,
2722 256 * 2,
2723 279 * 2,
2724 384 * 2,
2725 320 * 2,
2726 348 * 2,
2727 480 * 2,
2728 320 * 2,
2729 349 * 2,
2730 480 * 2,
2731 384 * 2,
2732 417 * 2,
2733 576 * 2,
2734 384 * 2,
2735 418 * 2,
2736 576 * 2,
2737 448 * 2,
2738 487 * 2,
2739 672 * 2,
2740 448 * 2,
2741 488 * 2,
2742 672 * 2,
2743 512 * 2,
2744 557 * 2,
2745 768 * 2,
2746 512 * 2,
2747 558 * 2,
2748 768 * 2,
2749 640 * 2,
2750 696 * 2,
2751 960 * 2,
2752 640 * 2,
2753 697 * 2,
2754 960 * 2,
2755 768 * 2,
2756 835 * 2,
2757 1152 * 2,
2758 768 * 2,
2759 836 * 2,
2760 1152 * 2,
2761 896 * 2,
2762 975 * 2,
2763 1344 * 2,
2764 896 * 2,
2765 976 * 2,
2766 1344 * 2,
2767 1024 * 2,
2768 1114 * 2,
2769 1536 * 2,
2770 1024 * 2,
2771 1115 * 2,
2772 1536 * 2,
2773 1152 * 2,
2774 1253 * 2,
2775 1728 * 2,
2776 1152 * 2,
2777 1254 * 2,
2778 1728 * 2,
2779 1280 * 2,
2780 1393 * 2,
2781 1920 * 2,
2782 1280 * 2,
2783 1394 * 2,
2784 1920 * 2
2785 ];
2786 var AC3_REGISTRATION_DESCRIPTOR = new Uint8Array([5, 4, 65, 67, 45, 51]);
2787 var EAC3_REGISTRATION_DESCRIPTOR = new Uint8Array([5, 4, 69, 65, 67, 51]);
2788 var EAC3_NUMBLKS_TABLE = [1, 2, 3, 6];
2789 var parseEac3SyncFrame = (data) => {
2790 if (data.length < 6) {
2791 return null;
2792 }
2793 if (data[0] !== 11 || data[1] !== 119) {
2794 return null;
2795 }
2796 const bitstream = new Bitstream(data);
2797 bitstream.skipBits(16);
2798 const strmtyp = bitstream.readBits(2);
2799 bitstream.skipBits(3);
2800 if (strmtyp !== 0 && strmtyp !== 2) {
2801 return null;
2802 }
2803 const frmsiz = bitstream.readBits(11);
2804 const fscod = bitstream.readBits(2);
2805 let fscod2 = 0;
2806 let numblkscod;
2807 if (fscod === 3) {
2808 fscod2 = bitstream.readBits(2);
2809 numblkscod = 3;
2810 } else {
2811 numblkscod = bitstream.readBits(2);
2812 }
2813 const acmod = bitstream.readBits(3);
2814 const lfeon = bitstream.readBits(1);
2815 const bsid = bitstream.readBits(5);
2816 if (bsid < 11 || bsid > 16) {
2817 return null;
2818 }
2819 const numblks = EAC3_NUMBLKS_TABLE[numblkscod];
2820 let fs;
2821 if (fscod < 3) {
2822 fs = AC3_SAMPLE_RATES[fscod] / 1e3;
2823 } else {
2824 fs = EAC3_REDUCED_SAMPLE_RATES[fscod2] / 1e3;
2825 }
2826 const dataRate = Math.round((frmsiz + 1) * fs / (numblks * 16));
2827 const bsmod = 0;
2828 const numDepSub = 0;
2829 const chanLoc = 0;
2830 const substream = {
2831 fscod,
2832 fscod2,
2833 bsid,
2834 bsmod,
2835 acmod,
2836 lfeon,
2837 numDepSub,
2838 chanLoc
2839 };
2840 return {
2841 dataRate,
2842 substreams: [substream]
2843 };
2844 };
2845
2846 // node_modules/mediabunny/dist/modules/src/packet.js
2847 var PLACEHOLDER_DATA = /* @__PURE__ */ new Uint8Array(0);
2848 var EncodedPacket = class _EncodedPacket {
2849 /** Creates a new {@link EncodedPacket} from raw bytes and timing information. */
2850 constructor(data, type, timestamp, duration, sequenceNumber = -1, byteLength, sideData) {
2851 this.data = data;
2852 this.type = type;
2853 this.timestamp = timestamp;
2854 this.duration = duration;
2855 this.sequenceNumber = sequenceNumber;
2856 if (data === PLACEHOLDER_DATA && byteLength === void 0) {
2857 throw new Error("Internal error: byteLength must be explicitly provided when constructing metadata-only packets.");
2858 }
2859 if (byteLength === void 0) {
2860 byteLength = data.byteLength;
2861 }
2862 if (!(data instanceof Uint8Array)) {
2863 throw new TypeError("data must be a Uint8Array.");
2864 }
2865 if (type !== "key" && type !== "delta") {
2866 throw new TypeError('type must be either "key" or "delta".');
2867 }
2868 if (!Number.isFinite(timestamp)) {
2869 throw new TypeError("timestamp must be a number.");
2870 }
2871 if (!Number.isFinite(duration) || duration < 0) {
2872 throw new TypeError("duration must be a non-negative number.");
2873 }
2874 if (!Number.isFinite(sequenceNumber)) {
2875 throw new TypeError("sequenceNumber must be a number.");
2876 }
2877 if (!Number.isInteger(byteLength) || byteLength < 0) {
2878 throw new TypeError("byteLength must be a non-negative integer.");
2879 }
2880 if (sideData !== void 0 && (typeof sideData !== "object" || !sideData)) {
2881 throw new TypeError("sideData, when provided, must be an object.");
2882 }
2883 if (sideData?.alpha !== void 0 && !(sideData.alpha instanceof Uint8Array)) {
2884 throw new TypeError("sideData.alpha, when provided, must be a Uint8Array.");
2885 }
2886 if (sideData?.alphaByteLength !== void 0 && (!Number.isInteger(sideData.alphaByteLength) || sideData.alphaByteLength < 0)) {
2887 throw new TypeError("sideData.alphaByteLength, when provided, must be a non-negative integer.");
2888 }
2889 this.byteLength = byteLength;
2890 this.sideData = sideData ?? {};
2891 if (this.sideData.alpha && this.sideData.alphaByteLength === void 0) {
2892 this.sideData.alphaByteLength = this.sideData.alpha.byteLength;
2893 }
2894 }
2895 /**
2896 * If this packet is a metadata-only packet. Metadata-only packets don't contain their packet data. They are the
2897 * result of retrieving packets with {@link PacketRetrievalOptions.metadataOnly} set to \`true\`.
2898 */
2899 get isMetadataOnly() {
2900 return this.data === PLACEHOLDER_DATA;
2901 }
2902 /** The timestamp of this packet in microseconds. */
2903 get microsecondTimestamp() {
2904 return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.timestamp);
2905 }
2906 /** The duration of this packet in microseconds. */
2907 get microsecondDuration() {
2908 return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.duration);
2909 }
2910 /** Converts this packet to an
2911 * [\`EncodedVideoChunk\`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedVideoChunk) for use with the
2912 * WebCodecs API. */
2913 toEncodedVideoChunk() {
2914 if (this.isMetadataOnly) {
2915 throw new TypeError("Metadata-only packets cannot be converted to a video chunk.");
2916 }
2917 if (typeof EncodedVideoChunk === "undefined") {
2918 throw new Error("Your browser does not support EncodedVideoChunk.");
2919 }
2920 return new EncodedVideoChunk({
2921 data: this.data,
2922 type: this.type,
2923 timestamp: this.microsecondTimestamp,
2924 duration: this.microsecondDuration
2925 });
2926 }
2927 /**
2928 * Converts this packet to an
2929 * [\`EncodedVideoChunk\`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedVideoChunk) for use with the
2930 * WebCodecs API, using the alpha side data instead of the color data. Throws if no alpha side data is defined.
2931 */
2932 alphaToEncodedVideoChunk(type = this.type) {
2933 if (!this.sideData.alpha) {
2934 throw new TypeError("This packet does not contain alpha side data.");
2935 }
2936 if (this.isMetadataOnly) {
2937 throw new TypeError("Metadata-only packets cannot be converted to a video chunk.");
2938 }
2939 if (typeof EncodedVideoChunk === "undefined") {
2940 throw new Error("Your browser does not support EncodedVideoChunk.");
2941 }
2942 return new EncodedVideoChunk({
2943 data: this.sideData.alpha,
2944 type,
2945 timestamp: this.microsecondTimestamp,
2946 duration: this.microsecondDuration
2947 });
2948 }
2949 /** Converts this packet to an
2950 * [\`EncodedAudioChunk\`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedAudioChunk) for use with the
2951 * WebCodecs API. */
2952 toEncodedAudioChunk() {
2953 if (this.isMetadataOnly) {
2954 throw new TypeError("Metadata-only packets cannot be converted to an audio chunk.");
2955 }
2956 if (typeof EncodedAudioChunk === "undefined") {
2957 throw new Error("Your browser does not support EncodedAudioChunk.");
2958 }
2959 return new EncodedAudioChunk({
2960 data: this.data,
2961 type: this.type,
2962 timestamp: this.microsecondTimestamp,
2963 duration: this.microsecondDuration
2964 });
2965 }
2966 /**
2967 * Creates an {@link EncodedPacket} from an
2968 * [\`EncodedVideoChunk\`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedVideoChunk) or
2969 * [\`EncodedAudioChunk\`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedAudioChunk). This method is useful
2970 * for converting chunks from the WebCodecs API to \`EncodedPacket\` instances.
2971 */
2972 static fromEncodedChunk(chunk, sideData) {
2973 if (!(chunk instanceof EncodedVideoChunk || chunk instanceof EncodedAudioChunk)) {
2974 throw new TypeError("chunk must be an EncodedVideoChunk or EncodedAudioChunk.");
2975 }
2976 const data = new Uint8Array(chunk.byteLength);
2977 chunk.copyTo(data);
2978 return new _EncodedPacket(data, chunk.type, chunk.timestamp / 1e6, (chunk.duration ?? 0) / 1e6, void 0, void 0, sideData);
2979 }
2980 /** Clones this packet while optionally modifying the new packet's data. */
2981 clone(options) {
2982 if (options !== void 0 && (typeof options !== "object" || options === null)) {
2983 throw new TypeError("options, when provided, must be an object.");
2984 }
2985 if (options?.data !== void 0 && !(options.data instanceof Uint8Array)) {
2986 throw new TypeError("options.data, when provided, must be a Uint8Array.");
2987 }
2988 if (options?.type !== void 0 && options.type !== "key" && options.type !== "delta") {
2989 throw new TypeError('options.type, when provided, must be either "key" or "delta".');
2990 }
2991 if (options?.timestamp !== void 0 && !Number.isFinite(options.timestamp)) {
2992 throw new TypeError("options.timestamp, when provided, must be a number.");
2993 }
2994 if (options?.duration !== void 0 && !Number.isFinite(options.duration)) {
2995 throw new TypeError("options.duration, when provided, must be a number.");
2996 }
2997 if (options?.sequenceNumber !== void 0 && !Number.isFinite(options.sequenceNumber)) {
2998 throw new TypeError("options.sequenceNumber, when provided, must be a number.");
2999 }
3000 if (options?.sideData !== void 0 && (typeof options.sideData !== "object" || options.sideData === null)) {
3001 throw new TypeError("options.sideData, when provided, must be an object.");
3002 }
3003 return new _EncodedPacket(options?.data ?? this.data, options?.type ?? this.type, options?.timestamp ?? this.timestamp, options?.duration ?? this.duration, options?.sequenceNumber ?? this.sequenceNumber, this.byteLength, options?.sideData ?? this.sideData);
3004 }
3005 };
3006
3007 // node_modules/mediabunny/dist/modules/src/isobmff/isobmff-misc.js
3008 var buildIsobmffMimeType = (info) => {
3009 const base = info.hasVideo ? "video/" : info.hasAudio ? "audio/" : "application/";
3010 let string = base + (info.isQuickTime ? "quicktime" : "mp4");
3011 if (info.codecStrings.length > 0) {
3012 const uniqueCodecMimeTypes = [...new Set(info.codecStrings)];
3013 string += \`; codecs="\${uniqueCodecMimeTypes.join(", ")}"\`;
3014 }
3015 return string;
3016 };
3017
3018 // node_modules/mediabunny/dist/modules/src/isobmff/isobmff-reader.js
3019 var MIN_BOX_HEADER_SIZE = 8;
3020 var MAX_BOX_HEADER_SIZE = 16;
3021
3022 // node_modules/mediabunny/dist/modules/src/matroska/ebml.js
3023 var EBMLFloat32 = class {
3024 constructor(value) {
3025 this.value = value;
3026 }
3027 };
3028 var EBMLFloat64 = class {
3029 constructor(value) {
3030 this.value = value;
3031 }
3032 };
3033 var EBMLSignedInt = class {
3034 constructor(value) {
3035 this.value = value;
3036 }
3037 };
3038 var EBMLUnicodeString = class {
3039 constructor(value) {
3040 this.value = value;
3041 }
3042 };
3043 var EBMLId;
3044 (function(EBMLId2) {
3045 EBMLId2[EBMLId2["EBML"] = 440786851] = "EBML";
3046 EBMLId2[EBMLId2["EBMLVersion"] = 17030] = "EBMLVersion";
3047 EBMLId2[EBMLId2["EBMLReadVersion"] = 17143] = "EBMLReadVersion";
3048 EBMLId2[EBMLId2["EBMLMaxIDLength"] = 17138] = "EBMLMaxIDLength";
3049 EBMLId2[EBMLId2["EBMLMaxSizeLength"] = 17139] = "EBMLMaxSizeLength";
3050 EBMLId2[EBMLId2["DocType"] = 17026] = "DocType";
3051 EBMLId2[EBMLId2["DocTypeVersion"] = 17031] = "DocTypeVersion";
3052 EBMLId2[EBMLId2["DocTypeReadVersion"] = 17029] = "DocTypeReadVersion";
3053 EBMLId2[EBMLId2["Void"] = 236] = "Void";
3054 EBMLId2[EBMLId2["Segment"] = 408125543] = "Segment";
3055 EBMLId2[EBMLId2["SeekHead"] = 290298740] = "SeekHead";
3056 EBMLId2[EBMLId2["Seek"] = 19899] = "Seek";
3057 EBMLId2[EBMLId2["SeekID"] = 21419] = "SeekID";
3058 EBMLId2[EBMLId2["SeekPosition"] = 21420] = "SeekPosition";
3059 EBMLId2[EBMLId2["Duration"] = 17545] = "Duration";
3060 EBMLId2[EBMLId2["Info"] = 357149030] = "Info";
3061 EBMLId2[EBMLId2["TimestampScale"] = 2807729] = "TimestampScale";
3062 EBMLId2[EBMLId2["MuxingApp"] = 19840] = "MuxingApp";
3063 EBMLId2[EBMLId2["WritingApp"] = 22337] = "WritingApp";
3064 EBMLId2[EBMLId2["Tracks"] = 374648427] = "Tracks";
3065 EBMLId2[EBMLId2["TrackEntry"] = 174] = "TrackEntry";
3066 EBMLId2[EBMLId2["TrackNumber"] = 215] = "TrackNumber";
3067 EBMLId2[EBMLId2["TrackUID"] = 29637] = "TrackUID";
3068 EBMLId2[EBMLId2["TrackType"] = 131] = "TrackType";
3069 EBMLId2[EBMLId2["FlagEnabled"] = 185] = "FlagEnabled";
3070 EBMLId2[EBMLId2["FlagDefault"] = 136] = "FlagDefault";
3071 EBMLId2[EBMLId2["FlagForced"] = 21930] = "FlagForced";
3072 EBMLId2[EBMLId2["FlagOriginal"] = 21934] = "FlagOriginal";
3073 EBMLId2[EBMLId2["FlagHearingImpaired"] = 21931] = "FlagHearingImpaired";
3074 EBMLId2[EBMLId2["FlagVisualImpaired"] = 21932] = "FlagVisualImpaired";
3075 EBMLId2[EBMLId2["FlagCommentary"] = 21935] = "FlagCommentary";
3076 EBMLId2[EBMLId2["FlagLacing"] = 156] = "FlagLacing";
3077 EBMLId2[EBMLId2["Name"] = 21358] = "Name";
3078 EBMLId2[EBMLId2["Language"] = 2274716] = "Language";
3079 EBMLId2[EBMLId2["LanguageBCP47"] = 2274717] = "LanguageBCP47";
3080 EBMLId2[EBMLId2["CodecID"] = 134] = "CodecID";
3081 EBMLId2[EBMLId2["CodecPrivate"] = 25506] = "CodecPrivate";
3082 EBMLId2[EBMLId2["CodecDelay"] = 22186] = "CodecDelay";
3083 EBMLId2[EBMLId2["SeekPreRoll"] = 22203] = "SeekPreRoll";
3084 EBMLId2[EBMLId2["DefaultDuration"] = 2352003] = "DefaultDuration";
3085 EBMLId2[EBMLId2["Video"] = 224] = "Video";
3086 EBMLId2[EBMLId2["PixelWidth"] = 176] = "PixelWidth";
3087 EBMLId2[EBMLId2["PixelHeight"] = 186] = "PixelHeight";
3088 EBMLId2[EBMLId2["DisplayWidth"] = 21680] = "DisplayWidth";
3089 EBMLId2[EBMLId2["DisplayHeight"] = 21690] = "DisplayHeight";
3090 EBMLId2[EBMLId2["DisplayUnit"] = 21682] = "DisplayUnit";
3091 EBMLId2[EBMLId2["AlphaMode"] = 21440] = "AlphaMode";
3092 EBMLId2[EBMLId2["Audio"] = 225] = "Audio";
3093 EBMLId2[EBMLId2["SamplingFrequency"] = 181] = "SamplingFrequency";
3094 EBMLId2[EBMLId2["Channels"] = 159] = "Channels";
3095 EBMLId2[EBMLId2["BitDepth"] = 25188] = "BitDepth";
3096 EBMLId2[EBMLId2["SimpleBlock"] = 163] = "SimpleBlock";
3097 EBMLId2[EBMLId2["BlockGroup"] = 160] = "BlockGroup";
3098 EBMLId2[EBMLId2["Block"] = 161] = "Block";
3099 EBMLId2[EBMLId2["BlockAdditions"] = 30113] = "BlockAdditions";
3100 EBMLId2[EBMLId2["BlockMore"] = 166] = "BlockMore";
3101 EBMLId2[EBMLId2["BlockAdditional"] = 165] = "BlockAdditional";
3102 EBMLId2[EBMLId2["BlockAddID"] = 238] = "BlockAddID";
3103 EBMLId2[EBMLId2["BlockDuration"] = 155] = "BlockDuration";
3104 EBMLId2[EBMLId2["ReferenceBlock"] = 251] = "ReferenceBlock";
3105 EBMLId2[EBMLId2["Cluster"] = 524531317] = "Cluster";
3106 EBMLId2[EBMLId2["Timestamp"] = 231] = "Timestamp";
3107 EBMLId2[EBMLId2["Cues"] = 475249515] = "Cues";
3108 EBMLId2[EBMLId2["CuePoint"] = 187] = "CuePoint";
3109 EBMLId2[EBMLId2["CueTime"] = 179] = "CueTime";
3110 EBMLId2[EBMLId2["CueTrackPositions"] = 183] = "CueTrackPositions";
3111 EBMLId2[EBMLId2["CueTrack"] = 247] = "CueTrack";
3112 EBMLId2[EBMLId2["CueClusterPosition"] = 241] = "CueClusterPosition";
3113 EBMLId2[EBMLId2["Colour"] = 21936] = "Colour";
3114 EBMLId2[EBMLId2["MatrixCoefficients"] = 21937] = "MatrixCoefficients";
3115 EBMLId2[EBMLId2["TransferCharacteristics"] = 21946] = "TransferCharacteristics";
3116 EBMLId2[EBMLId2["Primaries"] = 21947] = "Primaries";
3117 EBMLId2[EBMLId2["Range"] = 21945] = "Range";
3118 EBMLId2[EBMLId2["Projection"] = 30320] = "Projection";
3119 EBMLId2[EBMLId2["ProjectionType"] = 30321] = "ProjectionType";
3120 EBMLId2[EBMLId2["ProjectionPoseRoll"] = 30325] = "ProjectionPoseRoll";
3121 EBMLId2[EBMLId2["Attachments"] = 423732329] = "Attachments";
3122 EBMLId2[EBMLId2["AttachedFile"] = 24999] = "AttachedFile";
3123 EBMLId2[EBMLId2["FileDescription"] = 18046] = "FileDescription";
3124 EBMLId2[EBMLId2["FileName"] = 18030] = "FileName";
3125 EBMLId2[EBMLId2["FileMediaType"] = 18016] = "FileMediaType";
3126 EBMLId2[EBMLId2["FileData"] = 18012] = "FileData";
3127 EBMLId2[EBMLId2["FileUID"] = 18094] = "FileUID";
3128 EBMLId2[EBMLId2["Chapters"] = 272869232] = "Chapters";
3129 EBMLId2[EBMLId2["Tags"] = 307544935] = "Tags";
3130 EBMLId2[EBMLId2["Tag"] = 29555] = "Tag";
3131 EBMLId2[EBMLId2["Targets"] = 25536] = "Targets";
3132 EBMLId2[EBMLId2["TargetTypeValue"] = 26826] = "TargetTypeValue";
3133 EBMLId2[EBMLId2["TargetType"] = 25546] = "TargetType";
3134 EBMLId2[EBMLId2["TagTrackUID"] = 25541] = "TagTrackUID";
3135 EBMLId2[EBMLId2["TagEditionUID"] = 25545] = "TagEditionUID";
3136 EBMLId2[EBMLId2["TagChapterUID"] = 25540] = "TagChapterUID";
3137 EBMLId2[EBMLId2["TagAttachmentUID"] = 25542] = "TagAttachmentUID";
3138 EBMLId2[EBMLId2["SimpleTag"] = 26568] = "SimpleTag";
3139 EBMLId2[EBMLId2["TagName"] = 17827] = "TagName";
3140 EBMLId2[EBMLId2["TagLanguage"] = 17530] = "TagLanguage";
3141 EBMLId2[EBMLId2["TagString"] = 17543] = "TagString";
3142 EBMLId2[EBMLId2["TagBinary"] = 17541] = "TagBinary";
3143 EBMLId2[EBMLId2["ContentEncodings"] = 28032] = "ContentEncodings";
3144 EBMLId2[EBMLId2["ContentEncoding"] = 25152] = "ContentEncoding";
3145 EBMLId2[EBMLId2["ContentEncodingOrder"] = 20529] = "ContentEncodingOrder";
3146 EBMLId2[EBMLId2["ContentEncodingScope"] = 20530] = "ContentEncodingScope";
3147 EBMLId2[EBMLId2["ContentCompression"] = 20532] = "ContentCompression";
3148 EBMLId2[EBMLId2["ContentCompAlgo"] = 16980] = "ContentCompAlgo";
3149 EBMLId2[EBMLId2["ContentCompSettings"] = 16981] = "ContentCompSettings";
3150 EBMLId2[EBMLId2["ContentEncryption"] = 20533] = "ContentEncryption";
3151 })(EBMLId || (EBMLId = {}));
3152 var LEVEL_0_EBML_IDS = [
3153 EBMLId.EBML,
3154 EBMLId.Segment
3155 ];
3156 var LEVEL_1_EBML_IDS = [
3157 EBMLId.SeekHead,
3158 EBMLId.Info,
3159 EBMLId.Cluster,
3160 EBMLId.Tracks,
3161 EBMLId.Cues,
3162 EBMLId.Attachments,
3163 EBMLId.Chapters,
3164 EBMLId.Tags
3165 ];
3166 var LEVEL_0_AND_1_EBML_IDS = [
3167 ...LEVEL_0_EBML_IDS,
3168 ...LEVEL_1_EBML_IDS
3169 ];
3170 var measureUnsignedInt = (value) => {
3171 if (value < 1 << 8) {
3172 return 1;
3173 } else if (value < 1 << 16) {
3174 return 2;
3175 } else if (value < 1 << 24) {
3176 return 3;
3177 } else if (value < 2 ** 32) {
3178 return 4;
3179 } else if (value < 2 ** 40) {
3180 return 5;
3181 } else {
3182 return 6;
3183 }
3184 };
3185 var measureUnsignedBigInt = (value) => {
3186 if (value < 1n << 8n) {
3187 return 1;
3188 } else if (value < 1n << 16n) {
3189 return 2;
3190 } else if (value < 1n << 24n) {
3191 return 3;
3192 } else if (value < 1n << 32n) {
3193 return 4;
3194 } else if (value < 1n << 40n) {
3195 return 5;
3196 } else if (value < 1n << 48n) {
3197 return 6;
3198 } else if (value < 1n << 56n) {
3199 return 7;
3200 } else {
3201 return 8;
3202 }
3203 };
3204 var measureSignedInt = (value) => {
3205 if (value >= -(1 << 6) && value < 1 << 6) {
3206 return 1;
3207 } else if (value >= -(1 << 13) && value < 1 << 13) {
3208 return 2;
3209 } else if (value >= -(1 << 20) && value < 1 << 20) {
3210 return 3;
3211 } else if (value >= -(1 << 27) && value < 1 << 27) {
3212 return 4;
3213 } else if (value >= -(2 ** 34) && value < 2 ** 34) {
3214 return 5;
3215 } else {
3216 return 6;
3217 }
3218 };
3219 var measureVarInt = (value) => {
3220 if (value < (1 << 7) - 1) {
3221 return 1;
3222 } else if (value < (1 << 14) - 1) {
3223 return 2;
3224 } else if (value < (1 << 21) - 1) {
3225 return 3;
3226 } else if (value < (1 << 28) - 1) {
3227 return 4;
3228 } else if (value < 2 ** 35 - 1) {
3229 return 5;
3230 } else if (value < 2 ** 42 - 1) {
3231 return 6;
3232 } else {
3233 throw new Error("EBML varint size not supported " + value);
3234 }
3235 };
3236 var EBMLWriter = class {
3237 constructor(writer) {
3238 this.writer = writer;
3239 this.helper = new Uint8Array(8);
3240 this.helperView = new DataView(this.helper.buffer);
3241 this.offsets = /* @__PURE__ */ new WeakMap();
3242 this.dataOffsets = /* @__PURE__ */ new WeakMap();
3243 }
3244 writeByte(value) {
3245 this.helperView.setUint8(0, value);
3246 this.writer.write(this.helper.subarray(0, 1));
3247 }
3248 writeFloat32(value) {
3249 this.helperView.setFloat32(0, value, false);
3250 this.writer.write(this.helper.subarray(0, 4));
3251 }
3252 writeFloat64(value) {
3253 this.helperView.setFloat64(0, value, false);
3254 this.writer.write(this.helper);
3255 }
3256 writeUnsignedInt(value, width = measureUnsignedInt(value)) {
3257 let pos = 0;
3258 switch (width) {
3259 case 6:
3260 this.helperView.setUint8(pos++, value / 2 ** 40 | 0);
3261 // eslint-disable-next-line no-fallthrough
3262 case 5:
3263 this.helperView.setUint8(pos++, value / 2 ** 32 | 0);
3264 // eslint-disable-next-line no-fallthrough
3265 case 4:
3266 this.helperView.setUint8(pos++, value >> 24);
3267 // eslint-disable-next-line no-fallthrough
3268 case 3:
3269 this.helperView.setUint8(pos++, value >> 16);
3270 // eslint-disable-next-line no-fallthrough
3271 case 2:
3272 this.helperView.setUint8(pos++, value >> 8);
3273 // eslint-disable-next-line no-fallthrough
3274 case 1:
3275 this.helperView.setUint8(pos++, value);
3276 break;
3277 default:
3278 throw new Error("Bad unsigned int size " + width);
3279 }
3280 this.writer.write(this.helper.subarray(0, pos));
3281 }
3282 writeUnsignedBigInt(value, width = measureUnsignedBigInt(value)) {
3283 let pos = 0;
3284 for (let i2 = width - 1; i2 >= 0; i2--) {
3285 this.helperView.setUint8(pos++, Number(value >> BigInt(i2 * 8) & 0xffn));
3286 }
3287 this.writer.write(this.helper.subarray(0, pos));
3288 }
3289 writeSignedInt(value, width = measureSignedInt(value)) {
3290 if (value < 0) {
3291 value += 2 ** (width * 8);
3292 }
3293 this.writeUnsignedInt(value, width);
3294 }
3295 writeVarInt(value, width = measureVarInt(value)) {
3296 let pos = 0;
3297 switch (width) {
3298 case 1:
3299 this.helperView.setUint8(pos++, 1 << 7 | value);
3300 break;
3301 case 2:
3302 this.helperView.setUint8(pos++, 1 << 6 | value >> 8);
3303 this.helperView.setUint8(pos++, value);
3304 break;
3305 case 3:
3306 this.helperView.setUint8(pos++, 1 << 5 | value >> 16);
3307 this.helperView.setUint8(pos++, value >> 8);
3308 this.helperView.setUint8(pos++, value);
3309 break;
3310 case 4:
3311 this.helperView.setUint8(pos++, 1 << 4 | value >> 24);
3312 this.helperView.setUint8(pos++, value >> 16);
3313 this.helperView.setUint8(pos++, value >> 8);
3314 this.helperView.setUint8(pos++, value);
3315 break;
3316 case 5:
3317 this.helperView.setUint8(pos++, 1 << 3 | value / 2 ** 32 & 7);
3318 this.helperView.setUint8(pos++, value >> 24);
3319 this.helperView.setUint8(pos++, value >> 16);
3320 this.helperView.setUint8(pos++, value >> 8);
3321 this.helperView.setUint8(pos++, value);
3322 break;
3323 case 6:
3324 this.helperView.setUint8(pos++, 1 << 2 | value / 2 ** 40 & 3);
3325 this.helperView.setUint8(pos++, value / 2 ** 32 | 0);
3326 this.helperView.setUint8(pos++, value >> 24);
3327 this.helperView.setUint8(pos++, value >> 16);
3328 this.helperView.setUint8(pos++, value >> 8);
3329 this.helperView.setUint8(pos++, value);
3330 break;
3331 default:
3332 throw new Error("Bad EBML varint size " + width);
3333 }
3334 this.writer.write(this.helper.subarray(0, pos));
3335 }
3336 writeAsciiString(str) {
3337 this.writer.write(new Uint8Array(str.split("").map((x) => x.charCodeAt(0))));
3338 }
3339 writeEBML(data) {
3340 if (data === null)
3341 return;
3342 if (data instanceof Uint8Array) {
3343 this.writer.write(data);
3344 } else if (Array.isArray(data)) {
3345 for (const elem of data) {
3346 this.writeEBML(elem);
3347 }
3348 } else {
3349 this.offsets.set(data, this.writer.getPos());
3350 this.writeUnsignedInt(data.id);
3351 if (Array.isArray(data.data)) {
3352 const sizePos = this.writer.getPos();
3353 const sizeSize = data.size === -1 ? 1 : data.size ?? 4;
3354 if (data.size === -1) {
3355 this.writeByte(255);
3356 } else {
3357 this.writer.seek(this.writer.getPos() + sizeSize);
3358 }
3359 const startPos = this.writer.getPos();
3360 this.dataOffsets.set(data, startPos);
3361 this.writeEBML(data.data);
3362 if (data.size !== -1) {
3363 const size = this.writer.getPos() - startPos;
3364 const endPos = this.writer.getPos();
3365 this.writer.seek(sizePos);
3366 this.writeVarInt(size, sizeSize);
3367 this.writer.seek(endPos);
3368 }
3369 } else if (typeof data.data === "number") {
3370 const size = data.size ?? measureUnsignedInt(data.data);
3371 this.writeVarInt(size);
3372 this.writeUnsignedInt(data.data, size);
3373 } else if (typeof data.data === "bigint") {
3374 const size = data.size ?? measureUnsignedBigInt(data.data);
3375 this.writeVarInt(size);
3376 this.writeUnsignedBigInt(data.data, size);
3377 } else if (typeof data.data === "string") {
3378 this.writeVarInt(data.data.length);
3379 this.writeAsciiString(data.data);
3380 } else if (data.data instanceof Uint8Array) {
3381 this.writeVarInt(data.data.byteLength, data.size);
3382 this.writer.write(data.data);
3383 } else if (data.data instanceof EBMLFloat32) {
3384 this.writeVarInt(4);
3385 this.writeFloat32(data.data.value);
3386 } else if (data.data instanceof EBMLFloat64) {
3387 this.writeVarInt(8);
3388 this.writeFloat64(data.data.value);
3389 } else if (data.data instanceof EBMLSignedInt) {
3390 const size = data.size ?? measureSignedInt(data.data.value);
3391 this.writeVarInt(size);
3392 this.writeSignedInt(data.data.value, size);
3393 } else if (data.data instanceof EBMLUnicodeString) {
3394 const bytes2 = textEncoder.encode(data.data.value);
3395 this.writeVarInt(bytes2.length);
3396 this.writer.write(bytes2);
3397 } else {
3398 assertNever(data.data);
3399 }
3400 }
3401 }
3402 };
3403 var MAX_VAR_INT_SIZE = 8;
3404 var MAX_HEADER_SIZE = 2 * MAX_VAR_INT_SIZE;
3405 var CODEC_STRING_MAP = {
3406 "avc": "V_MPEG4/ISO/AVC",
3407 "hevc": "V_MPEGH/ISO/HEVC",
3408 "vp8": "V_VP8",
3409 "vp9": "V_VP9",
3410 "av1": "V_AV1",
3411 "aac": "A_AAC",
3412 "mp3": "A_MPEG/L3",
3413 "opus": "A_OPUS",
3414 "vorbis": "A_VORBIS",
3415 "flac": "A_FLAC",
3416 "ac3": "A_AC3",
3417 "eac3": "A_EAC3",
3418 "pcm-u8": "A_PCM/INT/LIT",
3419 "pcm-s16": "A_PCM/INT/LIT",
3420 "pcm-s16be": "A_PCM/INT/BIG",
3421 "pcm-s24": "A_PCM/INT/LIT",
3422 "pcm-s24be": "A_PCM/INT/BIG",
3423 "pcm-s32": "A_PCM/INT/LIT",
3424 "pcm-s32be": "A_PCM/INT/BIG",
3425 "pcm-f32": "A_PCM/FLOAT/IEEE",
3426 "pcm-f64": "A_PCM/FLOAT/IEEE",
3427 "webvtt": "S_TEXT/WEBVTT"
3428 };
3429
3430 // node_modules/mediabunny/dist/modules/src/matroska/matroska-misc.js
3431 var buildMatroskaMimeType = (info) => {
3432 const base = info.hasVideo ? "video/" : info.hasAudio ? "audio/" : "application/";
3433 let string = base + (info.isWebM ? "webm" : "x-matroska");
3434 if (info.codecStrings.length > 0) {
3435 const uniqueCodecMimeTypes = [...new Set(info.codecStrings.filter(Boolean))];
3436 string += \`; codecs="\${uniqueCodecMimeTypes.join(", ")}"\`;
3437 }
3438 return string;
3439 };
3440
3441 // node_modules/mediabunny/dist/modules/src/adts/adts-reader.js
3442 var MIN_ADTS_FRAME_HEADER_SIZE = 7;
3443 var MAX_ADTS_FRAME_HEADER_SIZE = 9;
3444 var readAdtsFrameHeader = (slice) => {
3445 const startPos = slice.filePos;
3446 const bytes2 = readBytes(slice, 9);
3447 const bitstream = new Bitstream(bytes2);
3448 const syncword = bitstream.readBits(12);
3449 if (syncword !== 4095) {
3450 return null;
3451 }
3452 bitstream.skipBits(1);
3453 const layer = bitstream.readBits(2);
3454 if (layer !== 0) {
3455 return null;
3456 }
3457 const protectionAbsence = bitstream.readBits(1);
3458 const objectType = bitstream.readBits(2) + 1;
3459 const samplingFrequencyIndex = bitstream.readBits(4);
3460 if (samplingFrequencyIndex === 15) {
3461 return null;
3462 }
3463 bitstream.skipBits(1);
3464 const channelConfiguration = bitstream.readBits(3);
3465 if (channelConfiguration === 0) {
3466 throw new Error("ADTS frames with channel configuration 0 are not supported.");
3467 }
3468 bitstream.skipBits(1);
3469 bitstream.skipBits(1);
3470 bitstream.skipBits(1);
3471 bitstream.skipBits(1);
3472 const frameLength = bitstream.readBits(13);
3473 bitstream.skipBits(11);
3474 const numberOfAacFrames = bitstream.readBits(2) + 1;
3475 if (numberOfAacFrames !== 1) {
3476 throw new Error("ADTS frames with more than one AAC frame are not supported.");
3477 }
3478 let crcCheck = null;
3479 if (protectionAbsence === 1) {
3480 slice.filePos -= 2;
3481 } else {
3482 crcCheck = bitstream.readBits(16);
3483 }
3484 return {
3485 objectType,
3486 samplingFrequencyIndex,
3487 channelConfiguration,
3488 frameLength,
3489 numberOfAacFrames,
3490 crcCheck,
3491 startPos
3492 };
3493 };
3494
3495 // node_modules/mediabunny/dist/modules/src/sample.js
3496 var __addDisposableResource = function(env, value, async) {
3497 if (value !== null && value !== void 0) {
3498 if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
3499 var dispose, inner;
3500 if (async) {
3501 if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
3502 dispose = value[Symbol.asyncDispose];
3503 }
3504 if (dispose === void 0) {
3505 if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
3506 dispose = value[Symbol.dispose];
3507 if (async) inner = dispose;
3508 }
3509 if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
3510 if (inner) dispose = function() {
3511 try {
3512 inner.call(this);
3513 } catch (e2) {
3514 return Promise.reject(e2);
3515 }
3516 };
3517 env.stack.push({ value, dispose, async });
3518 } else if (async) {
3519 env.stack.push({ async: true });
3520 }
3521 return value;
3522 };
3523 var __disposeResources = /* @__PURE__ */ (function(SuppressedError2) {
3524 return function(env) {
3525 function fail(e2) {
3526 env.error = env.hasError ? new SuppressedError2(e2, env.error, "An error was suppressed during disposal.") : e2;
3527 env.hasError = true;
3528 }
3529 var r2, s2 = 0;
3530 function next() {
3531 while (r2 = env.stack.pop()) {
3532 try {
3533 if (!r2.async && s2 === 1) return s2 = 0, env.stack.push(r2), Promise.resolve().then(next);
3534 if (r2.dispose) {
3535 var result = r2.dispose.call(r2.value);
3536 if (r2.async) return s2 |= 2, Promise.resolve(result).then(next, function(e2) {
3537 fail(e2);
3538 return next();
3539 });
3540 } else s2 |= 1;
3541 } catch (e2) {
3542 fail(e2);
3543 }
3544 }
3545 if (s2 === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
3546 if (env.hasError) throw env.error;
3547 }
3548 return next();
3549 };
3550 })(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
3551 var e2 = new Error(message);
3552 return e2.name = "SuppressedError", e2.error = error, e2.suppressed = suppressed, e2;
3553 });
3554 polyfillSymbolDispose();
3555 var lastVideoGcErrorLog = -Infinity;
3556 var lastAudioGcErrorLog = -Infinity;
3557 var finalizationRegistry = null;
3558 if (typeof FinalizationRegistry !== "undefined") {
3559 finalizationRegistry = new FinalizationRegistry((value) => {
3560 const now = performance.now();
3561 if (value.type === "video") {
3562 if (now - lastVideoGcErrorLog >= 1e3) {
3563 Logging._error(\`A VideoSample was garbage collected without first being closed. For proper resource management, make sure to call close() on all your VideoSamples as soon as you're done using them.\`);
3564 lastVideoGcErrorLog = now;
3565 }
3566 if (typeof VideoFrame !== "undefined" && value.data instanceof VideoFrame) {
3567 value.data.close();
3568 }
3569 } else {
3570 if (now - lastAudioGcErrorLog >= 1e3) {
3571 Logging._error(\`An AudioSample was garbage collected without first being closed. For proper resource management, make sure to call close() on all your AudioSamples as soon as you're done using them.\`);
3572 lastAudioGcErrorLog = now;
3573 }
3574 if (typeof AudioData !== "undefined" && value.data instanceof AudioData) {
3575 value.data.close();
3576 }
3577 }
3578 });
3579 }
3580 var VideoSampleResource = class {
3581 constructor() {
3582 this._referenceCount = 0;
3583 this._lastAllocationBuffer = null;
3584 }
3585 };
3586 var VIDEO_SAMPLE_PIXEL_FORMATS = [
3587 // 4:2:0 Y, U, V
3588 "I420",
3589 "I420P10",
3590 "I420P12",
3591 // 4:2:0 Y, U, V, A
3592 "I420A",
3593 "I420AP10",
3594 "I420AP12",
3595 // 4:2:2 Y, U, V
3596 "I422",
3597 "I422P10",
3598 "I422P12",
3599 // 4:2:2 Y, U, V, A
3600 "I422A",
3601 "I422AP10",
3602 "I422AP12",
3603 // 4:4:4 Y, U, V
3604 "I444",
3605 "I444P10",
3606 "I444P12",
3607 // 4:4:4 Y, U, V, A
3608 "I444A",
3609 "I444AP10",
3610 "I444AP12",
3611 // 4:2:0 Y, UV
3612 "NV12",
3613 // 4:4:4 RGBA
3614 "RGBA",
3615 // 4:4:4 RGBX (opaque)
3616 "RGBX",
3617 // 4:4:4 BGRA
3618 "BGRA",
3619 // 4:4:4 BGRX (opaque)
3620 "BGRX"
3621 ];
3622 var VIDEO_SAMPLE_PIXEL_FORMATS_SET = new Set(VIDEO_SAMPLE_PIXEL_FORMATS);
3623 var VideoSample = class _VideoSample {
3624 /** The width of the frame in pixels. */
3625 get codedWidth() {
3626 return this.visibleRect.width;
3627 }
3628 /** The height of the frame in pixels. */
3629 get codedHeight() {
3630 return this.visibleRect.height;
3631 }
3632 /** The display width of the frame in pixels, after aspect ratio adjustment and rotation. */
3633 get displayWidth() {
3634 return this.rotation % 180 === 0 ? this.squarePixelWidth : this.squarePixelHeight;
3635 }
3636 /** The display height of the frame in pixels, after aspect ratio adjustment and rotation. */
3637 get displayHeight() {
3638 return this.rotation % 180 === 0 ? this.squarePixelHeight : this.squarePixelWidth;
3639 }
3640 /** The presentation timestamp of the frame in microseconds. */
3641 get microsecondTimestamp() {
3642 return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.timestamp);
3643 }
3644 /** The duration of the frame in microseconds. */
3645 get microsecondDuration() {
3646 return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.duration);
3647 }
3648 /**
3649 * Whether this sample uses a pixel format that can hold transparency data. Note that this doesn't necessarily mean
3650 * that the sample is transparent.
3651 */
3652 get hasAlpha() {
3653 return this.format && this.format.includes("A");
3654 }
3655 constructor(data, init) {
3656 this._closed = false;
3657 if (data instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && data instanceof SharedArrayBuffer || ArrayBuffer.isView(data)) {
3658 if (!init || typeof init !== "object") {
3659 throw new TypeError("init must be an object.");
3660 }
3661 if (init.format === void 0 || !VIDEO_SAMPLE_PIXEL_FORMATS_SET.has(init.format)) {
3662 throw new TypeError("init.format must be one of: " + VIDEO_SAMPLE_PIXEL_FORMATS.join(", "));
3663 }
3664 if (!Number.isInteger(init.codedWidth) || init.codedWidth <= 0) {
3665 throw new TypeError("init.codedWidth must be a positive integer.");
3666 }
3667 if (!Number.isInteger(init.codedHeight) || init.codedHeight <= 0) {
3668 throw new TypeError("init.codedHeight must be a positive integer.");
3669 }
3670 if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
3671 throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
3672 }
3673 if (!Number.isFinite(init.timestamp)) {
3674 throw new TypeError("init.timestamp must be a number.");
3675 }
3676 if (init.duration !== void 0 && (!Number.isFinite(init.duration) || init.duration < 0)) {
3677 throw new TypeError("init.duration, when provided, must be a non-negative number.");
3678 }
3679 if (init.layout !== void 0) {
3680 if (!Array.isArray(init.layout)) {
3681 throw new TypeError("init.layout, when provided, must be an array.");
3682 }
3683 for (const plane of init.layout) {
3684 if (!plane || typeof plane !== "object" || Array.isArray(plane)) {
3685 throw new TypeError("Each entry in init.layout must be an object.");
3686 }
3687 if (!Number.isInteger(plane.offset) || plane.offset < 0) {
3688 throw new TypeError("plane.offset must be a non-negative integer.");
3689 }
3690 if (!Number.isInteger(plane.stride) || plane.stride < 0) {
3691 throw new TypeError("plane.stride must be a non-negative integer.");
3692 }
3693 }
3694 }
3695 if (init.visibleRect !== void 0) {
3696 validateRectangle(init.visibleRect, "init.visibleRect");
3697 }
3698 if (init.displayWidth !== void 0 && (!Number.isInteger(init.displayWidth) || init.displayWidth <= 0)) {
3699 throw new TypeError("init.displayWidth, when provided, must be a positive integer.");
3700 }
3701 if (init.displayHeight !== void 0 && (!Number.isInteger(init.displayHeight) || init.displayHeight <= 0)) {
3702 throw new TypeError("init.displayHeight, when provided, must be a positive integer.");
3703 }
3704 if (init.displayWidth !== void 0 !== (init.displayHeight !== void 0)) {
3705 throw new TypeError("init.displayWidth and init.displayHeight must be either both provided or both omitted.");
3706 }
3707 this._data = init._doNotCopy ? toUint8Array(data) : toUint8Array(data).slice();
3708 this._layout = init.layout ?? createDefaultPlaneLayout(init.format, init.codedWidth, init.codedHeight);
3709 this.format = init.format;
3710 this.rotation = init.rotation ?? 0;
3711 this.timestamp = init.timestamp;
3712 this.duration = init.duration ?? 0;
3713 let colorSpaceInit = init.colorSpace ?? null;
3714 if (colorSpaceInit === null) {
3715 if (this.format === "RGBA" || this.format === "RGBX" || this.format === "BGRA" || this.format === "BGRX") {
3716 colorSpaceInit = {
3717 primaries: "bt709",
3718 transfer: "iec61966-2-1",
3719 matrix: "rgb",
3720 fullRange: true
3721 };
3722 } else {
3723 colorSpaceInit = {
3724 primaries: "bt709",
3725 transfer: "bt709",
3726 matrix: "bt709",
3727 fullRange: false
3728 };
3729 }
3730 }
3731 this.colorSpace = new VideoSampleColorSpace(colorSpaceInit);
3732 this.visibleRect = {
3733 left: init.visibleRect?.left ?? 0,
3734 top: init.visibleRect?.top ?? 0,
3735 width: init.visibleRect?.width ?? init.codedWidth,
3736 height: init.visibleRect?.height ?? init.codedHeight
3737 };
3738 if (init.displayWidth !== void 0) {
3739 this.squarePixelWidth = this.rotation % 180 === 0 ? init.displayWidth : init.displayHeight;
3740 this.squarePixelHeight = this.rotation % 180 === 0 ? init.displayHeight : init.displayWidth;
3741 } else {
3742 this.squarePixelWidth = this.visibleRect.width;
3743 this.squarePixelHeight = this.visibleRect.height;
3744 }
3745 } else if (typeof VideoFrame !== "undefined" && data instanceof VideoFrame) {
3746 if (init?.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
3747 throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
3748 }
3749 if (init?.timestamp !== void 0 && !Number.isFinite(init?.timestamp)) {
3750 throw new TypeError("init.timestamp, when provided, must be a number.");
3751 }
3752 if (init?.duration !== void 0 && (!Number.isFinite(init.duration) || init.duration < 0)) {
3753 throw new TypeError("init.duration, when provided, must be a non-negative number.");
3754 }
3755 if (init?.visibleRect !== void 0) {
3756 validateRectangle(init.visibleRect, "init.visibleRect");
3757 }
3758 this._data = data;
3759 this._layout = null;
3760 this.format = data.format;
3761 this.visibleRect = {
3762 left: data.visibleRect?.x ?? 0,
3763 top: data.visibleRect?.y ?? 0,
3764 width: data.visibleRect?.width ?? data.codedWidth,
3765 height: data.visibleRect?.height ?? data.codedHeight
3766 };
3767 this.rotation = init?.rotation ?? 0;
3768 this.squarePixelWidth = data.displayWidth;
3769 this.squarePixelHeight = data.displayHeight;
3770 this.timestamp = init?.timestamp ?? data.timestamp / 1e6;
3771 this.duration = init?.duration ?? (data.duration ?? 0) / 1e6;
3772 this.colorSpace = new VideoSampleColorSpace(data.colorSpace);
3773 } else if (typeof HTMLImageElement !== "undefined" && data instanceof HTMLImageElement || typeof SVGImageElement !== "undefined" && data instanceof SVGImageElement || typeof ImageBitmap !== "undefined" && data instanceof ImageBitmap || typeof HTMLVideoElement !== "undefined" && data instanceof HTMLVideoElement || typeof HTMLCanvasElement !== "undefined" && data instanceof HTMLCanvasElement || typeof OffscreenCanvas !== "undefined" && data instanceof OffscreenCanvas) {
3774 if (!init || typeof init !== "object") {
3775 throw new TypeError("init must be an object.");
3776 }
3777 if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
3778 throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
3779 }
3780 if (!Number.isFinite(init.timestamp)) {
3781 throw new TypeError("init.timestamp must be a number.");
3782 }
3783 if (init.duration !== void 0 && (!Number.isFinite(init.duration) || init.duration < 0)) {
3784 throw new TypeError("init.duration, when provided, must be a non-negative number.");
3785 }
3786 if (typeof VideoFrame !== "undefined") {
3787 return new _VideoSample(new VideoFrame(data, {
3788 timestamp: Math.trunc(init.timestamp * SECOND_TO_MICROSECOND_FACTOR),
3789 // Drag 0 to undefined
3790 duration: Math.trunc((init.duration ?? 0) * SECOND_TO_MICROSECOND_FACTOR) || void 0
3791 }), init);
3792 }
3793 let width = 0;
3794 let height = 0;
3795 if ("naturalWidth" in data) {
3796 width = data.naturalWidth;
3797 height = data.naturalHeight;
3798 } else if ("videoWidth" in data) {
3799 width = data.videoWidth;
3800 height = data.videoHeight;
3801 } else if ("width" in data) {
3802 width = Number(data.width);
3803 height = Number(data.height);
3804 }
3805 if (!width || !height) {
3806 throw new TypeError("Could not determine dimensions.");
3807 }
3808 const canvas = new OffscreenCanvas(width, height);
3809 const context = canvas.getContext("2d", {
3810 alpha: isFirefox(),
3811 // Firefox has VideoFrame glitches with opaque canvases
3812 willReadFrequently: true
3813 });
3814 if (!context) {
3815 throw new Error("OffscreenCanvas must have support for the '2d' context in order to create a VideoSample from this data.");
3816 }
3817 context.drawImage(data, 0, 0);
3818 this._data = canvas;
3819 this._layout = null;
3820 this.format = "RGBX";
3821 this.visibleRect = { left: 0, top: 0, width, height };
3822 this.squarePixelWidth = width;
3823 this.squarePixelHeight = height;
3824 this.rotation = init.rotation ?? 0;
3825 this.timestamp = init.timestamp;
3826 this.duration = init.duration ?? 0;
3827 this.colorSpace = new VideoSampleColorSpace({
3828 matrix: "rgb",
3829 primaries: "bt709",
3830 transfer: "iec61966-2-1",
3831 fullRange: true
3832 });
3833 } else if (data instanceof VideoSampleResource) {
3834 if (!init || typeof init !== "object") {
3835 throw new TypeError("init must be an object.");
3836 }
3837 if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
3838 throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
3839 }
3840 if (!Number.isFinite(init.timestamp)) {
3841 throw new TypeError("init.timestamp must be a number.");
3842 }
3843 if (init.duration !== void 0 && (!Number.isFinite(init.duration) || init.duration < 0)) {
3844 throw new TypeError("init.duration, when provided, must be a non-negative number.");
3845 }
3846 this._data = data;
3847 data._referenceCount++;
3848 this.format = data.getFormat();
3849 if (this.format !== null && !VIDEO_SAMPLE_PIXEL_FORMATS.includes(this.format)) {
3850 throw new TypeError("getFormat() must return a VideoSamplePixelFormat or null.");
3851 }
3852 this.visibleRect = {
3853 left: 0,
3854 top: 0,
3855 width: data.getCodedWidth(),
3856 height: data.getCodedHeight()
3857 };
3858 if (!Number.isInteger(this.visibleRect.width) || this.visibleRect.width <= 0) {
3859 throw new TypeError("getCodedWidth() must return a positive integer.");
3860 }
3861 if (!Number.isInteger(this.visibleRect.height) || this.visibleRect.height <= 0) {
3862 throw new TypeError("getCodedHeight() must return a positive integer.");
3863 }
3864 this.squarePixelWidth = data.getSquarePixelWidth();
3865 if (!Number.isInteger(this.squarePixelWidth) || this.squarePixelWidth <= 0) {
3866 throw new TypeError("getSquarePixelWidth() must return a positive integer.");
3867 }
3868 this.squarePixelHeight = data.getSquarePixelHeight();
3869 if (!Number.isInteger(this.squarePixelHeight) || this.squarePixelHeight <= 0) {
3870 throw new TypeError("getSquarePixelHeight() must return a positive integer.");
3871 }
3872 this.rotation = init.rotation ?? 0;
3873 this.timestamp = init.timestamp;
3874 this.duration = init.duration ?? 0;
3875 this.colorSpace = data.getColorSpace();
3876 } else {
3877 throw new TypeError("Invalid data type: Must be a BufferSource, CanvasImageSource, or VideoSampleResource.");
3878 }
3879 this.encodeOptions = init?.encodeOptions ?? {};
3880 this.pixelAspectRatio = simplifyRational({
3881 num: this.squarePixelWidth * this.codedHeight,
3882 den: this.squarePixelHeight * this.codedWidth
3883 });
3884 finalizationRegistry?.register(this, { type: "video", data: this._data }, this);
3885 }
3886 /** Clones this video sample. */
3887 clone() {
3888 if (this._closed) {
3889 throw new Error("VideoSample is closed.");
3890 }
3891 assert(this._data !== null);
3892 if (this._data instanceof VideoSampleResource) {
3893 return new _VideoSample(this._data, {
3894 timestamp: this.timestamp,
3895 duration: this.duration,
3896 rotation: this.rotation,
3897 encodeOptions: this.encodeOptions
3898 });
3899 } else if (isVideoFrame(this._data)) {
3900 return new _VideoSample(this._data.clone(), {
3901 timestamp: this.timestamp,
3902 duration: this.duration,
3903 rotation: this.rotation,
3904 encodeOptions: this.encodeOptions
3905 });
3906 } else if (this._data instanceof Uint8Array) {
3907 assert(this._layout);
3908 return new _VideoSample(this._data, {
3909 format: this.format,
3910 layout: this._layout,
3911 codedWidth: this.codedWidth,
3912 codedHeight: this.codedHeight,
3913 timestamp: this.timestamp,
3914 duration: this.duration,
3915 colorSpace: this.colorSpace,
3916 rotation: this.rotation,
3917 visibleRect: this.visibleRect,
3918 displayWidth: this.displayWidth,
3919 displayHeight: this.displayHeight,
3920 encodeOptions: this.encodeOptions,
3921 // It's already been copied, if we copy it again we make the clone unnecessarily expensive
3922 _doNotCopy: true
3923 });
3924 } else {
3925 return new _VideoSample(this._data, {
3926 format: this.format,
3927 codedWidth: this.codedWidth,
3928 codedHeight: this.codedHeight,
3929 timestamp: this.timestamp,
3930 duration: this.duration,
3931 colorSpace: this.colorSpace,
3932 rotation: this.rotation,
3933 visibleRect: this.visibleRect,
3934 displayWidth: this.displayWidth,
3935 displayHeight: this.displayHeight,
3936 encodeOptions: this.encodeOptions
3937 });
3938 }
3939 }
3940 /**
3941 * Closes this video sample, releasing held resources. Video samples should be closed as soon as they are not
3942 * needed anymore.
3943 */
3944 close() {
3945 if (this._closed) {
3946 return;
3947 }
3948 finalizationRegistry?.unregister(this);
3949 if (this._data instanceof VideoSampleResource) {
3950 this._data._referenceCount--;
3951 if (this._data._referenceCount === 0) {
3952 this._data.close();
3953 }
3954 } else if (isVideoFrame(this._data)) {
3955 this._data.close();
3956 } else {
3957 this._data = null;
3958 }
3959 this._closed = true;
3960 }
3961 /**
3962 * Returns the number of bytes required to hold this video sample's pixel data.
3963 */
3964 allocationSize(options = {}) {
3965 validateVideoFrameCopyToOptions(options);
3966 if (this._closed) {
3967 throw new Error("VideoSample is closed.");
3968 }
3969 if ((options.format ?? this.format) == null) {
3970 throw new Error("Cannot get allocation size when format is null.");
3971 }
3972 if (isVideoFrame(this._data)) {
3973 return this._data.allocationSize(options);
3974 }
3975 const combinedLayout = ParseVideoFrameCopyToOptions(this, options);
3976 return combinedLayout.allocationSize;
3977 }
3978 /**
3979 * Copies this video sample's pixel data to an ArrayBuffer or ArrayBufferView.
3980 * @returns The byte layout of the planes of the copied data.
3981 */
3982 async copyTo(destination, options = {}) {
3983 if (!isAllowSharedBufferSource(destination)) {
3984 throw new TypeError("destination must be an ArrayBuffer or an ArrayBuffer view.");
3985 }
3986 validateVideoFrameCopyToOptions(options);
3987 if (this._closed) {
3988 throw new Error("VideoSample is closed.");
3989 }
3990 if ((options.format ?? this.format) == null) {
3991 throw new Error("Cannot copy video sample data when format is null.");
3992 }
3993 assert(this._data !== null);
3994 if (isVideoFrame(this._data)) {
3995 return this._data.copyTo(destination, options);
3996 }
3997 if (options.format && !["RGBA", "RGBX", "BGRA", "BGRX"].includes(this.format) && ["RGBA", "RGBX", "BGRA", "BGRX"].includes(options.format)) {
3998 if (this._data instanceof VideoSampleResource) {
3999 const env_1 = { stack: [], error: void 0, hasError: false };
4000 try {
4001 const rgbSample = __addDisposableResource(env_1, await this._data.toRgbSample({
4002 timestamp: this.timestamp,
4003 duration: this.duration,
4004 rotation: this.rotation
4005 }, options.colorSpace ?? "srgb"), false);
4006 if (!(rgbSample instanceof _VideoSample)) {
4007 throw new TypeError("toRgbSample() must return a VideoSample.");
4008 }
4009 if (!["RGBA", "RGBX", "BGRA", "BGRX"].includes(rgbSample.format)) {
4010 throw new Error(\`Sample returned by toRgbSample was expected to have an RGB format, got '\${rgbSample.format}' instead.\`);
4011 }
4012 return await rgbSample.copyTo(destination, options);
4013 } catch (e_1) {
4014 env_1.error = e_1;
4015 env_1.hasError = true;
4016 } finally {
4017 __disposeResources(env_1);
4018 }
4019 } else {
4020 if (typeof VideoFrame === "undefined") {
4021 throw new Error("For this sample, converting from a non-RGB to an RGB format requires VideoFrame to be defined.");
4022 }
4023 const tempFrame = this.toVideoFrame();
4024 const result = await tempFrame.copyTo(destination, options);
4025 tempFrame.close();
4026 return result;
4027 }
4028 }
4029 const combinedLayout = ParseVideoFrameCopyToOptions(this, options);
4030 assert(this.format);
4031 const destBytes = toUint8Array(destination);
4032 if (destBytes.byteLength < combinedLayout.allocationSize) {
4033 throw new TypeError(\`Destination buffer too small. Required: \${combinedLayout.allocationSize}, Available: \${destBytes.byteLength}\`);
4034 }
4035 const planeConfigs = getPlaneConfigs(this.format);
4036 let dataPlanes;
4037 if (this._data instanceof VideoSampleResource) {
4038 let result = this._data.getDataPlanes();
4039 if (result instanceof Promise)
4040 result = await result;
4041 if (!Array.isArray(result) || result.some((x) => !(x.data instanceof Uint8Array) || !Number.isInteger(x.stride) || x.stride < 0)) {
4042 throw new TypeError('getDataPlanes() must return an array of objects with a Uint8Array "data" property and a non-negative integer "stride" property.');
4043 }
4044 dataPlanes = result;
4045 } else if (this._data instanceof Uint8Array) {
4046 assert(this._layout);
4047 assert(this._layout.length === planeConfigs.length);
4048 dataPlanes = this._layout.map((planeLayout, i2) => {
4049 const height = Math.ceil(this.codedHeight / planeConfigs[i2].heightDivisor);
4050 return {
4051 data: this._data.subarray(planeLayout.offset, planeLayout.offset + planeLayout.stride * height),
4052 stride: planeLayout.stride
4053 };
4054 });
4055 } else {
4056 const canvas = this._data;
4057 const context = canvas.getContext("2d");
4058 assert(context);
4059 const imageData = context.getImageData(0, 0, this.codedWidth, this.codedHeight);
4060 dataPlanes = [{
4061 data: toUint8Array(imageData.data),
4062 stride: 4 * this.codedWidth
4063 }];
4064 }
4065 const planeLayouts = [];
4066 const numPlanes = planeConfigs.length;
4067 for (let planeIndex = 0; planeIndex < numPlanes; planeIndex++) {
4068 const computedLayout = combinedLayout.computedLayouts[planeIndex];
4069 const sourceStride = dataPlanes[planeIndex].stride;
4070 const sourceData = dataPlanes[planeIndex].data;
4071 let sourceOffset = computedLayout.sourceTop * sourceStride;
4072 sourceOffset += computedLayout.sourceLeftBytes;
4073 let destinationOffset = computedLayout.destinationOffset;
4074 const rowBytes = computedLayout.sourceWidthBytes;
4075 const layout = {
4076 offset: destinationOffset,
4077 stride: computedLayout.destinationStride
4078 };
4079 for (let row = 0; row < computedLayout.sourceHeight; row++) {
4080 if (sourceOffset + rowBytes > sourceData.byteLength) {
4081 throw new Error(\`Source buffer OOB read.\`);
4082 }
4083 if (destinationOffset + rowBytes > destBytes.byteLength) {
4084 throw new Error(\`Destination buffer OOB write.\`);
4085 }
4086 const srcSub = sourceData.subarray(sourceOffset, sourceOffset + rowBytes);
4087 destBytes.set(srcSub, destinationOffset);
4088 sourceOffset += sourceStride;
4089 destinationOffset += computedLayout.destinationStride;
4090 }
4091 planeLayouts.push(layout);
4092 }
4093 if (options.format !== void 0) {
4094 const needsRgbConversion = this.format.startsWith("RGB") !== options.format.startsWith("RGB");
4095 const needsAlphaConversion = this.format.includes("X") && options.format.includes("A");
4096 if (needsRgbConversion || needsAlphaConversion) {
4097 for (let i2 = 0; i2 < combinedLayout.allocationSize; i2 += 4) {
4098 if (needsRgbConversion) {
4099 const r2 = destBytes[i2];
4100 const b = destBytes[i2 + 2];
4101 destBytes[i2] = b;
4102 destBytes[i2 + 2] = r2;
4103 }
4104 if (needsAlphaConversion) {
4105 destBytes[i2 + 3] = 255;
4106 }
4107 }
4108 }
4109 }
4110 return planeLayouts;
4111 }
4112 /**
4113 * Converts this video sample to a VideoFrame for use with the WebCodecs API. The VideoFrame returned by this
4114 * method *must* be closed separately from this video sample.
4115 */
4116 toVideoFrame() {
4117 if (this._closed) {
4118 throw new Error("VideoSample is closed.");
4119 }
4120 assert(this._data !== null);
4121 if (this._data instanceof VideoSampleResource) {
4122 if (this.format === null) {
4123 throw new Error("Cannot convert a VideoSampleResource-backed VideoSample to VideoFrame if format is null.");
4124 }
4125 const planes = this._data.getDataPlanes();
4126 if (planes instanceof Promise) {
4127 throw new Error("Cannot convert a VideoSampleResource-backed VideoSample to VideoFrame if getDataPlanes() returns a promise.");
4128 }
4129 const size = planes.reduce((a2, b) => a2 + b.data.byteLength, 0);
4130 const buffer = new Uint8Array(size);
4131 let offset = 0;
4132 const offsets = [];
4133 for (const plane of planes) {
4134 buffer.set(plane.data, offset);
4135 offsets.push(offset);
4136 offset += plane.data.byteLength;
4137 }
4138 return new VideoFrame(buffer, {
4139 format: this.format,
4140 layout: planes.map((x, i2) => ({
4141 offset: offsets[i2],
4142 stride: x.stride
4143 })),
4144 codedWidth: this.codedWidth,
4145 codedHeight: this.codedHeight,
4146 timestamp: this.microsecondTimestamp,
4147 duration: this.microsecondDuration,
4148 colorSpace: this.colorSpace,
4149 displayWidth: this.squarePixelWidth,
4150 // Not display* since we're not passing rotation
4151 displayHeight: this.squarePixelHeight
4152 });
4153 } else if (isVideoFrame(this._data)) {
4154 return new VideoFrame(this._data, {
4155 timestamp: this.microsecondTimestamp,
4156 duration: this.microsecondDuration || void 0
4157 // Drag 0 duration to undefined, glitches some codecs
4158 });
4159 } else if (this._data instanceof Uint8Array) {
4160 return new VideoFrame(this._data, {
4161 format: this.format,
4162 codedWidth: this.codedWidth,
4163 codedHeight: this.codedHeight,
4164 timestamp: this.microsecondTimestamp,
4165 duration: this.microsecondDuration || void 0,
4166 colorSpace: this.colorSpace,
4167 displayWidth: this.squarePixelWidth,
4168 // Not display* since we're not passing rotation
4169 displayHeight: this.squarePixelHeight
4170 });
4171 } else {
4172 return new VideoFrame(this._data, {
4173 timestamp: this.microsecondTimestamp,
4174 duration: this.microsecondDuration || void 0
4175 });
4176 }
4177 }
4178 draw(context, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) {
4179 let sx = 0;
4180 let sy = 0;
4181 let sWidth = this.displayWidth;
4182 let sHeight = this.displayHeight;
4183 let dx = 0;
4184 let dy = 0;
4185 let dWidth = this.displayWidth;
4186 let dHeight = this.displayHeight;
4187 if (arg5 !== void 0) {
4188 sx = arg1;
4189 sy = arg2;
4190 sWidth = arg3;
4191 sHeight = arg4;
4192 dx = arg5;
4193 dy = arg6;
4194 if (arg7 !== void 0) {
4195 dWidth = arg7;
4196 dHeight = arg8;
4197 } else {
4198 dWidth = sWidth;
4199 dHeight = sHeight;
4200 }
4201 } else {
4202 dx = arg1;
4203 dy = arg2;
4204 if (arg3 !== void 0) {
4205 dWidth = arg3;
4206 dHeight = arg4;
4207 }
4208 }
4209 if (!(typeof CanvasRenderingContext2D !== "undefined" && context instanceof CanvasRenderingContext2D || typeof OffscreenCanvasRenderingContext2D !== "undefined" && context instanceof OffscreenCanvasRenderingContext2D)) {
4210 throw new TypeError("context must be a CanvasRenderingContext2D or OffscreenCanvasRenderingContext2D.");
4211 }
4212 if (!Number.isFinite(sx)) {
4213 throw new TypeError("sx must be a number.");
4214 }
4215 if (!Number.isFinite(sy)) {
4216 throw new TypeError("sy must be a number.");
4217 }
4218 if (!Number.isFinite(sWidth) || sWidth < 0) {
4219 throw new TypeError("sWidth must be a non-negative number.");
4220 }
4221 if (!Number.isFinite(sHeight) || sHeight < 0) {
4222 throw new TypeError("sHeight must be a non-negative number.");
4223 }
4224 if (!Number.isFinite(dx)) {
4225 throw new TypeError("dx must be a number.");
4226 }
4227 if (!Number.isFinite(dy)) {
4228 throw new TypeError("dy must be a number.");
4229 }
4230 if (!Number.isFinite(dWidth) || dWidth < 0) {
4231 throw new TypeError("dWidth must be a non-negative number.");
4232 }
4233 if (!Number.isFinite(dHeight) || dHeight < 0) {
4234 throw new TypeError("dHeight must be a non-negative number.");
4235 }
4236 if (this._closed) {
4237 throw new Error("VideoSample is closed.");
4238 }
4239 ({ sx, sy, sWidth, sHeight } = this._rotateSourceRegion(sx, sy, sWidth, sHeight, this.rotation));
4240 const source = this.toCanvasImageSource();
4241 context.save();
4242 const centerX = dx + dWidth / 2;
4243 const centerY = dy + dHeight / 2;
4244 context.translate(centerX, centerY);
4245 context.rotate(this.rotation * Math.PI / 180);
4246 const aspectRatioChange = this.rotation % 180 === 0 ? 1 : dWidth / dHeight;
4247 context.scale(1 / aspectRatioChange, aspectRatioChange);
4248 context.drawImage(source, sx, sy, sWidth, sHeight, -dWidth / 2, -dHeight / 2, dWidth, dHeight);
4249 context.restore();
4250 }
4251 /**
4252 * Draws the sample in the middle of the canvas corresponding to the context with the specified fit behavior.
4253 */
4254 drawWithFit(context, options) {
4255 if (!(typeof CanvasRenderingContext2D !== "undefined" && context instanceof CanvasRenderingContext2D || typeof OffscreenCanvasRenderingContext2D !== "undefined" && context instanceof OffscreenCanvasRenderingContext2D)) {
4256 throw new TypeError("context must be a CanvasRenderingContext2D or OffscreenCanvasRenderingContext2D.");
4257 }
4258 if (!options || typeof options !== "object") {
4259 throw new TypeError("options must be an object.");
4260 }
4261 if (!["fill", "contain", "cover"].includes(options.fit)) {
4262 throw new TypeError("options.fit must be 'fill', 'contain', or 'cover'.");
4263 }
4264 if (options.rotation !== void 0 && ![0, 90, 180, 270].includes(options.rotation)) {
4265 throw new TypeError("options.rotation, when provided, must be 0, 90, 180, or 270.");
4266 }
4267 if (options.crop !== void 0) {
4268 validateCropRectangle(options.crop, "options.");
4269 }
4270 const canvasWidth = context.canvas.width;
4271 const canvasHeight = context.canvas.height;
4272 const rotation = options.rotation ?? this.rotation;
4273 const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [this.squarePixelWidth, this.squarePixelHeight] : [this.squarePixelHeight, this.squarePixelWidth];
4274 let finalCrop = options.crop;
4275 if (finalCrop) {
4276 finalCrop = clampCropRectangle(finalCrop, rotatedWidth, rotatedHeight);
4277 }
4278 let dx;
4279 let dy;
4280 let newWidth;
4281 let newHeight;
4282 const { sx, sy, sWidth, sHeight } = this._rotateSourceRegion(options.crop?.left ?? 0, options.crop?.top ?? 0, options.crop?.width ?? rotatedWidth, options.crop?.height ?? rotatedHeight, rotation);
4283 if (options.fit === "fill") {
4284 dx = 0;
4285 dy = 0;
4286 newWidth = canvasWidth;
4287 newHeight = canvasHeight;
4288 } else {
4289 const [sampleWidth, sampleHeight] = options.crop ? [options.crop.width, options.crop.height] : [rotatedWidth, rotatedHeight];
4290 const scale = options.fit === "contain" ? Math.min(canvasWidth / sampleWidth, canvasHeight / sampleHeight) : Math.max(canvasWidth / sampleWidth, canvasHeight / sampleHeight);
4291 newWidth = sampleWidth * scale;
4292 newHeight = sampleHeight * scale;
4293 dx = (canvasWidth - newWidth) / 2;
4294 dy = (canvasHeight - newHeight) / 2;
4295 }
4296 context.save();
4297 const aspectRatioChange = rotation % 180 === 0 ? 1 : newWidth / newHeight;
4298 context.translate(canvasWidth / 2, canvasHeight / 2);
4299 context.rotate(rotation * Math.PI / 180);
4300 context.scale(1 / aspectRatioChange, aspectRatioChange);
4301 context.translate(-canvasWidth / 2, -canvasHeight / 2);
4302 context.drawImage(this.toCanvasImageSource(), sx, sy, sWidth, sHeight, dx, dy, newWidth, newHeight);
4303 context.restore();
4304 }
4305 /** @internal */
4306 _rotateSourceRegion(sx, sy, sWidth, sHeight, rotation) {
4307 if (rotation === 90) {
4308 [sx, sy, sWidth, sHeight] = [
4309 sy,
4310 this.squarePixelHeight - sx - sWidth,
4311 sHeight,
4312 sWidth
4313 ];
4314 } else if (rotation === 180) {
4315 [sx, sy] = [
4316 this.squarePixelWidth - sx - sWidth,
4317 this.squarePixelHeight - sy - sHeight
4318 ];
4319 } else if (rotation === 270) {
4320 [sx, sy, sWidth, sHeight] = [
4321 this.squarePixelWidth - sy - sHeight,
4322 sx,
4323 sHeight,
4324 sWidth
4325 ];
4326 }
4327 return { sx, sy, sWidth, sHeight };
4328 }
4329 /**
4330 * Converts this video sample to a
4331 * [\`CanvasImageSource\`](https://udn.realityripple.com/docs/Web/API/CanvasImageSource) for drawing to a canvas.
4332 *
4333 * You must use the value returned by this method immediately, as any VideoFrame created internally may
4334 * automatically be closed in the next microtask.
4335 */
4336 toCanvasImageSource() {
4337 if (this._closed) {
4338 throw new Error("VideoSample is closed.");
4339 }
4340 assert(this._data !== null);
4341 if (this._data instanceof VideoSampleResource || this._data instanceof Uint8Array) {
4342 const videoFrame = this.toVideoFrame();
4343 queueMicrotask(() => videoFrame.close());
4344 return videoFrame;
4345 } else {
4346 return this._data;
4347 }
4348 }
4349 /**
4350 * Transform this video sample to a new video sample given the options. Can be used to resize, rotate, and crop
4351 * the sample.
4352 *
4353 * In non-browser environments, this method will not work by default. To make it work, register a custom
4354 * transformer function via {@link registerVideoSampleTransformer}.
4355 */
4356 async transform(options) {
4357 if (!options || typeof options !== "object") {
4358 throw new TypeError("options must be an object.");
4359 }
4360 if (options.width !== void 0 && (!Number.isInteger(options.width) || options.width <= 0)) {
4361 throw new TypeError("options.width, when provided, must be a positive integer.");
4362 }
4363 if (options.height !== void 0 && (!Number.isInteger(options.height) || options.height <= 0)) {
4364 throw new TypeError("options.height, when provided, must be a positive integer.");
4365 }
4366 if (options.roundDimensionsTo !== void 0 && (!Number.isInteger(options.roundDimensionsTo) || options.roundDimensionsTo <= 0)) {
4367 throw new TypeError("options.roundDimensionsTo, when provided, must be a positive integer.");
4368 }
4369 if (options.fit !== void 0 && !["fill", "contain", "cover"].includes(options.fit)) {
4370 throw new TypeError('options.fit, when provided, must be one of "fill", "contain", or "cover".');
4371 }
4372 if (options.width !== void 0 && options.height !== void 0 && options.fit === void 0) {
4373 throw new TypeError("When both options.width and options.height are provided, options.fit must also be provided.");
4374 }
4375 if (options.rotate !== void 0 && ![0, 90, 180, 270].includes(options.rotate)) {
4376 throw new TypeError("options.rotate, when provided, must be 0, 90, 180 or 270.");
4377 }
4378 if (options.crop !== void 0) {
4379 validateCropRectangle(options.crop, "options.");
4380 }
4381 if (options.alpha !== void 0 && !["keep", "discard"].includes(options.alpha)) {
4382 throw new TypeError("options.alpha, when provided, must be 'keep' or 'discard'.");
4383 }
4384 const rotation = normalizeRotation(this.rotation + (options.rotate ?? 0));
4385 const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [this.squarePixelWidth, this.squarePixelHeight] : [this.squarePixelHeight, this.squarePixelWidth];
4386 let finalCrop = options.crop;
4387 if (finalCrop) {
4388 finalCrop = clampCropRectangle(finalCrop, rotatedWidth, rotatedHeight);
4389 }
4390 const cropWidth = finalCrop ? finalCrop.width : rotatedWidth;
4391 const cropHeight = finalCrop ? finalCrop.height : rotatedHeight;
4392 const originalAspectRatio = cropWidth / cropHeight;
4393 let targetWidth;
4394 let targetHeight;
4395 if (options.width !== void 0 && options.height === void 0) {
4396 targetWidth = options.width;
4397 targetHeight = targetWidth / originalAspectRatio;
4398 } else if (options.width === void 0 && options.height !== void 0) {
4399 targetHeight = options.height;
4400 targetWidth = targetHeight * originalAspectRatio;
4401 } else if (options.width !== void 0 && options.height !== void 0) {
4402 targetWidth = options.width;
4403 targetHeight = options.height;
4404 } else {
4405 targetWidth = cropWidth;
4406 targetHeight = cropHeight;
4407 }
4408 targetWidth = roundToMultiple(targetWidth, options.roundDimensionsTo ?? 1);
4409 targetHeight = roundToMultiple(targetHeight, options.roundDimensionsTo ?? 1);
4410 const description = {
4411 width: targetWidth,
4412 height: targetHeight,
4413 fit: options.fit ?? "fill",
4414 rotation,
4415 crop: finalCrop ?? {
4416 left: 0,
4417 top: 0,
4418 width: rotatedWidth,
4419 height: rotatedHeight
4420 },
4421 alpha: options.alpha ?? "keep"
4422 };
4423 for (const transformer of registeredVideoSampleTransformers) {
4424 let result = transformer(this, description);
4425 if (result instanceof Promise)
4426 result = await result;
4427 if (result !== null) {
4428 return result;
4429 }
4430 }
4431 let canvas = null;
4432 let canvasIsNew = false;
4433 for (const entry of transformationCanvasCache) {
4434 if (entry.canvas.width === description.width && entry.canvas.height === description.height) {
4435 canvas = entry.canvas;
4436 entry.age = transformationCanvasCacheNextAge++;
4437 break;
4438 }
4439 }
4440 if (canvas === null) {
4441 if (typeof OffscreenCanvas !== "undefined") {
4442 canvas = new OffscreenCanvas(description.width, description.height);
4443 } else {
4444 if (typeof window === "undefined" || typeof document === "undefined") {
4445 throw new Error("Cannot transform VideoSamples in this environment. Either run in an environment with OffscreenCanvas or HTMLCanvasElement, or supply a custom VideoSample transformer using registerVideoSampleTransformer().");
4446 }
4447 canvas = document.createElement("canvas");
4448 canvas.width = description.width;
4449 canvas.height = description.height;
4450 }
4451 canvasIsNew = true;
4452 if (transformationCanvasCache.length >= TRANSFORMATION_CANVAS_CACHE_MAX_SIZE) {
4453 transformationCanvasCache.splice(arrayArgmin(transformationCanvasCache, (x) => x.age), 1);
4454 }
4455 transformationCanvasCache.push({
4456 canvas,
4457 age: transformationCanvasCacheNextAge++
4458 });
4459 }
4460 const context = canvas.getContext("2d", {
4461 alpha: true
4462 });
4463 if (!context) {
4464 throw new Error("The '2d' canvas context is required to transform VideoSamples. Register a custom transformer using registerVideoSampleTransformer to work around this limitation.");
4465 }
4466 if (description.alpha === "discard") {
4467 context.fillStyle = "black";
4468 context.fillRect(0, 0, description.width, description.height);
4469 } else if (!canvasIsNew) {
4470 context.clearRect(0, 0, description.width, description.height);
4471 }
4472 this.drawWithFit(context, {
4473 fit: description.fit,
4474 rotation: description.rotation,
4475 crop: description.crop
4476 });
4477 return new _VideoSample(canvas, {
4478 timestamp: this.timestamp,
4479 duration: this.duration,
4480 rotation: 0
4481 // Any previous rotation is now baked in
4482 });
4483 }
4484 /** Sets the rotation metadata of this video sample. */
4485 setRotation(newRotation) {
4486 if (![0, 90, 180, 270].includes(newRotation)) {
4487 throw new TypeError("newRotation must be 0, 90, 180, or 270.");
4488 }
4489 this.rotation = newRotation;
4490 }
4491 /** Sets the presentation timestamp of this video sample, in seconds. */
4492 setTimestamp(newTimestamp) {
4493 if (!Number.isFinite(newTimestamp)) {
4494 throw new TypeError("newTimestamp must be a number.");
4495 }
4496 this.timestamp = newTimestamp;
4497 }
4498 /** Sets the duration of this video sample, in seconds. */
4499 setDuration(newDuration) {
4500 if (!Number.isFinite(newDuration) || newDuration < 0) {
4501 throw new TypeError("newDuration must be a non-negative number.");
4502 }
4503 this.duration = newDuration;
4504 }
4505 /** Sets the encode options used when this sample is passed to an encoder. */
4506 setEncodeOptions(newEncodeOptions) {
4507 if (!newEncodeOptions || typeof newEncodeOptions !== "object") {
4508 throw new TypeError("newEncodeOptions must be an object.");
4509 }
4510 this.encodeOptions = newEncodeOptions;
4511 }
4512 /** Calls \`.close()\`. */
4513 [Symbol.dispose]() {
4514 this.close();
4515 }
4516 };
4517 var registeredVideoSampleTransformers = [];
4518 var TRANSFORMATION_CANVAS_CACHE_MAX_SIZE = 3;
4519 var transformationCanvasCache = [];
4520 var transformationCanvasCacheNextAge = 0;
4521 var VideoSampleColorSpace = class {
4522 /** Creates a new VideoSampleColorSpace. */
4523 constructor(init) {
4524 if (init !== void 0) {
4525 if (!init || typeof init !== "object") {
4526 throw new TypeError("init.colorSpace, when provided, must be an object.");
4527 }
4528 const primariesValues = Object.keys(COLOR_PRIMARIES_MAP);
4529 if (init.primaries != null && !primariesValues.includes(init.primaries)) {
4530 throw new TypeError(\`init.colorSpace.primaries, when provided, must be one of \${primariesValues.join(", ")}.\`);
4531 }
4532 const transferValues = Object.keys(TRANSFER_CHARACTERISTICS_MAP);
4533 if (init.transfer != null && !transferValues.includes(init.transfer)) {
4534 throw new TypeError(\`init.colorSpace.transfer, when provided, must be one of \${transferValues.join(", ")}.\`);
4535 }
4536 const matrixValues = Object.keys(MATRIX_COEFFICIENTS_MAP);
4537 if (init.matrix != null && !matrixValues.includes(init.matrix)) {
4538 throw new TypeError(\`init.colorSpace.matrix, when provided, must be one of \${matrixValues.join(", ")}.\`);
4539 }
4540 if (init.fullRange != null && typeof init.fullRange !== "boolean") {
4541 throw new TypeError("init.colorSpace.fullRange, when provided, must be a boolean.");
4542 }
4543 }
4544 this.primaries = init?.primaries ?? null;
4545 this.transfer = init?.transfer ?? null;
4546 this.matrix = init?.matrix ?? null;
4547 this.fullRange = init?.fullRange ?? null;
4548 }
4549 /** Serializes the color space to a JSON object. */
4550 toJSON() {
4551 return {
4552 primaries: this.primaries,
4553 transfer: this.transfer,
4554 matrix: this.matrix,
4555 fullRange: this.fullRange
4556 };
4557 }
4558 };
4559 var isVideoFrame = (x) => {
4560 return typeof VideoFrame !== "undefined" && x instanceof VideoFrame;
4561 };
4562 var clampCropRectangle = (crop, outerWidth, outerHeight) => {
4563 const left = Math.min(crop.left, outerWidth);
4564 const top = Math.min(crop.top, outerHeight);
4565 const width = Math.min(crop.width, outerWidth - left);
4566 const height = Math.min(crop.height, outerHeight - top);
4567 assert(width >= 0);
4568 assert(height >= 0);
4569 return { left, top, width, height };
4570 };
4571 var validateCropRectangle = (crop, prefix) => {
4572 if (!crop || typeof crop !== "object") {
4573 throw new TypeError(prefix + "crop, when provided, must be an object.");
4574 }
4575 if (!Number.isInteger(crop.left) || crop.left < 0) {
4576 throw new TypeError(prefix + "crop.left must be a non-negative integer.");
4577 }
4578 if (!Number.isInteger(crop.top) || crop.top < 0) {
4579 throw new TypeError(prefix + "crop.top must be a non-negative integer.");
4580 }
4581 if (!Number.isInteger(crop.width) || crop.width < 0) {
4582 throw new TypeError(prefix + "crop.width must be a non-negative integer.");
4583 }
4584 if (!Number.isInteger(crop.height) || crop.height < 0) {
4585 throw new TypeError(prefix + "crop.height must be a non-negative integer.");
4586 }
4587 };
4588 var validateVideoFrameCopyToOptions = (options) => {
4589 if (!options || typeof options !== "object") {
4590 throw new TypeError("options must be an object.");
4591 }
4592 if (options.colorSpace !== void 0 && !["display-p3", "srgb"].includes(options.colorSpace)) {
4593 throw new TypeError("options.colorSpace, when provided, must be 'display-p3' or 'srgb'.");
4594 }
4595 if (options.format !== void 0 && typeof options.format !== "string") {
4596 throw new TypeError("options.format, when provided, must be a string.");
4597 }
4598 if (options.layout !== void 0) {
4599 if (!Array.isArray(options.layout)) {
4600 throw new TypeError("options.layout, when provided, must be an array.");
4601 }
4602 for (const plane of options.layout) {
4603 if (!plane || typeof plane !== "object") {
4604 throw new TypeError("Each entry in options.layout must be an object.");
4605 }
4606 if (!Number.isInteger(plane.offset) || plane.offset < 0) {
4607 throw new TypeError("plane.offset must be a non-negative integer.");
4608 }
4609 if (!Number.isInteger(plane.stride) || plane.stride < 0) {
4610 throw new TypeError("plane.stride must be a non-negative integer.");
4611 }
4612 }
4613 }
4614 if (options.rect !== void 0) {
4615 if (!options.rect || typeof options.rect !== "object") {
4616 throw new TypeError("options.rect, when provided, must be an object.");
4617 }
4618 if (options.rect.x !== void 0 && (!Number.isInteger(options.rect.x) || options.rect.x < 0)) {
4619 throw new TypeError("options.rect.x, when provided, must be a non-negative integer.");
4620 }
4621 if (options.rect.y !== void 0 && (!Number.isInteger(options.rect.y) || options.rect.y < 0)) {
4622 throw new TypeError("options.rect.y, when provided, must be a non-negative integer.");
4623 }
4624 if (options.rect.width !== void 0 && (!Number.isInteger(options.rect.width) || options.rect.width < 0)) {
4625 throw new TypeError("options.rect.width, when provided, must be a non-negative integer.");
4626 }
4627 if (options.rect.height !== void 0 && (!Number.isInteger(options.rect.height) || options.rect.height < 0)) {
4628 throw new TypeError("options.rect.height, when provided, must be a non-negative integer.");
4629 }
4630 }
4631 };
4632 var createDefaultPlaneLayout = (format, codedWidth, codedHeight) => {
4633 const planes = getPlaneConfigs(format);
4634 const layouts = [];
4635 let currentOffset = 0;
4636 for (const plane of planes) {
4637 const planeWidth = Math.ceil(codedWidth / plane.widthDivisor);
4638 const planeHeight = Math.ceil(codedHeight / plane.heightDivisor);
4639 const stride = planeWidth * plane.sampleBytes;
4640 const planeSize = stride * planeHeight;
4641 layouts.push({
4642 offset: currentOffset,
4643 stride
4644 });
4645 currentOffset += planeSize;
4646 }
4647 return layouts;
4648 };
4649 var getPlaneConfigs = (format) => {
4650 const yuv = (yBytes, uvBytes, subX, subY, hasAlpha) => {
4651 const configs = [
4652 { sampleBytes: yBytes, widthDivisor: 1, heightDivisor: 1 },
4653 { sampleBytes: uvBytes, widthDivisor: subX, heightDivisor: subY },
4654 { sampleBytes: uvBytes, widthDivisor: subX, heightDivisor: subY }
4655 ];
4656 if (hasAlpha) {
4657 configs.push({ sampleBytes: yBytes, widthDivisor: 1, heightDivisor: 1 });
4658 }
4659 return configs;
4660 };
4661 switch (format) {
4662 case "I420":
4663 return yuv(1, 1, 2, 2, false);
4664 case "I420P10":
4665 case "I420P12":
4666 return yuv(2, 2, 2, 2, false);
4667 case "I420A":
4668 return yuv(1, 1, 2, 2, true);
4669 case "I420AP10":
4670 case "I420AP12":
4671 return yuv(2, 2, 2, 2, true);
4672 case "I422":
4673 return yuv(1, 1, 2, 1, false);
4674 case "I422P10":
4675 case "I422P12":
4676 return yuv(2, 2, 2, 1, false);
4677 case "I422A":
4678 return yuv(1, 1, 2, 1, true);
4679 case "I422AP10":
4680 case "I422AP12":
4681 return yuv(2, 2, 2, 1, true);
4682 case "I444":
4683 return yuv(1, 1, 1, 1, false);
4684 case "I444P10":
4685 case "I444P12":
4686 return yuv(2, 2, 1, 1, false);
4687 case "I444A":
4688 return yuv(1, 1, 1, 1, true);
4689 case "I444AP10":
4690 case "I444AP12":
4691 return yuv(2, 2, 1, 1, true);
4692 case "NV12":
4693 return [
4694 { sampleBytes: 1, widthDivisor: 1, heightDivisor: 1 },
4695 { sampleBytes: 2, widthDivisor: 2, heightDivisor: 2 }
4696 // Interleaved U and V
4697 ];
4698 case "RGBA":
4699 case "RGBX":
4700 case "BGRA":
4701 case "BGRX":
4702 return [
4703 { sampleBytes: 4, widthDivisor: 1, heightDivisor: 1 }
4704 ];
4705 default:
4706 assertNever(format);
4707 assert(false);
4708 }
4709 };
4710 var ParseVideoFrameCopyToOptions = (sample, options) => {
4711 const defaultRect = {
4712 left: 0,
4713 top: 0,
4714 width: sample.codedWidth,
4715 height: sample.codedHeight
4716 };
4717 const overrideRect = options.rect;
4718 const parsedRect = ParseVisibleRect(defaultRect, overrideRect, sample.codedWidth, sample.codedHeight, sample.format);
4719 const optLayout = options.layout;
4720 let format;
4721 if (!options.format || options.format === sample.format) {
4722 format = sample.format;
4723 } else if (["RGBA", "RGBX", "BGRA", "BGRX"].includes(options.format)) {
4724 format = options.format;
4725 } else {
4726 throw new Error("NotSupportedError: Invalid destination format.");
4727 }
4728 return ComputeLayoutAndAllocationSize(parsedRect, format, optLayout);
4729 };
4730 var ParseVisibleRect = (defaultRect, overrideRect, codedWidth, codedHeight, format) => {
4731 const sourceRect = { ...defaultRect };
4732 if (overrideRect !== void 0) {
4733 if (overrideRect.width === 0 || overrideRect.height === 0) {
4734 throw new TypeError("visibleRect dimensions cannot be zero.");
4735 }
4736 if ((overrideRect.x || 0) + (overrideRect.width || 0) > codedWidth) {
4737 throw new TypeError("visibleRect exceeds codedWidth.");
4738 }
4739 if ((overrideRect.y || 0) + (overrideRect.height || 0) > codedHeight) {
4740 throw new TypeError("visibleRect exceeds codedHeight.");
4741 }
4742 sourceRect.x = overrideRect.x || 0;
4743 sourceRect.y = overrideRect.y || 0;
4744 sourceRect.width = overrideRect.width || 0;
4745 sourceRect.height = overrideRect.height || 0;
4746 }
4747 const validAlignment = VerifyRectOffsetAlignment(format, sourceRect);
4748 if (!validAlignment) {
4749 throw new TypeError("visibleRect alignment is invalid for the format.");
4750 }
4751 return sourceRect;
4752 };
4753 var VerifyRectOffsetAlignment = (format, rect) => {
4754 if (format === null)
4755 return true;
4756 const planes = getPlaneConfigs(format);
4757 for (let planeIndex = 0; planeIndex < planes.length; planeIndex++) {
4758 const plane = planes[planeIndex];
4759 const sampleWidth = plane.widthDivisor;
4760 const sampleHeight = plane.heightDivisor;
4761 if ((rect.x || 0) % sampleWidth !== 0)
4762 return false;
4763 if ((rect.y || 0) % sampleHeight !== 0)
4764 return false;
4765 }
4766 return true;
4767 };
4768 var ComputeLayoutAndAllocationSize = (parsedRect, format, layout) => {
4769 const planes = getPlaneConfigs(format);
4770 const numPlanes = planes.length;
4771 if (layout !== void 0 && layout.length !== numPlanes) {
4772 throw new TypeError(\`Layout must have \${numPlanes} planes.\`);
4773 }
4774 let minAllocationSize = 0;
4775 const computedLayouts = [];
4776 const endOffsets = [];
4777 for (let planeIndex = 0; planeIndex < numPlanes; planeIndex++) {
4778 const plane = planes[planeIndex];
4779 const sampleBytes = plane.sampleBytes;
4780 const sampleWidth = plane.widthDivisor;
4781 const sampleHeight = plane.heightDivisor;
4782 const computedLayout = {
4783 destinationOffset: 0,
4784 destinationStride: 0,
4785 sourceTop: 0,
4786 sourceHeight: 0,
4787 sourceLeftBytes: 0,
4788 sourceWidthBytes: 0
4789 };
4790 computedLayout.sourceTop = Math.ceil(Math.trunc(parsedRect.y || 0) / sampleHeight);
4791 computedLayout.sourceHeight = Math.ceil(Math.trunc(parsedRect.height || 0) / sampleHeight);
4792 computedLayout.sourceLeftBytes = Math.floor(Math.trunc(parsedRect.x || 0) / sampleWidth) * sampleBytes;
4793 computedLayout.sourceWidthBytes = Math.floor(Math.trunc(parsedRect.width || 0) / sampleWidth) * sampleBytes;
4794 if (layout !== void 0) {
4795 const planeLayout = layout[planeIndex];
4796 if (planeLayout.stride < computedLayout.sourceWidthBytes) {
4797 throw new TypeError(\`Stride for plane \${planeIndex} is too small.\`);
4798 }
4799 computedLayout.destinationOffset = planeLayout.offset;
4800 computedLayout.destinationStride = planeLayout.stride;
4801 } else {
4802 computedLayout.destinationOffset = minAllocationSize;
4803 computedLayout.destinationStride = computedLayout.sourceWidthBytes;
4804 }
4805 const planeSize = computedLayout.destinationStride * computedLayout.sourceHeight;
4806 const planeEnd = planeSize + computedLayout.destinationOffset;
4807 if (planeEnd > 4294967295) {
4808 throw new TypeError("Allocation size exceeds limit.");
4809 }
4810 endOffsets.push(planeEnd);
4811 minAllocationSize = Math.max(minAllocationSize, planeEnd);
4812 for (let earlierPlaneIndex = 0; earlierPlaneIndex < planeIndex; earlierPlaneIndex++) {
4813 const earlierLayout = computedLayouts[earlierPlaneIndex];
4814 if (endOffsets[planeIndex] <= earlierLayout.destinationOffset || endOffsets[earlierPlaneIndex] <= computedLayout.destinationOffset) {
4815 continue;
4816 }
4817 throw new TypeError("Planes overlap.");
4818 }
4819 computedLayouts.push(computedLayout);
4820 }
4821 return {
4822 allocationSize: minAllocationSize,
4823 computedLayouts
4824 };
4825 };
4826
4827 // node_modules/mediabunny/dist/modules/src/encode.js
4828 var canEncodeVideoMemo = /* @__PURE__ */ new Map();
4829 var validateVideoEncodingConfig = (config) => {
4830 if (!config || typeof config !== "object") {
4831 throw new TypeError("Encoding config must be an object.");
4832 }
4833 if (!VIDEO_CODECS.includes(config.codec)) {
4834 throw new TypeError(\`Invalid video codec '\${config.codec}'. Must be one of: \${VIDEO_CODECS.join(", ")}.\`);
4835 }
4836 if (!(config.bitrate instanceof Quality) && (!Number.isInteger(config.bitrate) || config.bitrate <= 0)) {
4837 throw new TypeError("config.bitrate must be a positive integer or a quality.");
4838 }
4839 if (config.keyFrameInterval !== void 0 && (!Number.isFinite(config.keyFrameInterval) || config.keyFrameInterval < 0)) {
4840 throw new TypeError("config.keyFrameInterval, when provided, must be a non-negative number.");
4841 }
4842 if (config.sizeChangeBehavior !== void 0 && !["deny", "passThrough", "fill", "contain", "cover"].includes(config.sizeChangeBehavior)) {
4843 throw new TypeError("config.sizeChangeBehavior, when provided, must be 'deny', 'passThrough', 'fill', 'contain' or 'cover'.");
4844 }
4845 if (config.transform !== void 0) {
4846 if (typeof config.transform !== "object" || !config.transform) {
4847 throw new TypeError("config.transform, when provided, must be an object.");
4848 }
4849 if (config.transform.width !== void 0 && (!Number.isInteger(config.transform.width) || config.transform.width <= 0)) {
4850 throw new TypeError("config.transform.width, when provided, must be a positive integer.");
4851 }
4852 if (config.transform.height !== void 0 && (!Number.isInteger(config.transform.height) || config.transform.height <= 0)) {
4853 throw new TypeError("config.transform.height, when provided, must be a positive integer.");
4854 }
4855 if (config.transform.fit !== void 0 && !["fill", "contain", "cover"].includes(config.transform.fit)) {
4856 throw new TypeError('config.transform.fit, when provided, must be one of "fill", "contain", or "cover".');
4857 }
4858 if (config.transform.width !== void 0 && config.transform.height !== void 0 && config.transform.fit === void 0 && !["fill", "contain", "cover"].includes(config.sizeChangeBehavior)) {
4859 throw new TypeError("When both config.transform.width and config.transform.height are provided, config.transform.fit must also be provided.");
4860 }
4861 if (config.transform.fit !== void 0 && ["fill", "contain", "cover"].includes(config.sizeChangeBehavior) && config.transform.fit !== config.sizeChangeBehavior) {
4862 throw new TypeError("config.transform.fit, when provided, cannot differ from config.sizeChangeBehavior when config.sizeChangeBehavior is 'fill', 'contain' or 'cover', as sizeChangeBehavior already determines the fitting algorithm.");
4863 }
4864 if (config.transform.rotate !== void 0 && ![0, 90, 180, 270].includes(config.transform.rotate)) {
4865 throw new TypeError("config.transform.rotate, when provided, must be 0, 90, 180 or 270.");
4866 }
4867 if (config.transform.crop !== void 0) {
4868 validateCropRectangle(config.transform.crop, "config.transform.");
4869 }
4870 if (config.transform.process !== void 0 && typeof config.transform.process !== "function") {
4871 throw new TypeError("config.transform.process, when provided, must be a function.");
4872 }
4873 if (config.transform.frameRate !== void 0 && (!Number.isFinite(config.transform.frameRate) || config.transform.frameRate <= 0)) {
4874 throw new TypeError("config.transform.frameRate, when provided, must be a finite positive number.");
4875 }
4876 if (config.transform.force !== void 0 && typeof config.transform.force !== "boolean") {
4877 throw new TypeError("config.transform.force, when provided, must be a boolean.");
4878 }
4879 }
4880 if (config.onEncodedPacket !== void 0 && typeof config.onEncodedPacket !== "function") {
4881 throw new TypeError("config.onEncodedPacket, when provided, must be a function.");
4882 }
4883 if (config.onEncoderConfig !== void 0 && typeof config.onEncoderConfig !== "function") {
4884 throw new TypeError("config.onEncoderConfig, when provided, must be a function.");
4885 }
4886 if (config.onEncodedSample !== void 0 && typeof config.onEncodedSample !== "function") {
4887 throw new TypeError("config.onEncodedSample, when provided, must be a function.");
4888 }
4889 validateVideoEncodingAdditionalOptions(config.codec, config);
4890 };
4891 var validateVideoEncodingAdditionalOptions = (codec, options) => {
4892 if (!options || typeof options !== "object") {
4893 throw new TypeError("Encoding options must be an object.");
4894 }
4895 if (options.alpha !== void 0 && !["discard", "keep"].includes(options.alpha)) {
4896 throw new TypeError("options.alpha, when provided, must be 'discard' or 'keep'.");
4897 }
4898 if (options.bitrateMode !== void 0 && !["constant", "variable"].includes(options.bitrateMode)) {
4899 throw new TypeError("bitrateMode, when provided, must be 'constant' or 'variable'.");
4900 }
4901 if (options.latencyMode !== void 0 && !["quality", "realtime"].includes(options.latencyMode)) {
4902 throw new TypeError("latencyMode, when provided, must be 'quality' or 'realtime'.");
4903 }
4904 if (options.fullCodecString !== void 0 && typeof options.fullCodecString !== "string") {
4905 throw new TypeError("fullCodecString, when provided, must be a string.");
4906 }
4907 if (options.fullCodecString !== void 0 && inferCodecFromCodecString(options.fullCodecString) !== codec) {
4908 throw new TypeError(\`fullCodecString, when provided, must be a string that matches the specified codec (\${codec}).\`);
4909 }
4910 if (options.hardwareAcceleration !== void 0 && !["no-preference", "prefer-hardware", "prefer-software"].includes(options.hardwareAcceleration)) {
4911 throw new TypeError("hardwareAcceleration, when provided, must be 'no-preference', 'prefer-hardware' or 'prefer-software'.");
4912 }
4913 if (options.scalabilityMode !== void 0 && typeof options.scalabilityMode !== "string") {
4914 throw new TypeError("scalabilityMode, when provided, must be a string.");
4915 }
4916 if (options.contentHint !== void 0 && typeof options.contentHint !== "string") {
4917 throw new TypeError("contentHint, when provided, must be a string.");
4918 }
4919 };
4920 var buildVideoEncoderConfig = (options) => {
4921 const resolvedBitrate = options.bitrate instanceof Quality ? options.bitrate._toVideoBitrate(options.codec, options.width, options.height) : options.bitrate;
4922 return {
4923 codec: options.fullCodecString ?? buildVideoCodecString(options.codec, options.width, options.height, resolvedBitrate),
4924 width: options.width,
4925 height: options.height,
4926 displayWidth: options.squarePixelWidth,
4927 displayHeight: options.squarePixelHeight,
4928 bitrate: resolvedBitrate,
4929 bitrateMode: options.bitrateMode,
4930 alpha: options.alpha ?? "discard",
4931 framerate: options.framerate,
4932 latencyMode: options.latencyMode,
4933 hardwareAcceleration: options.hardwareAcceleration,
4934 scalabilityMode: options.scalabilityMode,
4935 contentHint: options.contentHint,
4936 ...getVideoEncoderConfigExtension(options.codec)
4937 };
4938 };
4939 var Quality = class {
4940 /** @internal */
4941 constructor(factor) {
4942 this._factor = factor;
4943 }
4944 /** @internal */
4945 _toVideoBitrate(codec, width, height) {
4946 const pixels = width * height;
4947 const codecEfficiencyFactors = {
4948 avc: 1,
4949 // H.264/AVC (baseline)
4950 hevc: 0.6,
4951 // H.265/HEVC (~40% more efficient than AVC)
4952 vp9: 0.6,
4953 // Similar to HEVC
4954 av1: 0.4,
4955 // ~60% more efficient than AVC
4956 vp8: 1.2
4957 // Slightly less efficient than AVC
4958 };
4959 const referencePixels = 1920 * 1080;
4960 const referenceBitrate = 3e6;
4961 const scaleFactor = Math.pow(pixels / referencePixels, 0.95);
4962 const baseBitrate = referenceBitrate * scaleFactor;
4963 const codecAdjustedBitrate = baseBitrate * codecEfficiencyFactors[codec];
4964 const finalBitrate = codecAdjustedBitrate * this._factor;
4965 return Math.ceil(finalBitrate / 1e3) * 1e3;
4966 }
4967 /** @internal */
4968 _toAudioBitrate(codec) {
4969 if (PCM_AUDIO_CODECS.includes(codec) || codec === "flac") {
4970 return void 0;
4971 }
4972 const baseRates = {
4973 aac: 128e3,
4974 // 128kbps base for AAC
4975 opus: 64e3,
4976 // 64kbps base for Opus
4977 mp3: 16e4,
4978 // 160kbps base for MP3
4979 vorbis: 64e3,
4980 // 64kbps base for Vorbis
4981 ac3: 384e3,
4982 // 384kbps base for AC-3
4983 eac3: 192e3
4984 // 192kbps base for E-AC-3
4985 };
4986 const baseBitrate = baseRates[codec];
4987 if (!baseBitrate) {
4988 throw new Error(\`Unhandled codec: \${codec}\`);
4989 }
4990 let finalBitrate = baseBitrate * this._factor;
4991 if (codec === "aac") {
4992 const validRates = [96e3, 128e3, 16e4, 192e3];
4993 finalBitrate = validRates.reduce((prev, curr) => Math.abs(curr - finalBitrate) < Math.abs(prev - finalBitrate) ? curr : prev);
4994 } else if (codec === "opus" || codec === "vorbis") {
4995 finalBitrate = Math.max(6e3, finalBitrate);
4996 } else if (codec === "mp3") {
4997 const validRates = [
4998 8e3,
4999 16e3,
5000 24e3,
5001 32e3,
5002 4e4,
5003 48e3,
5004 64e3,
5005 8e4,
5006 96e3,
5007 112e3,
5008 128e3,
5009 16e4,
5010 192e3,
5011 224e3,
5012 256e3,
5013 32e4
5014 ];
5015 finalBitrate = validRates.reduce((prev, curr) => Math.abs(curr - finalBitrate) < Math.abs(prev - finalBitrate) ? curr : prev);
5016 }
5017 return Math.round(finalBitrate / 1e3) * 1e3;
5018 }
5019 };
5020 var QUALITY_HIGH = /* @__PURE__ */ new Quality(2);
5021 var canEncodeVideo = async (codec, options = {}) => {
5022 const { width = 1280, height = 720, bitrate = 1e6, ...restOptions } = options;
5023 if (!VIDEO_CODECS.includes(codec)) {
5024 return false;
5025 }
5026 if (!Number.isInteger(width) || width <= 0) {
5027 throw new TypeError("width must be a positive integer.");
5028 }
5029 if (!Number.isInteger(height) || height <= 0) {
5030 throw new TypeError("height must be a positive integer.");
5031 }
5032 if (!(bitrate instanceof Quality) && (!Number.isInteger(bitrate) || bitrate <= 0)) {
5033 throw new TypeError("bitrate must be a positive integer or a quality.");
5034 }
5035 validateVideoEncodingAdditionalOptions(codec, restOptions);
5036 const encoderConfig = buildVideoEncoderConfig({
5037 codec,
5038 width,
5039 height,
5040 bitrate,
5041 framerate: void 0,
5042 ...restOptions,
5043 alpha: "discard"
5044 // Since we handle alpha ourselves
5045 });
5046 const key = JSON.stringify(encoderConfig);
5047 const memoized = canEncodeVideoMemo.get(key);
5048 if (memoized) {
5049 return memoized;
5050 }
5051 const promise = (async () => {
5052 if (customVideoEncoders.some((x) => x.supports(codec, encoderConfig))) {
5053 return true;
5054 }
5055 if (typeof VideoEncoder === "undefined") {
5056 return false;
5057 }
5058 const hasOddDimension = width % 2 === 1 || height % 2 === 1;
5059 if (hasOddDimension && (codec === "avc" || codec === "hevc")) {
5060 return false;
5061 }
5062 const support = await VideoEncoder.isConfigSupported(encoderConfig);
5063 if (!support.supported) {
5064 return false;
5065 }
5066 if (isFirefox()) {
5067 return new Promise(async (resolve) => {
5068 try {
5069 const encoder = new VideoEncoder({
5070 output: () => {
5071 },
5072 error: () => resolve(false)
5073 });
5074 encoder.configure(encoderConfig);
5075 const frameData = new Uint8Array(width * height * 4);
5076 const frame = new VideoFrame(frameData, {
5077 format: "RGBA",
5078 codedWidth: width,
5079 codedHeight: height,
5080 timestamp: 0
5081 });
5082 encoder.encode(frame);
5083 frame.close();
5084 await encoder.flush();
5085 resolve(true);
5086 } catch {
5087 resolve(false);
5088 }
5089 });
5090 }
5091 return true;
5092 })();
5093 canEncodeVideoMemo.set(key, promise);
5094 return promise;
5095 };
5096
5097 // node_modules/mediabunny/dist/modules/src/custom-coder.js
5098 var customVideoEncoders = [];
5099
5100 // node_modules/mediabunny/dist/modules/src/reader.js
5101 var FileSlice = class _FileSlice {
5102 constructor(bytes2, view2, offset, start, end) {
5103 this.bytes = bytes2;
5104 this.view = view2;
5105 this.offset = offset;
5106 this.start = start;
5107 this.end = end;
5108 this.bufferPos = start - offset;
5109 }
5110 static tempFromBytes(bytes2) {
5111 return new _FileSlice(bytes2, toDataView(bytes2), 0, 0, bytes2.length);
5112 }
5113 get length() {
5114 return this.end - this.start;
5115 }
5116 get filePos() {
5117 return this.offset + this.bufferPos;
5118 }
5119 set filePos(value) {
5120 this.bufferPos = value - this.offset;
5121 }
5122 /** The number of bytes left from the current pos to the end of the slice. */
5123 get remainingLength() {
5124 return Math.max(this.end - this.filePos, 0);
5125 }
5126 skip(byteCount) {
5127 this.bufferPos += byteCount;
5128 }
5129 /** Creates a new subslice of this slice whose byte range must be contained within this slice. */
5130 slice(filePos, length = this.end - filePos) {
5131 if (filePos < this.start || filePos + length > this.end) {
5132 throw new RangeError("Slicing outside of original slice.");
5133 }
5134 return new _FileSlice(this.bytes, this.view, this.offset, filePos, filePos + length);
5135 }
5136 };
5137 var checkIsInRange = (slice, bytesToRead) => {
5138 if (slice.filePos < slice.start || slice.filePos + bytesToRead > slice.end) {
5139 throw new RangeError(\`Tried reading [\${slice.filePos}, \${slice.filePos + bytesToRead}), but slice is [\${slice.start}, \${slice.end}). This is likely an internal error, please report it alongside the file that caused it.\`);
5140 }
5141 };
5142 var readBytes = (slice, length) => {
5143 checkIsInRange(slice, length);
5144 const bytes2 = slice.bytes.subarray(slice.bufferPos, slice.bufferPos + length);
5145 slice.bufferPos += length;
5146 return bytes2;
5147 };
5148
5149 // node_modules/mediabunny/dist/modules/src/muxer.js
5150 var Muxer = class {
5151 constructor(output) {
5152 this.mutex = new AsyncMutex();
5153 this.trackTimestampInfo = /* @__PURE__ */ new WeakMap();
5154 this.output = output;
5155 }
5156 // eslint-disable-next-line @typescript-eslint/no-unused-vars
5157 onTrackClose(track) {
5158 }
5159 validateTimestamp(track, timestampInSeconds, isKeyPacket) {
5160 if (timestampInSeconds < 0) {
5161 throw new Error(\`Timestamps must be non-negative (got \${timestampInSeconds}s).\`);
5162 }
5163 let timestampInfo = this.trackTimestampInfo.get(track);
5164 if (!timestampInfo) {
5165 if (!isKeyPacket) {
5166 throw new Error("First packet must be a key packet.");
5167 }
5168 timestampInfo = {
5169 maxTimestamp: timestampInSeconds,
5170 maxTimestampBeforeLastKeyPacket: null
5171 };
5172 this.trackTimestampInfo.set(track, timestampInfo);
5173 } else {
5174 if (isKeyPacket) {
5175 timestampInfo.maxTimestampBeforeLastKeyPacket = timestampInfo.maxTimestamp;
5176 }
5177 if (timestampInfo.maxTimestampBeforeLastKeyPacket !== null && timestampInSeconds < timestampInfo.maxTimestampBeforeLastKeyPacket) {
5178 throw new Error(\`Timestamps cannot be smaller than the largest timestamp of the previous GOP (a GOP begins with a key packet and ends right before the next key packet). Got \${timestampInSeconds}s, but largest timestamp is \${timestampInfo.maxTimestampBeforeLastKeyPacket}s.\`);
5179 }
5180 timestampInfo.maxTimestamp = Math.max(timestampInfo.maxTimestamp, timestampInSeconds);
5181 }
5182 }
5183 };
5184
5185 // node_modules/mediabunny/dist/modules/src/subtitles.js
5186 var inlineTimestampRegex = /<(?:(\\d{2}):)?(\\d{2}):(\\d{2}).(\\d{3})>/g;
5187 var timestampRegex = /(?:(\\d{2}):)?(\\d{2}):(\\d{2}).(\\d{3})/;
5188 var parseSubtitleTimestamp = (string) => {
5189 const match = timestampRegex.exec(string);
5190 if (!match)
5191 throw new Error("Expected match.");
5192 return 60 * 60 * 1e3 * Number(match[1] || "0") + 60 * 1e3 * Number(match[2]) + 1e3 * Number(match[3]) + Number(match[4]);
5193 };
5194 var formatSubtitleTimestamp = (timestamp) => {
5195 const hours = Math.floor(timestamp / (60 * 60 * 1e3));
5196 const minutes = Math.floor(timestamp % (60 * 60 * 1e3) / (60 * 1e3));
5197 const seconds = Math.floor(timestamp % (60 * 1e3) / 1e3);
5198 const milliseconds = timestamp % 1e3;
5199 return hours.toString().padStart(2, "0") + ":" + minutes.toString().padStart(2, "0") + ":" + seconds.toString().padStart(2, "0") + "." + milliseconds.toString().padStart(3, "0");
5200 };
5201
5202 // node_modules/mediabunny/dist/modules/src/isobmff/isobmff-boxes.js
5203 var IsobmffBoxWriter = class {
5204 constructor(writer) {
5205 this.writer = writer;
5206 this.helper = new Uint8Array(8);
5207 this.helperView = new DataView(this.helper.buffer);
5208 this.offsets = /* @__PURE__ */ new WeakMap();
5209 }
5210 writeU32(value) {
5211 this.helperView.setUint32(0, value, false);
5212 this.writer.write(this.helper.subarray(0, 4));
5213 }
5214 writeU64(value) {
5215 this.helperView.setUint32(0, Math.floor(value / 2 ** 32), false);
5216 this.helperView.setUint32(4, value, false);
5217 this.writer.write(this.helper.subarray(0, 8));
5218 }
5219 writeAscii(text) {
5220 for (let i2 = 0; i2 < text.length; i2++) {
5221 this.helperView.setUint8(i2 % 8, text.charCodeAt(i2));
5222 if (i2 % 8 === 7)
5223 this.writer.write(this.helper);
5224 }
5225 if (text.length % 8 !== 0) {
5226 this.writer.write(this.helper.subarray(0, text.length % 8));
5227 }
5228 }
5229 writeBox(box2) {
5230 this.offsets.set(box2, this.writer.getPos());
5231 if (box2.contents && !box2.children) {
5232 this.writeBoxHeader(box2, box2.size ?? box2.contents.byteLength + 8);
5233 this.writer.write(box2.contents);
5234 } else {
5235 const startPos = this.writer.getPos();
5236 this.writeBoxHeader(box2, 0);
5237 if (box2.contents)
5238 this.writer.write(box2.contents);
5239 if (box2.children) {
5240 for (const child of box2.children)
5241 if (child)
5242 this.writeBox(child);
5243 }
5244 const endPos = this.writer.getPos();
5245 const size = box2.size ?? endPos - startPos;
5246 this.writer.seek(startPos);
5247 this.writeBoxHeader(box2, size);
5248 this.writer.seek(endPos);
5249 }
5250 }
5251 writeBoxHeader(box2, size) {
5252 this.writeU32(box2.largeSize ? 1 : size);
5253 this.writeAscii(box2.type);
5254 if (box2.largeSize)
5255 this.writeU64(size);
5256 }
5257 measureBoxHeader(box2) {
5258 return 8 + (box2.largeSize ? 8 : 0);
5259 }
5260 patchBox(box2) {
5261 const boxOffset = this.offsets.get(box2);
5262 assert(boxOffset !== void 0);
5263 const endPos = this.writer.getPos();
5264 this.writer.seek(boxOffset);
5265 this.writeBox(box2);
5266 this.writer.seek(endPos);
5267 }
5268 measureBox(box2) {
5269 if (box2.contents && !box2.children) {
5270 const headerSize = this.measureBoxHeader(box2);
5271 return headerSize + box2.contents.byteLength;
5272 } else {
5273 let result = this.measureBoxHeader(box2);
5274 if (box2.contents)
5275 result += box2.contents.byteLength;
5276 if (box2.children) {
5277 for (const child of box2.children)
5278 if (child)
5279 result += this.measureBox(child);
5280 }
5281 return result;
5282 }
5283 }
5284 };
5285 var bytes = /* @__PURE__ */ new Uint8Array(8);
5286 var view = /* @__PURE__ */ new DataView(bytes.buffer);
5287 var u8 = (value) => {
5288 return [(value % 256 + 256) % 256];
5289 };
5290 var u16 = (value) => {
5291 view.setUint16(0, value, false);
5292 return [bytes[0], bytes[1]];
5293 };
5294 var i16 = (value) => {
5295 view.setInt16(0, value, false);
5296 return [bytes[0], bytes[1]];
5297 };
5298 var u24 = (value) => {
5299 view.setUint32(0, value, false);
5300 return [bytes[1], bytes[2], bytes[3]];
5301 };
5302 var u32 = (value) => {
5303 view.setUint32(0, value, false);
5304 return [bytes[0], bytes[1], bytes[2], bytes[3]];
5305 };
5306 var i32 = (value) => {
5307 view.setInt32(0, value, false);
5308 return [bytes[0], bytes[1], bytes[2], bytes[3]];
5309 };
5310 var u64 = (value) => {
5311 view.setUint32(0, Math.floor(value / 2 ** 32), false);
5312 view.setUint32(4, value, false);
5313 return [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]];
5314 };
5315 var i64 = (value) => {
5316 view.setInt32(0, Math.floor(value / 2 ** 32), false);
5317 view.setUint32(4, value, false);
5318 return [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]];
5319 };
5320 var fixed_8_8 = (value) => {
5321 view.setInt16(0, 2 ** 8 * value, false);
5322 return [bytes[0], bytes[1]];
5323 };
5324 var fixed_16_16 = (value) => {
5325 view.setInt32(0, 2 ** 16 * value, false);
5326 return [bytes[0], bytes[1], bytes[2], bytes[3]];
5327 };
5328 var fixed_2_30 = (value) => {
5329 view.setInt32(0, 2 ** 30 * value, false);
5330 return [bytes[0], bytes[1], bytes[2], bytes[3]];
5331 };
5332 var variableUnsignedInt = (value, byteLength) => {
5333 const bytes2 = [];
5334 let remaining = value;
5335 do {
5336 let byte = remaining & 127;
5337 remaining >>= 7;
5338 if (bytes2.length > 0) {
5339 byte |= 128;
5340 }
5341 bytes2.push(byte);
5342 if (byteLength !== void 0) {
5343 byteLength--;
5344 }
5345 } while (remaining > 0 || byteLength);
5346 return bytes2.reverse();
5347 };
5348 var ascii = (text, nullTerminated = false) => {
5349 const bytes2 = Array(text.length).fill(null).map((_2, i2) => text.charCodeAt(i2));
5350 if (nullTerminated)
5351 bytes2.push(0);
5352 return bytes2;
5353 };
5354 var rotationMatrix = (rotationInDegrees) => {
5355 const theta = rotationInDegrees * (Math.PI / 180);
5356 const cosTheta = Math.round(Math.cos(theta));
5357 const sinTheta = Math.round(Math.sin(theta));
5358 return [
5359 cosTheta,
5360 sinTheta,
5361 0,
5362 -sinTheta,
5363 cosTheta,
5364 0,
5365 0,
5366 0,
5367 1
5368 ];
5369 };
5370 var IDENTITY_MATRIX = /* @__PURE__ */ rotationMatrix(0);
5371 var matrixToBytes = (matrix) => {
5372 return [
5373 fixed_16_16(matrix[0]),
5374 fixed_16_16(matrix[1]),
5375 fixed_2_30(matrix[2]),
5376 fixed_16_16(matrix[3]),
5377 fixed_16_16(matrix[4]),
5378 fixed_2_30(matrix[5]),
5379 fixed_16_16(matrix[6]),
5380 fixed_16_16(matrix[7]),
5381 fixed_2_30(matrix[8])
5382 ];
5383 };
5384 var box = (type, contents, children) => ({
5385 type,
5386 contents: contents && new Uint8Array(contents.flat(10)),
5387 children
5388 });
5389 var fullBox = (type, version, flags, contents, children) => box(type, [u8(version), u24(flags), contents ?? []], children);
5390 var ftyp = (details) => {
5391 const minorVersion = 512;
5392 if (details.isQuickTime) {
5393 return box("ftyp", [
5394 ascii("qt "),
5395 // Major brand
5396 u32(minorVersion),
5397 // Minor version
5398 // Compatible brands
5399 ascii("qt ")
5400 ]);
5401 }
5402 if (details.fragmented) {
5403 if (details.cmaf) {
5404 return box("ftyp", [
5405 ascii("iso5"),
5406 // Major brand
5407 u32(minorVersion),
5408 // Minor version
5409 // Compatible brands
5410 ascii("iso5"),
5411 ascii("iso6"),
5412 ascii("mp41"),
5413 ascii("cmfc"),
5414 ascii("dash")
5415 ]);
5416 } else {
5417 return box("ftyp", [
5418 ascii("iso5"),
5419 // Major brand
5420 u32(minorVersion),
5421 // Minor version
5422 // Compatible brands
5423 ascii("iso5"),
5424 ascii("iso6"),
5425 ascii("mp41")
5426 ]);
5427 }
5428 }
5429 return box("ftyp", [
5430 ascii("isom"),
5431 // Major brand
5432 u32(minorVersion),
5433 // Minor version
5434 // Compatible brands
5435 ascii("isom"),
5436 details.holdsAvc ? ascii("avc1") : [],
5437 ascii("mp41")
5438 ]);
5439 };
5440 var styp = () => box("styp", [
5441 ascii("iso5"),
5442 // Major brand
5443 u32(0),
5444 // Minor version
5445 // Compatible brands
5446 ascii("iso5"),
5447 ascii("iso6"),
5448 ascii("mp41"),
5449 ascii("cmfc"),
5450 ascii("dash")
5451 ]);
5452 var sidx = (muxer, referencedSize) => {
5453 let duration = muxer.maxWrittenEndTimestamp - muxer.minWrittenTimestamp;
5454 if (!Number.isFinite(duration)) {
5455 duration = 0;
5456 }
5457 return fullBox("sidx", 1, 0, [
5458 u32(1),
5459 // Reference ID
5460 u32(GLOBAL_TIMESCALE),
5461 // Timescale
5462 u64(intoTimescale(muxer.minWrittenTimestamp, GLOBAL_TIMESCALE)),
5463 // Earliest presentation time
5464 u64(0),
5465 // First offset
5466 u16(0),
5467 // Reserved
5468 u16(1),
5469 // Reference count
5470 u32(referencedSize & 2147483647),
5471 // Reference type (0) + referenced size
5472 u32(intoTimescale(duration, GLOBAL_TIMESCALE)),
5473 // Subsegment duration
5474 u32(0)
5475 // Starts with SAP + SAP type + SAP delta time (no information provided)
5476 ]);
5477 };
5478 var mdat = (reserveLargeSize) => ({ type: "mdat", largeSize: reserveLargeSize });
5479 var free = (size) => ({ type: "free", size });
5480 var moov = (muxer) => {
5481 return box("moov", void 0, [
5482 mvhd(muxer.creationTime, muxer.trackDatas),
5483 ...muxer.trackDatas.map((x) => trak(x, muxer.creationTime)),
5484 muxer.isFragmented ? mvex(muxer.trackDatas) : null,
5485 udta(muxer)
5486 ]);
5487 };
5488 var mvhd = (creationTime, trackDatas) => {
5489 const duration = Math.max(0, ...trackDatas.map((trackData) => intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(trackData.startTimestampOffset ?? 0, GLOBAL_TIMESCALE)));
5490 const nextTrackId = Math.max(0, ...trackDatas.map((x) => x.track.id)) + 1;
5491 const needsU64 = !isU32(creationTime) || !isU32(duration);
5492 const u32OrU64 = needsU64 ? u64 : u32;
5493 return fullBox("mvhd", +needsU64, 0, [
5494 u32OrU64(creationTime),
5495 // Creation time
5496 u32OrU64(creationTime),
5497 // Modification time
5498 u32(GLOBAL_TIMESCALE),
5499 // Timescale
5500 u32OrU64(duration),
5501 // Duration
5502 fixed_16_16(1),
5503 // Preferred rate
5504 fixed_8_8(1),
5505 // Preferred volume
5506 Array(10).fill(0),
5507 // Reserved
5508 matrixToBytes(IDENTITY_MATRIX),
5509 // Matrix
5510 Array(24).fill(0),
5511 // Pre-defined
5512 u32(nextTrackId)
5513 // Next track ID
5514 ]);
5515 };
5516 var presentationSpan = (trackData) => {
5517 if (trackData.samples.length === 0) {
5518 return 0;
5519 }
5520 let minTimestamp = Infinity;
5521 let maxEndTimestamp = -Infinity;
5522 for (let i2 = 0; i2 < trackData.samples.length; i2++) {
5523 const sample = trackData.samples[i2];
5524 if (sample.timestamp < minTimestamp) {
5525 minTimestamp = sample.timestamp;
5526 }
5527 if (sample.timestamp + sample.duration > maxEndTimestamp) {
5528 maxEndTimestamp = sample.timestamp + sample.duration;
5529 }
5530 }
5531 if (minTimestamp === Infinity) {
5532 return 0;
5533 }
5534 return maxEndTimestamp - minTimestamp;
5535 };
5536 var trak = (trackData, creationTime) => {
5537 const trackMetadata = getTrackMetadata(trackData);
5538 const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset > 0;
5539 return box("trak", void 0, [
5540 tkhd(trackData, creationTime),
5541 needsEditList ? edts(trackData, trackData.startTimestampOffset) : null,
5542 mdia(trackData, creationTime),
5543 trackMetadata.name !== void 0 ? box("udta", void 0, [
5544 box("name", [
5545 ...textEncoder.encode(trackMetadata.name)
5546 ])
5547 ]) : null
5548 ]);
5549 };
5550 var tkhd = (trackData, creationTime) => {
5551 const durationInGlobalTimescale = intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(trackData.startTimestampOffset ?? 0, GLOBAL_TIMESCALE);
5552 const needsU64 = !isU32(creationTime) || !isU32(durationInGlobalTimescale);
5553 const u32OrU64 = needsU64 ? u64 : u32;
5554 let matrix;
5555 if (trackData.type === "video") {
5556 const rotation = trackData.track.metadata.rotation;
5557 matrix = rotationMatrix(rotation ?? 0);
5558 } else {
5559 matrix = IDENTITY_MATRIX;
5560 }
5561 let flags = 2;
5562 if (trackData.track.metadata.disposition?.default !== false) {
5563 flags |= 1;
5564 }
5565 return fullBox("tkhd", +needsU64, flags, [
5566 u32OrU64(creationTime),
5567 // Creation time
5568 u32OrU64(creationTime),
5569 // Modification time
5570 u32(trackData.track.id),
5571 // Track ID
5572 u32(0),
5573 // Reserved
5574 u32OrU64(durationInGlobalTimescale),
5575 // Duration
5576 Array(8).fill(0),
5577 // Reserved
5578 u16(0),
5579 // Layer
5580 u16(trackData.track.id),
5581 // Alternate group
5582 fixed_8_8(trackData.type === "audio" ? 1 : 0),
5583 // Volume
5584 u16(0),
5585 // Reserved
5586 matrixToBytes(matrix),
5587 // Matrix
5588 fixed_16_16(trackData.type === "video" ? trackData.info.width : 0),
5589 // Track width
5590 fixed_16_16(trackData.type === "video" ? trackData.info.height : 0)
5591 // Track height
5592 ]);
5593 };
5594 var edts = (trackData, offset) => {
5595 const startOffset = intoTimescale(offset, GLOBAL_TIMESCALE);
5596 const mediaDuration = intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE);
5597 const needs64Bits = !isU32(startOffset) || !isU32(mediaDuration);
5598 const u32OrU64 = needs64Bits ? u64 : u32;
5599 const i32OrI64 = needs64Bits ? i64 : i32;
5600 return box("edts", void 0, [
5601 fullBox("elst", needs64Bits ? 1 : 0, 0, [
5602 u32(2),
5603 // Entry count
5604 // #1
5605 u32OrU64(startOffset),
5606 // Segment duration
5607 i32OrI64(-1),
5608 // Media time
5609 fixed_16_16(1),
5610 // Media rate
5611 // #2
5612 u32OrU64(mediaDuration),
5613 // Segment duration
5614 i32OrI64(0),
5615 // Media time
5616 fixed_16_16(1)
5617 // Media rate
5618 ])
5619 ]);
5620 };
5621 var mdia = (trackData, creationTime) => box("mdia", void 0, [
5622 mdhd(trackData, creationTime),
5623 hdlr(true, TRACK_TYPE_TO_COMPONENT_SUBTYPE[trackData.type], TRACK_TYPE_TO_HANDLER_NAME[trackData.type]),
5624 minf(trackData)
5625 ]);
5626 var mdhd = (trackData, creationTime) => {
5627 const localDuration = intoTimescale(presentationSpan(trackData), trackData.timescale);
5628 const needsU64 = !isU32(creationTime) || !isU32(localDuration);
5629 const u32OrU64 = needsU64 ? u64 : u32;
5630 return fullBox("mdhd", +needsU64, 0, [
5631 u32OrU64(creationTime),
5632 // Creation time
5633 u32OrU64(creationTime),
5634 // Modification time
5635 u32(trackData.timescale),
5636 // Timescale
5637 u32OrU64(localDuration),
5638 // Duration
5639 u16(getLanguageCodeInt(trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE)),
5640 // Language
5641 u16(0)
5642 // Quality
5643 ]);
5644 };
5645 var TRACK_TYPE_TO_COMPONENT_SUBTYPE = {
5646 video: "vide",
5647 audio: "soun",
5648 subtitle: "text"
5649 };
5650 var TRACK_TYPE_TO_HANDLER_NAME = {
5651 video: "MediabunnyVideoHandler",
5652 audio: "MediabunnySoundHandler",
5653 subtitle: "MediabunnyTextHandler"
5654 };
5655 var hdlr = (hasComponentType, handlerType, name, manufacturer = "\\0\\0\\0\\0") => fullBox("hdlr", 0, 0, [
5656 hasComponentType ? ascii("mhlr") : u32(0),
5657 // Component type
5658 ascii(handlerType),
5659 // Component subtype
5660 ascii(manufacturer),
5661 // Component manufacturer
5662 u32(0),
5663 // Component flags
5664 u32(0),
5665 // Component flags mask
5666 ascii(name, true)
5667 // Component name
5668 ]);
5669 var minf = (trackData) => box("minf", void 0, [
5670 TRACK_TYPE_TO_HEADER_BOX[trackData.type](),
5671 dinf(),
5672 stbl(trackData)
5673 ]);
5674 var vmhd = () => fullBox("vmhd", 0, 1, [
5675 u16(0),
5676 // Graphics mode
5677 u16(0),
5678 // Opcolor R
5679 u16(0),
5680 // Opcolor G
5681 u16(0)
5682 // Opcolor B
5683 ]);
5684 var smhd = () => fullBox("smhd", 0, 0, [
5685 u16(0),
5686 // Balance
5687 u16(0)
5688 // Reserved
5689 ]);
5690 var nmhd = () => fullBox("nmhd", 0, 0);
5691 var TRACK_TYPE_TO_HEADER_BOX = {
5692 video: vmhd,
5693 audio: smhd,
5694 subtitle: nmhd
5695 };
5696 var dinf = () => box("dinf", void 0, [
5697 dref()
5698 ]);
5699 var dref = () => fullBox("dref", 0, 0, [
5700 u32(1)
5701 // Entry count
5702 ], [
5703 url()
5704 ]);
5705 var url = () => fullBox("url ", 0, 1);
5706 var stbl = (trackData) => {
5707 const needsCtts = trackData.compositionTimeOffsetTable.length > 1 || trackData.compositionTimeOffsetTable.some((x) => x.sampleCompositionTimeOffset !== 0);
5708 return box("stbl", void 0, [
5709 stsd(trackData),
5710 stts(trackData),
5711 needsCtts ? ctts(trackData) : null,
5712 needsCtts ? cslg(trackData) : null,
5713 stsc(trackData),
5714 stsz(trackData),
5715 stco(trackData),
5716 stss(trackData)
5717 ]);
5718 };
5719 var stsd = (trackData) => {
5720 let sampleDescription;
5721 if (trackData.type === "video") {
5722 sampleDescription = videoSampleDescription(videoCodecToBoxName(trackData.track.source._codec, trackData.info.decoderConfig.codec), trackData);
5723 } else if (trackData.type === "audio") {
5724 const boxName = audioCodecToBoxName(trackData.track.source._codec, trackData.muxer.isQuickTime);
5725 assert(boxName);
5726 sampleDescription = soundSampleDescription(boxName, trackData);
5727 } else if (trackData.type === "subtitle") {
5728 sampleDescription = subtitleSampleDescription(SUBTITLE_CODEC_TO_BOX_NAME[trackData.track.source._codec], trackData);
5729 }
5730 assert(sampleDescription);
5731 return fullBox("stsd", 0, 0, [
5732 u32(1)
5733 // Entry count
5734 ], [
5735 sampleDescription
5736 ]);
5737 };
5738 var videoSampleDescription = (compressionType, trackData) => box(compressionType, [
5739 Array(6).fill(0),
5740 // Reserved
5741 u16(1),
5742 // Data reference index
5743 u16(0),
5744 // Pre-defined
5745 u16(0),
5746 // Reserved
5747 Array(12).fill(0),
5748 // Pre-defined
5749 u16(trackData.info.width),
5750 // Width
5751 u16(trackData.info.height),
5752 // Height
5753 u32(4718592),
5754 // Horizontal resolution
5755 u32(4718592),
5756 // Vertical resolution
5757 u32(0),
5758 // Reserved
5759 u16(1),
5760 // Frame count
5761 Array(32).fill(0),
5762 // Compressor name
5763 u16(24),
5764 // Depth
5765 i16(65535)
5766 // Pre-defined
5767 ], [
5768 VIDEO_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData),
5769 pasp(trackData),
5770 colorSpaceIsComplete(trackData.info.decoderConfig.colorSpace) ? colr(trackData) : null
5771 ]);
5772 var pasp = (trackData) => {
5773 if (trackData.info.pixelAspectRatio.num === trackData.info.pixelAspectRatio.den) {
5774 return null;
5775 }
5776 return box("pasp", [
5777 u32(trackData.info.pixelAspectRatio.num),
5778 u32(trackData.info.pixelAspectRatio.den)
5779 ]);
5780 };
5781 var colr = (trackData) => box("colr", [
5782 ascii(trackData.muxer.isQuickTime ? "nclc" : "nclx"),
5783 // Colour type
5784 u16(COLOR_PRIMARIES_MAP[trackData.info.decoderConfig.colorSpace.primaries]),
5785 // Colour primaries
5786 u16(TRANSFER_CHARACTERISTICS_MAP[trackData.info.decoderConfig.colorSpace.transfer]),
5787 // Transfer characteristics
5788 u16(MATRIX_COEFFICIENTS_MAP[trackData.info.decoderConfig.colorSpace.matrix]),
5789 // Matrix coefficients
5790 trackData.muxer.isQuickTime ? [] : u8((trackData.info.decoderConfig.colorSpace.fullRange ? 1 : 0) << 7)
5791 // Full range flag
5792 ]);
5793 var avcC = (trackData) => trackData.info.decoderConfig && box("avcC", [
5794 // For AVC, description is an AVCDecoderConfigurationRecord, so nothing else to do here
5795 ...toUint8Array(trackData.info.decoderConfig.description)
5796 ]);
5797 var hvcC = (trackData) => trackData.info.decoderConfig && box("hvcC", [
5798 // For HEVC, description is an HEVCDecoderConfigurationRecord, so nothing else to do here
5799 ...toUint8Array(trackData.info.decoderConfig.description)
5800 ]);
5801 var vpcC = (trackData) => {
5802 if (!trackData.info.decoderConfig) {
5803 return null;
5804 }
5805 const decoderConfig = trackData.info.decoderConfig;
5806 const parts = decoderConfig.codec.split(".");
5807 const profile = Number(parts[1]);
5808 const level = Number(parts[2]);
5809 const bitDepth = Number(parts[3]);
5810 const chromaSubsampling = parts[4] ? Number(parts[4]) : 1;
5811 const videoFullRangeFlag = parts[8] ? Number(parts[8]) : Number(decoderConfig.colorSpace?.fullRange ?? 0);
5812 const thirdByte = (bitDepth << 4) + (chromaSubsampling << 1) + videoFullRangeFlag;
5813 const colourPrimaries = parts[5] ? Number(parts[5]) : decoderConfig.colorSpace?.primaries ? COLOR_PRIMARIES_MAP[decoderConfig.colorSpace.primaries] : 2;
5814 const transferCharacteristics = parts[6] ? Number(parts[6]) : decoderConfig.colorSpace?.transfer ? TRANSFER_CHARACTERISTICS_MAP[decoderConfig.colorSpace.transfer] : 2;
5815 const matrixCoefficients = parts[7] ? Number(parts[7]) : decoderConfig.colorSpace?.matrix ? MATRIX_COEFFICIENTS_MAP[decoderConfig.colorSpace.matrix] : 2;
5816 return fullBox("vpcC", 1, 0, [
5817 u8(profile),
5818 // Profile
5819 u8(level),
5820 // Level
5821 u8(thirdByte),
5822 // Bit depth, chroma subsampling, full range
5823 u8(colourPrimaries),
5824 // Colour primaries
5825 u8(transferCharacteristics),
5826 // Transfer characteristics
5827 u8(matrixCoefficients),
5828 // Matrix coefficients
5829 u16(0)
5830 // Codec initialization data size
5831 ]);
5832 };
5833 var av1C = (trackData) => {
5834 return box("av1C", generateAv1CodecConfigurationFromCodecString(trackData.info.decoderConfig.codec));
5835 };
5836 var soundSampleDescription = (compressionType, trackData) => {
5837 let version = 0;
5838 let contents;
5839 let sampleSizeInBits = 16;
5840 const isPcmCodec = PCM_AUDIO_CODECS.includes(trackData.track.source._codec);
5841 if (isPcmCodec) {
5842 const codec = trackData.track.source._codec;
5843 const { sampleSize } = parsePcmCodec(codec);
5844 sampleSizeInBits = 8 * sampleSize;
5845 if (sampleSizeInBits > 16) {
5846 version = 1;
5847 }
5848 }
5849 if (trackData.muxer.isQuickTime) {
5850 version = 1;
5851 }
5852 if (version === 0) {
5853 contents = [
5854 Array(6).fill(0),
5855 // Reserved
5856 u16(1),
5857 // Data reference index
5858 u16(version),
5859 // Version
5860 u16(0),
5861 // Revision level
5862 u32(0),
5863 // Vendor
5864 u16(trackData.info.numberOfChannels),
5865 // Number of channels
5866 u16(sampleSizeInBits),
5867 // Sample size (bits)
5868 u16(0),
5869 // Compression ID
5870 u16(0),
5871 // Packet size
5872 u16(trackData.info.sampleRate < 2 ** 16 ? trackData.info.sampleRate : 0),
5873 // Sample rate (upper)
5874 u16(0)
5875 // Sample rate (lower)
5876 ];
5877 } else {
5878 const compressionId = isPcmCodec ? 0 : -2;
5879 contents = [
5880 Array(6).fill(0),
5881 // Reserved
5882 u16(1),
5883 // Data reference index
5884 u16(version),
5885 // Version
5886 u16(0),
5887 // Revision level
5888 u32(0),
5889 // Vendor
5890 u16(trackData.info.numberOfChannels),
5891 // Number of channels
5892 u16(Math.min(sampleSizeInBits, 16)),
5893 // Sample size (bits)
5894 i16(compressionId),
5895 // Compression ID
5896 u16(0),
5897 // Packet size
5898 u16(trackData.info.sampleRate < 2 ** 16 ? trackData.info.sampleRate : 0),
5899 // Sample rate (upper)
5900 u16(0),
5901 // Sample rate (lower)
5902 isPcmCodec ? [
5903 u32(1),
5904 // Samples per packet (must be 1 for uncompressed formats)
5905 u32(sampleSizeInBits / 8),
5906 // Bytes per packet
5907 u32(trackData.info.numberOfChannels * sampleSizeInBits / 8)
5908 // Bytes per frame
5909 ] : [
5910 u32(0),
5911 // Samples per packet (don't bother, still works with 0)
5912 u32(0),
5913 // Bytes per packet (variable)
5914 u32(0)
5915 // Bytes per frame (variable)
5916 ],
5917 u32(2)
5918 // Bytes per sample (constant in FFmpeg)
5919 ];
5920 }
5921 return box(compressionType, contents, [
5922 audioCodecToConfigurationBox(trackData.track.source._codec, trackData.muxer.isQuickTime)?.(trackData) ?? null
5923 ]);
5924 };
5925 var esds = (trackData) => {
5926 let objectTypeIndication;
5927 switch (trackData.track.source._codec) {
5928 case "aac":
5929 {
5930 objectTypeIndication = 64;
5931 }
5932 ;
5933 break;
5934 case "mp3":
5935 {
5936 objectTypeIndication = 107;
5937 }
5938 ;
5939 break;
5940 case "vorbis":
5941 {
5942 objectTypeIndication = 221;
5943 }
5944 ;
5945 break;
5946 default:
5947 throw new Error(\`Unhandled audio codec: \${trackData.track.source._codec}\`);
5948 }
5949 let bytes2 = [
5950 ...u8(objectTypeIndication),
5951 // Object type indication
5952 ...u8(21),
5953 // stream type(6bits)=5 audio, flags(2bits)=1
5954 ...u24(0),
5955 // 24bit buffer size
5956 ...u32(0),
5957 // max bitrate
5958 ...u32(0)
5959 // avg bitrate
5960 ];
5961 if (trackData.info.decoderConfig.description) {
5962 const description = toUint8Array(trackData.info.decoderConfig.description);
5963 bytes2 = [
5964 ...bytes2,
5965 ...u8(5),
5966 // TAG(5) = DecoderSpecificInfo
5967 ...variableUnsignedInt(description.byteLength),
5968 ...description
5969 ];
5970 }
5971 bytes2 = [
5972 ...u16(1),
5973 // ES_ID = 1
5974 ...u8(0),
5975 // flags etc = 0
5976 ...u8(4),
5977 // TAG(4) = ES Descriptor
5978 ...variableUnsignedInt(bytes2.length),
5979 ...bytes2,
5980 ...u8(6),
5981 // TAG(6)
5982 ...u8(1),
5983 // length
5984 ...u8(2)
5985 // data
5986 ];
5987 bytes2 = [
5988 ...u8(3),
5989 // TAG(3) = Object Descriptor
5990 ...variableUnsignedInt(bytes2.length),
5991 ...bytes2
5992 ];
5993 return fullBox("esds", 0, 0, bytes2);
5994 };
5995 var wave = (trackData) => {
5996 return box("wave", void 0, [
5997 frma(trackData),
5998 enda(trackData),
5999 box("\\0\\0\\0\\0")
6000 // NULL tag at the end
6001 ]);
6002 };
6003 var frma = (trackData) => {
6004 return box("frma", [
6005 ascii(audioCodecToBoxName(trackData.track.source._codec, trackData.muxer.isQuickTime))
6006 ]);
6007 };
6008 var enda = (trackData) => {
6009 const { littleEndian } = parsePcmCodec(trackData.track.source._codec);
6010 return box("enda", [
6011 u16(+littleEndian)
6012 ]);
6013 };
6014 var dOps = (trackData) => {
6015 let outputChannelCount = trackData.info.numberOfChannels;
6016 let preSkip = 3840;
6017 let inputSampleRate = trackData.info.sampleRate;
6018 let outputGain = 0;
6019 let channelMappingFamily = 0;
6020 let channelMappingTable = new Uint8Array(0);
6021 const description = trackData.info.decoderConfig?.description;
6022 if (description) {
6023 assert(description.byteLength >= 18);
6024 const bytes2 = toUint8Array(description);
6025 const header = parseOpusIdentificationHeader(bytes2);
6026 outputChannelCount = header.outputChannelCount;
6027 preSkip = header.preSkip;
6028 inputSampleRate = header.inputSampleRate;
6029 outputGain = header.outputGain;
6030 channelMappingFamily = header.channelMappingFamily;
6031 if (header.channelMappingTable) {
6032 channelMappingTable = header.channelMappingTable;
6033 }
6034 }
6035 return box("dOps", [
6036 u8(0),
6037 // Version
6038 u8(outputChannelCount),
6039 // OutputChannelCount
6040 u16(preSkip),
6041 // PreSkip
6042 u32(inputSampleRate),
6043 // InputSampleRate
6044 i16(outputGain),
6045 // OutputGain
6046 u8(channelMappingFamily),
6047 // ChannelMappingFamily
6048 ...channelMappingTable
6049 ]);
6050 };
6051 var dfLa = (trackData) => {
6052 const description = trackData.info.decoderConfig?.description;
6053 assert(description);
6054 const bytes2 = toUint8Array(description);
6055 return fullBox("dfLa", 0, 0, [
6056 ...bytes2.subarray(4)
6057 ]);
6058 };
6059 var pcmC = (trackData) => {
6060 const { littleEndian, sampleSize } = parsePcmCodec(trackData.track.source._codec);
6061 const formatFlags = +littleEndian;
6062 return fullBox("pcmC", 0, 0, [
6063 u8(formatFlags),
6064 u8(8 * sampleSize)
6065 ]);
6066 };
6067 var dac3 = (trackData) => {
6068 const frameInfo = parseAc3SyncFrame(trackData.info.firstPacket.data);
6069 if (!frameInfo) {
6070 throw new Error("Couldn't extract AC-3 frame info from the audio packet. Ensure the packets contain valid AC-3 sync frames (as specified in ETSI TS 102 366).");
6071 }
6072 const bytes2 = new Uint8Array(3);
6073 const bitstream = new Bitstream(bytes2);
6074 bitstream.writeBits(2, frameInfo.fscod);
6075 bitstream.writeBits(5, frameInfo.bsid);
6076 bitstream.writeBits(3, frameInfo.bsmod);
6077 bitstream.writeBits(3, frameInfo.acmod);
6078 bitstream.writeBits(1, frameInfo.lfeon);
6079 bitstream.writeBits(5, frameInfo.bitRateCode);
6080 bitstream.writeBits(5, 0);
6081 return box("dac3", [...bytes2]);
6082 };
6083 var dec3 = (trackData) => {
6084 const frameInfo = parseEac3SyncFrame(trackData.info.firstPacket.data);
6085 if (!frameInfo) {
6086 throw new Error("Couldn't extract E-AC-3 frame info from the audio packet. Ensure the packets contain valid E-AC-3 sync frames (as specified in ETSI TS 102 366).");
6087 }
6088 let totalBits = 16;
6089 for (const sub of frameInfo.substreams) {
6090 totalBits += 23;
6091 if (sub.numDepSub > 0) {
6092 totalBits += 9;
6093 } else {
6094 totalBits += 1;
6095 }
6096 }
6097 const size = Math.ceil(totalBits / 8);
6098 const bytes2 = new Uint8Array(size);
6099 const bitstream = new Bitstream(bytes2);
6100 bitstream.writeBits(13, frameInfo.dataRate);
6101 bitstream.writeBits(3, frameInfo.substreams.length - 1);
6102 for (const sub of frameInfo.substreams) {
6103 bitstream.writeBits(2, sub.fscod);
6104 bitstream.writeBits(5, sub.bsid);
6105 bitstream.writeBits(1, 0);
6106 bitstream.writeBits(1, 0);
6107 bitstream.writeBits(3, sub.bsmod);
6108 bitstream.writeBits(3, sub.acmod);
6109 bitstream.writeBits(1, sub.lfeon);
6110 bitstream.writeBits(3, 0);
6111 bitstream.writeBits(4, sub.numDepSub);
6112 if (sub.numDepSub > 0) {
6113 bitstream.writeBits(9, sub.chanLoc);
6114 } else {
6115 bitstream.writeBits(1, 0);
6116 }
6117 }
6118 return box("dec3", [...bytes2]);
6119 };
6120 var subtitleSampleDescription = (compressionType, trackData) => box(compressionType, [
6121 Array(6).fill(0),
6122 // Reserved
6123 u16(1)
6124 // Data reference index
6125 ], [
6126 SUBTITLE_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData)
6127 ]);
6128 var vttC = (trackData) => box("vttC", [
6129 ...textEncoder.encode(trackData.info.config.description)
6130 ]);
6131 var stts = (trackData) => {
6132 return fullBox("stts", 0, 0, [
6133 u32(trackData.timeToSampleTable.length),
6134 // Number of entries
6135 trackData.timeToSampleTable.map((x) => [
6136 u32(x.sampleCount),
6137 // Sample count
6138 u32(x.sampleDelta)
6139 // Sample duration
6140 ])
6141 ]);
6142 };
6143 var stss = (trackData) => {
6144 if (trackData.samples.every((x) => x.type === "key"))
6145 return null;
6146 const keySamples = [...trackData.samples.entries()].filter(([, sample]) => sample.type === "key");
6147 return fullBox("stss", 0, 0, [
6148 u32(keySamples.length),
6149 // Number of entries
6150 keySamples.map(([index]) => u32(index + 1))
6151 // Sync sample table
6152 ]);
6153 };
6154 var stsc = (trackData) => {
6155 return fullBox("stsc", 0, 0, [
6156 u32(trackData.compactlyCodedChunkTable.length),
6157 // Number of entries
6158 trackData.compactlyCodedChunkTable.map((x) => [
6159 u32(x.firstChunk),
6160 // First chunk
6161 u32(x.samplesPerChunk),
6162 // Samples per chunk
6163 u32(1)
6164 // Sample description index
6165 ])
6166 ]);
6167 };
6168 var stsz = (trackData) => {
6169 if (trackData.type === "audio" && trackData.info.requiresPcmTransformation) {
6170 const { sampleSize } = parsePcmCodec(trackData.track.source._codec);
6171 return fullBox("stsz", 0, 0, [
6172 u32(sampleSize * trackData.info.numberOfChannels),
6173 // Sample size
6174 u32(trackData.samples.reduce((acc, x) => acc + intoTimescale(x.duration, trackData.timescale), 0))
6175 ]);
6176 }
6177 return fullBox("stsz", 0, 0, [
6178 u32(0),
6179 // Sample size (0 means non-constant size)
6180 u32(trackData.samples.length),
6181 // Number of entries
6182 trackData.samples.map((x) => u32(x.size))
6183 // Sample size table
6184 ]);
6185 };
6186 var stco = (trackData) => {
6187 if (trackData.finalizedChunks.length > 0 && last(trackData.finalizedChunks).offset >= 2 ** 32) {
6188 return fullBox("co64", 0, 0, [
6189 u32(trackData.finalizedChunks.length),
6190 // Number of entries
6191 trackData.finalizedChunks.map((x) => u64(x.offset))
6192 // Chunk offset table
6193 ]);
6194 }
6195 return fullBox("stco", 0, 0, [
6196 u32(trackData.finalizedChunks.length),
6197 // Number of entries
6198 trackData.finalizedChunks.map((x) => u32(x.offset))
6199 // Chunk offset table
6200 ]);
6201 };
6202 var ctts = (trackData) => {
6203 return fullBox("ctts", 1, 0, [
6204 u32(trackData.compositionTimeOffsetTable.length),
6205 // Number of entries
6206 trackData.compositionTimeOffsetTable.map((x) => [
6207 u32(x.sampleCount),
6208 // Sample count
6209 i32(x.sampleCompositionTimeOffset)
6210 // Sample offset
6211 ])
6212 ]);
6213 };
6214 var cslg = (trackData) => {
6215 let leastDecodeToDisplayDelta = Infinity;
6216 let greatestDecodeToDisplayDelta = -Infinity;
6217 let compositionStartTime = Infinity;
6218 let compositionEndTime = -Infinity;
6219 assert(trackData.compositionTimeOffsetTable.length > 0);
6220 assert(trackData.samples.length > 0);
6221 for (let i2 = 0; i2 < trackData.compositionTimeOffsetTable.length; i2++) {
6222 const entry = trackData.compositionTimeOffsetTable[i2];
6223 leastDecodeToDisplayDelta = Math.min(leastDecodeToDisplayDelta, entry.sampleCompositionTimeOffset);
6224 greatestDecodeToDisplayDelta = Math.max(greatestDecodeToDisplayDelta, entry.sampleCompositionTimeOffset);
6225 }
6226 for (let i2 = 0; i2 < trackData.samples.length; i2++) {
6227 const sample = trackData.samples[i2];
6228 compositionStartTime = Math.min(compositionStartTime, intoTimescale(sample.timestamp, trackData.timescale));
6229 compositionEndTime = Math.max(compositionEndTime, intoTimescale(sample.timestamp + sample.duration, trackData.timescale));
6230 }
6231 const compositionToDtsShift = Math.max(-leastDecodeToDisplayDelta, 0);
6232 if (compositionEndTime >= 2 ** 31) {
6233 return null;
6234 }
6235 return fullBox("cslg", 0, 0, [
6236 i32(compositionToDtsShift),
6237 // Composition to DTS shift
6238 i32(leastDecodeToDisplayDelta),
6239 // Least decode to display delta
6240 i32(greatestDecodeToDisplayDelta),
6241 // Greatest decode to display delta
6242 i32(compositionStartTime),
6243 // Composition start time
6244 i32(compositionEndTime)
6245 // Composition end time
6246 ]);
6247 };
6248 var mvex = (trackDatas) => {
6249 return box("mvex", void 0, trackDatas.map(trex));
6250 };
6251 var trex = (trackData) => {
6252 return fullBox("trex", 0, 0, [
6253 u32(trackData.track.id),
6254 // Track ID
6255 u32(1),
6256 // Default sample description index
6257 u32(0),
6258 // Default sample duration
6259 u32(0),
6260 // Default sample size
6261 u32(0)
6262 // Default sample flags
6263 ]);
6264 };
6265 var moof = (sequenceNumber, trackDatas) => {
6266 return box("moof", void 0, [
6267 mfhd(sequenceNumber),
6268 ...trackDatas.map(traf)
6269 ]);
6270 };
6271 var mfhd = (sequenceNumber) => {
6272 return fullBox("mfhd", 0, 0, [
6273 u32(sequenceNumber)
6274 // Sequence number
6275 ]);
6276 };
6277 var fragmentSampleFlags = (sample) => {
6278 let byte1 = 0;
6279 let byte2 = 0;
6280 const byte3 = 0;
6281 const byte4 = 0;
6282 const sampleIsDifferenceSample = sample.type === "delta";
6283 byte2 |= +sampleIsDifferenceSample;
6284 if (sampleIsDifferenceSample) {
6285 byte1 |= 1;
6286 } else {
6287 byte1 |= 2;
6288 }
6289 return byte1 << 24 | byte2 << 16 | byte3 << 8 | byte4;
6290 };
6291 var traf = (trackData) => {
6292 return box("traf", void 0, [
6293 tfhd(trackData),
6294 tfdt(trackData),
6295 trun(trackData)
6296 ]);
6297 };
6298 var tfhd = (trackData) => {
6299 assert(trackData.currentChunk);
6300 let tfFlags = 0;
6301 tfFlags |= 8;
6302 tfFlags |= 16;
6303 tfFlags |= 32;
6304 tfFlags |= 131072;
6305 const referenceSample = trackData.currentChunk.samples[1] ?? trackData.currentChunk.samples[0];
6306 const referenceSampleInfo = {
6307 duration: referenceSample.timescaleUnitsToNextSample,
6308 size: referenceSample.size,
6309 flags: fragmentSampleFlags(referenceSample)
6310 };
6311 return fullBox("tfhd", 0, tfFlags, [
6312 u32(trackData.track.id),
6313 // Track ID
6314 u32(referenceSampleInfo.duration),
6315 // Default sample duration
6316 u32(referenceSampleInfo.size),
6317 // Default sample size
6318 u32(referenceSampleInfo.flags)
6319 // Default sample flags
6320 ]);
6321 };
6322 var tfdt = (trackData) => {
6323 assert(trackData.currentChunk);
6324 return fullBox("tfdt", 1, 0, [
6325 u64(intoTimescale(trackData.currentChunk.startTimestamp, trackData.timescale))
6326 // Base Media Decode Time
6327 ]);
6328 };
6329 var trun = (trackData) => {
6330 assert(trackData.currentChunk);
6331 const allSampleDurations = trackData.currentChunk.samples.map((x) => x.timescaleUnitsToNextSample);
6332 const allSampleSizes = trackData.currentChunk.samples.map((x) => x.size);
6333 const allSampleFlags = trackData.currentChunk.samples.map(fragmentSampleFlags);
6334 const allSampleCompositionTimeOffsets = trackData.currentChunk.samples.map((x) => intoTimescale(x.timestamp - x.decodeTimestamp, trackData.timescale));
6335 const uniqueSampleDurations = new Set(allSampleDurations);
6336 const uniqueSampleSizes = new Set(allSampleSizes);
6337 const uniqueSampleFlags = new Set(allSampleFlags);
6338 const uniqueSampleCompositionTimeOffsets = new Set(allSampleCompositionTimeOffsets);
6339 const firstSampleFlagsPresent = uniqueSampleFlags.size === 2 && allSampleFlags[0] !== allSampleFlags[1];
6340 const sampleDurationPresent = uniqueSampleDurations.size > 1;
6341 const sampleSizePresent = uniqueSampleSizes.size > 1;
6342 const sampleFlagsPresent = !firstSampleFlagsPresent && uniqueSampleFlags.size > 1;
6343 const sampleCompositionTimeOffsetsPresent = uniqueSampleCompositionTimeOffsets.size > 1 || [...uniqueSampleCompositionTimeOffsets].some((x) => x !== 0);
6344 let flags = 0;
6345 flags |= 1;
6346 flags |= 4 * +firstSampleFlagsPresent;
6347 flags |= 256 * +sampleDurationPresent;
6348 flags |= 512 * +sampleSizePresent;
6349 flags |= 1024 * +sampleFlagsPresent;
6350 flags |= 2048 * +sampleCompositionTimeOffsetsPresent;
6351 return fullBox("trun", 1, flags, [
6352 u32(trackData.currentChunk.samples.length),
6353 // Sample count
6354 u32(trackData.currentChunk.offset - trackData.currentChunk.moofOffset || 0),
6355 // Data offset
6356 firstSampleFlagsPresent ? u32(allSampleFlags[0]) : [],
6357 trackData.currentChunk.samples.map((_2, i2) => [
6358 sampleDurationPresent ? u32(allSampleDurations[i2]) : [],
6359 // Sample duration
6360 sampleSizePresent ? u32(allSampleSizes[i2]) : [],
6361 // Sample size
6362 sampleFlagsPresent ? u32(allSampleFlags[i2]) : [],
6363 // Sample flags
6364 // Sample composition time offsets
6365 sampleCompositionTimeOffsetsPresent ? i32(allSampleCompositionTimeOffsets[i2]) : []
6366 ])
6367 ]);
6368 };
6369 var mfra = (trackDatas) => {
6370 return box("mfra", void 0, [
6371 ...trackDatas.map(tfra),
6372 mfro()
6373 ]);
6374 };
6375 var tfra = (trackData, trackIndex) => {
6376 const version = 1;
6377 return fullBox("tfra", version, 0, [
6378 u32(trackData.track.id),
6379 // Track ID
6380 u32(63),
6381 // This specifies that traf number, trun number and sample number are 32-bit ints
6382 u32(trackData.finalizedChunks.length),
6383 // Number of entries
6384 trackData.finalizedChunks.map((chunk) => [
6385 u64(intoTimescale(chunk.samples[0].timestamp, trackData.timescale)),
6386 // Time (in presentation time)
6387 u64(chunk.moofOffset),
6388 // moof offset
6389 u32(trackIndex + 1),
6390 // traf number
6391 u32(1),
6392 // trun number
6393 u32(1)
6394 // Sample number
6395 ])
6396 ]);
6397 };
6398 var mfro = () => {
6399 return fullBox("mfro", 0, 0, [
6400 // This value needs to be overwritten manually from the outside, where the actual size of the enclosing mfra box
6401 // is known
6402 u32(0)
6403 // Size
6404 ]);
6405 };
6406 var vtte = () => box("vtte");
6407 var vttc = (payload, timestamp, identifier, settings, sourceId) => box("vttc", void 0, [
6408 sourceId !== null ? box("vsid", [i32(sourceId)]) : null,
6409 identifier !== null ? box("iden", [...textEncoder.encode(identifier)]) : null,
6410 timestamp !== null ? box("ctim", [...textEncoder.encode(formatSubtitleTimestamp(timestamp))]) : null,
6411 settings !== null ? box("sttg", [...textEncoder.encode(settings)]) : null,
6412 box("payl", [...textEncoder.encode(payload)])
6413 ]);
6414 var vtta = (notes) => box("vtta", [...textEncoder.encode(notes)]);
6415 var udta = (muxer) => {
6416 const boxes = [];
6417 const metadataFormat = muxer.format._options.metadataFormat ?? "auto";
6418 const metadataTags = muxer.output._metadataTags;
6419 if (metadataFormat === "mdir" || metadataFormat === "auto" && !muxer.isQuickTime) {
6420 const metaBox = metaMdir(metadataTags);
6421 if (metaBox)
6422 boxes.push(metaBox);
6423 } else if (metadataFormat === "mdta") {
6424 const metaBox = metaMdta(metadataTags);
6425 if (metaBox)
6426 boxes.push(metaBox);
6427 } else if (metadataFormat === "udta" || metadataFormat === "auto" && muxer.isQuickTime) {
6428 addQuickTimeMetadataTagBoxes(boxes, muxer.output._metadataTags);
6429 }
6430 if (boxes.length === 0) {
6431 return null;
6432 }
6433 return box("udta", void 0, boxes);
6434 };
6435 var addQuickTimeMetadataTagBoxes = (boxes, tags) => {
6436 for (const { key, value } of keyValueIterator(tags)) {
6437 switch (key) {
6438 case "title":
6439 {
6440 boxes.push(metadataTagStringBoxShort("©nam", value));
6441 }
6442 ;
6443 break;
6444 case "description":
6445 {
6446 boxes.push(metadataTagStringBoxShort("©des", value));
6447 }
6448 ;
6449 break;
6450 case "artist":
6451 {
6452 boxes.push(metadataTagStringBoxShort("©ART", value));
6453 }
6454 ;
6455 break;
6456 case "album":
6457 {
6458 boxes.push(metadataTagStringBoxShort("©alb", value));
6459 }
6460 ;
6461 break;
6462 case "albumArtist":
6463 {
6464 boxes.push(metadataTagStringBoxShort("albr", value));
6465 }
6466 ;
6467 break;
6468 case "genre":
6469 {
6470 boxes.push(metadataTagStringBoxShort("©gen", value));
6471 }
6472 ;
6473 break;
6474 case "date":
6475 {
6476 boxes.push(metadataTagStringBoxShort("©day", value.toISOString().slice(0, 10)));
6477 }
6478 ;
6479 break;
6480 case "comment":
6481 {
6482 boxes.push(metadataTagStringBoxShort("©cmt", value));
6483 }
6484 ;
6485 break;
6486 case "lyrics":
6487 {
6488 boxes.push(metadataTagStringBoxShort("©lyr", value));
6489 }
6490 ;
6491 break;
6492 case "raw":
6493 {
6494 }
6495 ;
6496 break;
6497 case "discNumber":
6498 case "discsTotal":
6499 case "trackNumber":
6500 case "tracksTotal":
6501 case "images":
6502 {
6503 }
6504 ;
6505 break;
6506 default:
6507 assertNever(key);
6508 }
6509 }
6510 if (tags.raw) {
6511 for (const key in tags.raw) {
6512 const value = tags.raw[key];
6513 if (value == null || key.length !== 4 || boxes.some((x) => x.type === key)) {
6514 continue;
6515 }
6516 if (typeof value === "string") {
6517 boxes.push(metadataTagStringBoxShort(key, value));
6518 } else if (value instanceof Uint8Array) {
6519 boxes.push(box(key, Array.from(value)));
6520 }
6521 }
6522 }
6523 };
6524 var metadataTagStringBoxShort = (name, value) => {
6525 const encoded = textEncoder.encode(value);
6526 return box(name, [
6527 u16(encoded.length),
6528 u16(getLanguageCodeInt("und")),
6529 Array.from(encoded)
6530 ]);
6531 };
6532 var DATA_BOX_MIME_TYPE_MAP = {
6533 "image/jpeg": 13,
6534 "image/png": 14,
6535 "image/bmp": 27
6536 };
6537 var generateMetadataPairs = (tags, isMdta) => {
6538 const pairs = [];
6539 for (const { key, value } of keyValueIterator(tags)) {
6540 switch (key) {
6541 case "title":
6542 {
6543 pairs.push({ key: isMdta ? "title" : "©nam", value: dataStringBoxLong(value) });
6544 }
6545 ;
6546 break;
6547 case "description":
6548 {
6549 pairs.push({ key: isMdta ? "description" : "©des", value: dataStringBoxLong(value) });
6550 }
6551 ;
6552 break;
6553 case "artist":
6554 {
6555 pairs.push({ key: isMdta ? "artist" : "©ART", value: dataStringBoxLong(value) });
6556 }
6557 ;
6558 break;
6559 case "album":
6560 {
6561 pairs.push({ key: isMdta ? "album" : "©alb", value: dataStringBoxLong(value) });
6562 }
6563 ;
6564 break;
6565 case "albumArtist":
6566 {
6567 pairs.push({ key: isMdta ? "album_artist" : "aART", value: dataStringBoxLong(value) });
6568 }
6569 ;
6570 break;
6571 case "comment":
6572 {
6573 pairs.push({ key: isMdta ? "comment" : "©cmt", value: dataStringBoxLong(value) });
6574 }
6575 ;
6576 break;
6577 case "genre":
6578 {
6579 pairs.push({ key: isMdta ? "genre" : "©gen", value: dataStringBoxLong(value) });
6580 }
6581 ;
6582 break;
6583 case "lyrics":
6584 {
6585 pairs.push({ key: isMdta ? "lyrics" : "©lyr", value: dataStringBoxLong(value) });
6586 }
6587 ;
6588 break;
6589 case "date":
6590 {
6591 pairs.push({
6592 key: isMdta ? "date" : "©day",
6593 value: dataStringBoxLong(value.toISOString().slice(0, 10))
6594 });
6595 }
6596 ;
6597 break;
6598 case "images":
6599 {
6600 for (const image of value) {
6601 if (image.kind !== "coverFront") {
6602 continue;
6603 }
6604 pairs.push({ key: "covr", value: box("data", [
6605 u32(DATA_BOX_MIME_TYPE_MAP[image.mimeType] ?? 0),
6606 // Type indicator
6607 u32(0),
6608 // Locale indicator
6609 Array.from(image.data)
6610 // Kinda slow, hopefully temp
6611 ]) });
6612 }
6613 }
6614 ;
6615 break;
6616 case "trackNumber":
6617 {
6618 if (isMdta) {
6619 const string = tags.tracksTotal !== void 0 ? \`\${value}/\${tags.tracksTotal}\` : value.toString();
6620 pairs.push({ key: "track", value: dataStringBoxLong(string) });
6621 } else {
6622 pairs.push({ key: "trkn", value: box("data", [
6623 u32(0),
6624 // 8 bytes empty
6625 u32(0),
6626 u16(0),
6627 // Empty
6628 u16(value),
6629 u16(tags.tracksTotal ?? 0),
6630 u16(0)
6631 // Empty
6632 ]) });
6633 }
6634 }
6635 ;
6636 break;
6637 case "discNumber":
6638 {
6639 if (!isMdta) {
6640 pairs.push({ key: "disc", value: box("data", [
6641 u32(0),
6642 // 8 bytes empty
6643 u32(0),
6644 u16(0),
6645 // Empty
6646 u16(value),
6647 u16(tags.discsTotal ?? 0),
6648 u16(0)
6649 // Empty
6650 ]) });
6651 }
6652 }
6653 ;
6654 break;
6655 case "tracksTotal":
6656 case "discsTotal":
6657 {
6658 }
6659 ;
6660 break;
6661 case "raw":
6662 {
6663 }
6664 ;
6665 break;
6666 default:
6667 assertNever(key);
6668 }
6669 }
6670 if (tags.raw) {
6671 for (const key in tags.raw) {
6672 const value = tags.raw[key];
6673 if (value == null || !isMdta && key.length !== 4 || pairs.some((x) => x.key === key)) {
6674 continue;
6675 }
6676 if (typeof value === "string") {
6677 pairs.push({ key, value: dataStringBoxLong(value) });
6678 } else if (value instanceof Uint8Array) {
6679 pairs.push({ key, value: box("data", [
6680 u32(0),
6681 // Type indicator
6682 u32(0),
6683 // Locale indicator
6684 Array.from(value)
6685 ]) });
6686 } else if (value instanceof RichImageData) {
6687 pairs.push({ key, value: box("data", [
6688 u32(DATA_BOX_MIME_TYPE_MAP[value.mimeType] ?? 0),
6689 // Type indicator
6690 u32(0),
6691 // Locale indicator
6692 Array.from(value.data)
6693 // Kinda slow, hopefully temp
6694 ]) });
6695 }
6696 }
6697 }
6698 return pairs;
6699 };
6700 var metaMdir = (tags) => {
6701 const pairs = generateMetadataPairs(tags, false);
6702 if (pairs.length === 0) {
6703 return null;
6704 }
6705 return fullBox("meta", 0, 0, void 0, [
6706 hdlr(false, "mdir", "", "appl"),
6707 // mdir handler
6708 box("ilst", void 0, pairs.map((pair) => box(pair.key, void 0, [pair.value])))
6709 // Item list without keys box
6710 ]);
6711 };
6712 var metaMdta = (tags) => {
6713 const pairs = generateMetadataPairs(tags, true);
6714 if (pairs.length === 0) {
6715 return null;
6716 }
6717 return box("meta", void 0, [
6718 hdlr(false, "mdta", ""),
6719 // mdta handler
6720 fullBox("keys", 0, 0, [
6721 u32(pairs.length)
6722 ], pairs.map((pair) => box("mdta", [
6723 ...textEncoder.encode(pair.key)
6724 ]))),
6725 box("ilst", void 0, pairs.map((pair, i2) => {
6726 const boxName = String.fromCharCode(...u32(i2 + 1));
6727 return box(boxName, void 0, [pair.value]);
6728 }))
6729 ]);
6730 };
6731 var dataStringBoxLong = (value) => {
6732 return box("data", [
6733 u32(1),
6734 // Type indicator (UTF-8)
6735 u32(0),
6736 // Locale indicator
6737 ...textEncoder.encode(value)
6738 ]);
6739 };
6740 var videoCodecToBoxName = (codec, fullCodecString) => {
6741 switch (codec) {
6742 case "avc":
6743 return fullCodecString.startsWith("avc3") ? "avc3" : "avc1";
6744 case "hevc":
6745 return "hvc1";
6746 case "vp8":
6747 return "vp08";
6748 case "vp9":
6749 return "vp09";
6750 case "av1":
6751 return "av01";
6752 }
6753 };
6754 var VIDEO_CODEC_TO_CONFIGURATION_BOX = {
6755 avc: avcC,
6756 hevc: hvcC,
6757 vp8: vpcC,
6758 vp9: vpcC,
6759 av1: av1C
6760 };
6761 var audioCodecToBoxName = (codec, isQuickTime) => {
6762 switch (codec) {
6763 case "aac":
6764 return "mp4a";
6765 case "mp3":
6766 return "mp4a";
6767 case "opus":
6768 return "Opus";
6769 case "vorbis":
6770 return "mp4a";
6771 case "flac":
6772 return "fLaC";
6773 case "ulaw":
6774 return "ulaw";
6775 case "alaw":
6776 return "alaw";
6777 case "pcm-u8":
6778 return "raw ";
6779 case "pcm-s8":
6780 return "sowt";
6781 case "ac3":
6782 return "ac-3";
6783 case "eac3":
6784 return "ec-3";
6785 }
6786 if (isQuickTime) {
6787 switch (codec) {
6788 case "pcm-s16":
6789 return "sowt";
6790 case "pcm-s16be":
6791 return "twos";
6792 case "pcm-s24":
6793 return "in24";
6794 case "pcm-s24be":
6795 return "in24";
6796 case "pcm-s32":
6797 return "in32";
6798 case "pcm-s32be":
6799 return "in32";
6800 case "pcm-f32":
6801 return "fl32";
6802 case "pcm-f32be":
6803 return "fl32";
6804 case "pcm-f64":
6805 return "fl64";
6806 case "pcm-f64be":
6807 return "fl64";
6808 }
6809 } else {
6810 switch (codec) {
6811 case "pcm-s16":
6812 return "ipcm";
6813 case "pcm-s16be":
6814 return "ipcm";
6815 case "pcm-s24":
6816 return "ipcm";
6817 case "pcm-s24be":
6818 return "ipcm";
6819 case "pcm-s32":
6820 return "ipcm";
6821 case "pcm-s32be":
6822 return "ipcm";
6823 case "pcm-f32":
6824 return "fpcm";
6825 case "pcm-f32be":
6826 return "fpcm";
6827 case "pcm-f64":
6828 return "fpcm";
6829 case "pcm-f64be":
6830 return "fpcm";
6831 }
6832 }
6833 };
6834 var audioCodecToConfigurationBox = (codec, isQuickTime) => {
6835 switch (codec) {
6836 case "aac":
6837 return esds;
6838 case "mp3":
6839 return esds;
6840 case "opus":
6841 return dOps;
6842 case "vorbis":
6843 return esds;
6844 case "flac":
6845 return dfLa;
6846 case "ac3":
6847 return dac3;
6848 case "eac3":
6849 return dec3;
6850 }
6851 if (isQuickTime) {
6852 switch (codec) {
6853 case "pcm-s24":
6854 return wave;
6855 case "pcm-s24be":
6856 return wave;
6857 case "pcm-s32":
6858 return wave;
6859 case "pcm-s32be":
6860 return wave;
6861 case "pcm-f32":
6862 return wave;
6863 case "pcm-f32be":
6864 return wave;
6865 case "pcm-f64":
6866 return wave;
6867 case "pcm-f64be":
6868 return wave;
6869 }
6870 } else {
6871 switch (codec) {
6872 case "pcm-s16":
6873 return pcmC;
6874 case "pcm-s16be":
6875 return pcmC;
6876 case "pcm-s24":
6877 return pcmC;
6878 case "pcm-s24be":
6879 return pcmC;
6880 case "pcm-s32":
6881 return pcmC;
6882 case "pcm-s32be":
6883 return pcmC;
6884 case "pcm-f32":
6885 return pcmC;
6886 case "pcm-f32be":
6887 return pcmC;
6888 case "pcm-f64":
6889 return pcmC;
6890 case "pcm-f64be":
6891 return pcmC;
6892 }
6893 }
6894 return null;
6895 };
6896 var SUBTITLE_CODEC_TO_BOX_NAME = {
6897 webvtt: "wvtt"
6898 };
6899 var SUBTITLE_CODEC_TO_CONFIGURATION_BOX = {
6900 webvtt: vttC
6901 };
6902 var getLanguageCodeInt = (code) => {
6903 assert(code.length === 3);
6904 ;
6905 let language = 0;
6906 for (let i2 = 0; i2 < 3; i2++) {
6907 language <<= 5;
6908 language += code.charCodeAt(i2) - 96;
6909 }
6910 return language;
6911 };
6912
6913 // node_modules/mediabunny/dist/modules/src/writer.js
6914 var Writer = class {
6915 constructor(target, isMonotonic) {
6916 this.finalized = false;
6917 this.started = false;
6918 this.pos = 0;
6919 this.trackedWrites = null;
6920 this.trackedStart = -1;
6921 this.trackedEnd = -1;
6922 if (target._writerAcquired) {
6923 throw new Error("Can't have multiple Writers for the same Target.");
6924 }
6925 this.target = target;
6926 target._setMonotonicity(isMonotonic);
6927 target._writerAcquired = true;
6928 }
6929 start() {
6930 assert(!this.started);
6931 this.target._start();
6932 this.started = true;
6933 }
6934 /** Writes the given data to the target, at the current position. */
6935 write(data) {
6936 assert(this.started && !this.finalized);
6937 this.maybeTrackWrites(data);
6938 this.target._write(data, this.pos);
6939 this.pos += data.byteLength;
6940 }
6941 /** Sets the current position for future writes to a new one. */
6942 seek(newPos) {
6943 this.pos = newPos;
6944 }
6945 /** Returns the current position. */
6946 getPos() {
6947 return this.pos;
6948 }
6949 /** Signals to the writer that it may be time to flush. */
6950 async flush() {
6951 assert(this.started && !this.finalized);
6952 return this.target._flush();
6953 }
6954 /** Called after muxing has finished. */
6955 async finalize() {
6956 assert(this.started && !this.finalized);
6957 await this.target._finalize();
6958 this.finalized = true;
6959 }
6960 maybeTrackWrites(data) {
6961 if (!this.trackedWrites) {
6962 return;
6963 }
6964 let pos = this.getPos();
6965 if (pos < this.trackedStart) {
6966 if (pos + data.byteLength <= this.trackedStart) {
6967 return;
6968 }
6969 data = data.subarray(this.trackedStart - pos);
6970 pos = 0;
6971 }
6972 const neededSize = pos + data.byteLength - this.trackedStart;
6973 let newLength = this.trackedWrites.byteLength;
6974 while (newLength < neededSize) {
6975 newLength *= 2;
6976 }
6977 if (newLength !== this.trackedWrites.byteLength) {
6978 const copy = new Uint8Array(newLength);
6979 copy.set(this.trackedWrites, 0);
6980 this.trackedWrites = copy;
6981 }
6982 this.trackedWrites.set(data, pos - this.trackedStart);
6983 this.trackedEnd = Math.max(this.trackedEnd, pos + data.byteLength);
6984 }
6985 startTrackingWrites() {
6986 this.trackedWrites = new Uint8Array(2 ** 10);
6987 this.trackedStart = this.getPos();
6988 this.trackedEnd = this.trackedStart;
6989 }
6990 stopTrackingWrites() {
6991 if (!this.trackedWrites) {
6992 throw new Error("Internal error: Can't get tracked writes since nothing was tracked.");
6993 }
6994 const slice = this.trackedWrites.subarray(0, this.trackedEnd - this.trackedStart);
6995 const result = {
6996 data: slice,
6997 start: this.trackedStart,
6998 end: this.trackedEnd
6999 };
7000 this.trackedWrites = null;
7001 return result;
7002 }
7003 };
7004
7005 // node_modules/mediabunny/dist/modules/src/target.js
7006 var Target = class extends EventEmitter {
7007 constructor() {
7008 super(...arguments);
7009 this._writerAcquired = false;
7010 this._monotonicity = null;
7011 this.onwrite = null;
7012 }
7013 /** @internal */
7014 _setMonotonicity(monotonicity) {
7015 if (this._monotonicity !== false) {
7016 this._monotonicity = monotonicity;
7017 } else {
7018 }
7019 }
7020 /** @internal */
7021 _dispatchWrite(start, end) {
7022 this.onwrite?.(start, end);
7023 this._emit("write", { start, end });
7024 }
7025 /**
7026 * Returns a new {@link RangedTarget} that writes data to this target using the given offset.
7027 *
7028 * Useful for writing a file into a section of a larger file.
7029 */
7030 slice(offset) {
7031 if (!Number.isInteger(offset) || offset < 0) {
7032 throw new TypeError("offset must be a non-negative integer.");
7033 }
7034 return new RangedTarget(this, offset);
7035 }
7036 };
7037 var ARRAY_BUFFER_INITIAL_SIZE = 2 ** 16;
7038 var ARRAY_BUFFER_MAX_SIZE = 2 ** 32;
7039 var BufferTarget = class extends Target {
7040 /** Creates a new {@link BufferTarget}. The buffer holding the data will be created and managed internally. */
7041 constructor(options = {}) {
7042 super();
7043 this.buffer = null;
7044 this._maxPos = 0;
7045 if (!options || typeof options !== "object") {
7046 throw new TypeError("BufferTarget options, when provided, must be an object.");
7047 }
7048 if (options.onFinalize !== void 0 && typeof options.onFinalize !== "function") {
7049 throw new TypeError("options.onFinalize, when provided, must be a function.");
7050 }
7051 this._options = options;
7052 this._supportsResize = "resize" in new ArrayBuffer(0);
7053 if (this._supportsResize) {
7054 try {
7055 this._buffer = new ArrayBuffer(ARRAY_BUFFER_INITIAL_SIZE, { maxByteLength: ARRAY_BUFFER_MAX_SIZE });
7056 } catch {
7057 this._buffer = new ArrayBuffer(ARRAY_BUFFER_INITIAL_SIZE);
7058 this._supportsResize = false;
7059 }
7060 } else {
7061 this._buffer = new ArrayBuffer(ARRAY_BUFFER_INITIAL_SIZE);
7062 }
7063 this._bytes = new Uint8Array(this._buffer);
7064 }
7065 /** @internal */
7066 _ensureSize(size) {
7067 let newLength = this._buffer.byteLength;
7068 while (newLength < size)
7069 newLength *= 2;
7070 if (newLength === this._buffer.byteLength)
7071 return;
7072 if (newLength > ARRAY_BUFFER_MAX_SIZE) {
7073 throw new Error(\`ArrayBuffer exceeded maximum size of \${ARRAY_BUFFER_MAX_SIZE} bytes. Please consider using another target.\`);
7074 }
7075 if (this._supportsResize) {
7076 this._buffer.resize(newLength);
7077 } else {
7078 const newBuffer = new ArrayBuffer(newLength);
7079 const newBytes = new Uint8Array(newBuffer);
7080 newBytes.set(this._bytes, 0);
7081 this._buffer = newBuffer;
7082 this._bytes = newBytes;
7083 }
7084 }
7085 /** @internal */
7086 _start() {
7087 }
7088 /** @internal */
7089 _write(data, pos) {
7090 this._ensureSize(pos + data.byteLength);
7091 this._bytes.set(data, pos);
7092 this._maxPos = Math.max(this._maxPos, pos + data.byteLength);
7093 this._dispatchWrite(pos, pos + data.byteLength);
7094 }
7095 /** @internal */
7096 async _flush() {
7097 }
7098 /** @internal */
7099 async _finalize() {
7100 this.buffer = this._buffer.slice(0, this._maxPos);
7101 if (this._options.onFinalize) {
7102 await this._options.onFinalize(this.buffer);
7103 }
7104 this._emit("finalized");
7105 }
7106 /** @internal */
7107 async _close() {
7108 }
7109 /** @internal */
7110 _getSlice(start, end) {
7111 return this._bytes.slice(start, end);
7112 }
7113 };
7114 var DEFAULT_CHUNK_SIZE = 2 ** 24;
7115 var RangedTarget = class extends Target {
7116 /** @internal */
7117 constructor(baseTarget, offset) {
7118 super();
7119 this._baseTarget = baseTarget;
7120 this._offset = offset;
7121 }
7122 /** @internal */
7123 _start() {
7124 }
7125 /** @internal */
7126 _write(data, pos) {
7127 this._baseTarget._write(data, this._offset + pos);
7128 this._dispatchWrite(pos, pos + data.byteLength);
7129 }
7130 /** @internal */
7131 _flush() {
7132 return this._baseTarget._flush();
7133 }
7134 /** @internal */
7135 async _finalize() {
7136 this._emit("finalized");
7137 }
7138 /** @internal */
7139 async _close() {
7140 }
7141 /** @internal */
7142 _setMonotonicity(monotonicity) {
7143 super._setMonotonicity(monotonicity);
7144 this._baseTarget._setMonotonicity(monotonicity);
7145 }
7146 };
7147 var PathedTarget = class {
7148 /** Creates a new {@link PathedTarget} from a root path and a callback. */
7149 constructor(rootPath, getTarget) {
7150 this.rootPath = rootPath;
7151 this.getTarget = getTarget;
7152 if (typeof rootPath !== "string") {
7153 throw new TypeError("rootPath must be a string.");
7154 }
7155 if (typeof getTarget !== "function") {
7156 throw new TypeError("getTarget must be a function.");
7157 }
7158 }
7159 };
7160
7161 // node_modules/mediabunny/dist/modules/src/isobmff/isobmff-muxer.js
7162 var GLOBAL_TIMESCALE = 57600;
7163 var TIMESTAMP_OFFSET = 2082844800;
7164 var getTrackMetadata = (trackData) => {
7165 const metadata = {};
7166 const track = trackData.track;
7167 if (track.metadata.name !== void 0) {
7168 metadata.name = track.metadata.name;
7169 }
7170 return metadata;
7171 };
7172 var intoTimescale = (timeInSeconds, timescale, round = true) => {
7173 const value = timeInSeconds * timescale;
7174 return round ? Math.round(value) : value;
7175 };
7176 var IsobmffMuxer = class extends Muxer {
7177 constructor(output, format) {
7178 super(output);
7179 this.writer = null;
7180 this.boxWriter = null;
7181 this.initWriter = null;
7182 this.initBoxWriter = null;
7183 this.auxTarget = new BufferTarget();
7184 this.auxWriter = new Writer(this.auxTarget, false);
7185 this.auxBoxWriter = new IsobmffBoxWriter(this.auxWriter);
7186 this.mdat = null;
7187 this.ftypSize = null;
7188 this.trackDatas = [];
7189 this.allTracksKnown = promiseWithResolvers();
7190 this.creationTime = Math.floor(Date.now() / 1e3) + TIMESTAMP_OFFSET;
7191 this.finalizedChunks = [];
7192 this.nextFragmentNumber = 1;
7193 this.maxWrittenTimestamp = -Infinity;
7194 this.minWrittenTimestamp = Infinity;
7195 this.maxWrittenEndTimestamp = -Infinity;
7196 this.segmentHeaderSize = null;
7197 this.format = format;
7198 this.isQuickTime = format instanceof MovOutputFormat;
7199 this.isCmaf = format instanceof CmafOutputFormat;
7200 this.minimumFragmentDuration = format._options.minimumFragmentDuration ?? (format instanceof CmafOutputFormat ? Infinity : 1);
7201 }
7202 async start() {
7203 const release = await this.mutex.acquire();
7204 if (!this.isCmaf) {
7205 this.writer = await this.output._getRootWriter((target) => this.format._options.fastStart !== void 0 ? this.format._options.fastStart === "fragmented" : target instanceof BufferTarget);
7206 this.boxWriter = new IsobmffBoxWriter(this.writer);
7207 this.fastStart = this.format._options.fastStart ?? (this.writer.target instanceof BufferTarget ? "in-memory" : false);
7208 this.isFragmented = this.fastStart === "fragmented";
7209 } else {
7210 this.fastStart = "fragmented";
7211 this.isFragmented = true;
7212 }
7213 if (this.isCmaf) {
7214 if (!this.output._hasInitTarget()) {
7215 throw new Error(\`CMAF outputs require the initTarget field in OutputOptions to be set; the init segment will be written to it.\`);
7216 }
7217 const initTarget = await this.output._getInitTarget();
7218 const initWriter = new Writer(initTarget, true);
7219 initWriter.start();
7220 this.initWriter = initWriter;
7221 this.initBoxWriter = new IsobmffBoxWriter(initWriter);
7222 }
7223 const holdsAvc = this.output._tracks.some((x) => x.isVideoTrack() && x.source._codec === "avc");
7224 {
7225 const boxWriter = this.initBoxWriter ?? this.boxWriter;
7226 assert(boxWriter);
7227 if (this.format._options.onFtyp) {
7228 boxWriter.writer.startTrackingWrites();
7229 }
7230 boxWriter.writeBox(ftyp({
7231 isQuickTime: this.isQuickTime,
7232 holdsAvc,
7233 fragmented: this.isFragmented,
7234 cmaf: this.isCmaf
7235 }));
7236 if (this.format._options.onFtyp) {
7237 const { data, start } = boxWriter.writer.stopTrackingWrites();
7238 this.format._options.onFtyp(data, start);
7239 }
7240 this.ftypSize = boxWriter.writer.getPos();
7241 if (this.isCmaf) {
7242 await this.initWriter.flush();
7243 }
7244 }
7245 if (this.fastStart === "in-memory") {
7246 } else if (this.fastStart === "reserve") {
7247 for (const track of this.output._tracks) {
7248 if (track.metadata.maximumPacketCount === void 0) {
7249 throw new Error("All tracks must specify maximumPacketCount in their metadata when using fastStart: 'reserve'.");
7250 }
7251 }
7252 } else if (this.isFragmented) {
7253 } else {
7254 assert(this.writer);
7255 assert(this.boxWriter);
7256 if (this.format._options.onMdat) {
7257 this.writer.startTrackingWrites();
7258 }
7259 this.mdat = mdat(true);
7260 this.boxWriter.writeBox(this.mdat);
7261 }
7262 await this.writer?.flush();
7263 release();
7264 }
7265 allTracksAreKnown() {
7266 for (const track of this.output._tracks) {
7267 if (!track.source._closed && !this.trackDatas.some((x) => x.track === track)) {
7268 return false;
7269 }
7270 }
7271 return true;
7272 }
7273 async getMimeType() {
7274 await this.allTracksKnown.promise;
7275 const codecStrings = this.trackDatas.map((trackData) => {
7276 if (trackData.type === "video") {
7277 return trackData.info.decoderConfig.codec;
7278 } else if (trackData.type === "audio") {
7279 return trackData.info.decoderConfig.codec;
7280 } else {
7281 const map = {
7282 webvtt: "wvtt"
7283 };
7284 return map[trackData.track.source._codec];
7285 }
7286 });
7287 return buildIsobmffMimeType({
7288 isQuickTime: this.isQuickTime,
7289 hasVideo: this.trackDatas.some((x) => x.type === "video"),
7290 hasAudio: this.trackDatas.some((x) => x.type === "audio"),
7291 codecStrings
7292 });
7293 }
7294 getVideoTrackData(track, packet, meta) {
7295 const existingTrackData = this.trackDatas.find((x) => x.track === track);
7296 if (existingTrackData) {
7297 return existingTrackData;
7298 }
7299 validateVideoChunkMetadata(meta);
7300 assert(meta);
7301 assert(meta.decoderConfig);
7302 const decoderConfig = { ...meta.decoderConfig };
7303 assert(decoderConfig.codedWidth !== void 0);
7304 assert(decoderConfig.codedHeight !== void 0);
7305 let requiresAnnexBTransformation = false;
7306 if (track.source._codec === "avc" && !decoderConfig.description) {
7307 const decoderConfigurationRecord = extractAvcDecoderConfigurationRecord(packet.data);
7308 if (!decoderConfigurationRecord) {
7309 throw new Error("Couldn't extract an AVCDecoderConfigurationRecord from the AVC packet. Make sure the packets are in Annex B format (as specified in ITU-T-REC-H.264) when not providing a description, or provide a description (must be an AVCDecoderConfigurationRecord as specified in ISO 14496-15) and ensure the packets are in AVCC format.");
7310 }
7311 decoderConfig.description = serializeAvcDecoderConfigurationRecord(decoderConfigurationRecord);
7312 requiresAnnexBTransformation = true;
7313 } else if (track.source._codec === "hevc" && !decoderConfig.description) {
7314 const decoderConfigurationRecord = extractHevcDecoderConfigurationRecord(packet.data);
7315 if (!decoderConfigurationRecord) {
7316 throw new Error("Couldn't extract an HEVCDecoderConfigurationRecord from the HEVC packet. Make sure the packets are in Annex B format (as specified in ITU-T-REC-H.265) when not providing a description, or provide a description (must be an HEVCDecoderConfigurationRecord as specified in ISO 14496-15) and ensure the packets are in HEVC format.");
7317 }
7318 decoderConfig.description = serializeHevcDecoderConfigurationRecord(decoderConfigurationRecord);
7319 requiresAnnexBTransformation = true;
7320 }
7321 const timescale = computeRationalApproximation(1 / (track.metadata.frameRate ?? GLOBAL_TIMESCALE), 1e6).den;
7322 const displayAspectWidth = decoderConfig.displayAspectWidth;
7323 const displayAspectHeight = decoderConfig.displayAspectHeight;
7324 const pixelAspectRatio = displayAspectWidth === void 0 || displayAspectHeight === void 0 ? { num: 1, den: 1 } : simplifyRational({
7325 num: displayAspectWidth * decoderConfig.codedHeight,
7326 den: displayAspectHeight * decoderConfig.codedWidth
7327 });
7328 const newTrackData = {
7329 muxer: this,
7330 track,
7331 type: "video",
7332 info: {
7333 width: decoderConfig.codedWidth,
7334 height: decoderConfig.codedHeight,
7335 pixelAspectRatio,
7336 decoderConfig,
7337 requiresAnnexBTransformation
7338 },
7339 timescale,
7340 samples: [],
7341 sampleQueue: [],
7342 timestampProcessingQueue: [],
7343 timeToSampleTable: [],
7344 compositionTimeOffsetTable: [],
7345 lastTimescaleUnits: null,
7346 lastSample: null,
7347 startTimestampOffset: null,
7348 finalizedChunks: [],
7349 currentChunk: null,
7350 compactlyCodedChunkTable: [],
7351 closed: false
7352 };
7353 this.trackDatas.push(newTrackData);
7354 this.trackDatas.sort((a2, b) => a2.track.id - b.track.id);
7355 if (this.allTracksAreKnown()) {
7356 this.allTracksKnown.resolve();
7357 }
7358 return newTrackData;
7359 }
7360 getAudioTrackData(track, packet, meta) {
7361 const existingTrackData = this.trackDatas.find((x) => x.track === track);
7362 if (existingTrackData) {
7363 return existingTrackData;
7364 }
7365 validateAudioChunkMetadata(meta);
7366 assert(meta);
7367 assert(meta.decoderConfig);
7368 const decoderConfig = { ...meta.decoderConfig };
7369 let requiresAdtsStripping = false;
7370 if (track.source._codec === "aac" && !decoderConfig.description) {
7371 const adtsFrame = readAdtsFrameHeader(FileSlice.tempFromBytes(packet.data));
7372 if (!adtsFrame) {
7373 throw new Error("Couldn't parse ADTS header from the AAC packet. Make sure the packets are in ADTS format (as specified in ISO 13818-7) when not providing a description, or provide a description (must be an AudioSpecificConfig as specified in ISO 14496-3) and ensure the packets are raw AAC data.");
7374 }
7375 const sampleRate = aacFrequencyTable[adtsFrame.samplingFrequencyIndex];
7376 const numberOfChannels = aacChannelMap[adtsFrame.channelConfiguration];
7377 if (sampleRate === void 0 || numberOfChannels === void 0) {
7378 throw new Error("Invalid ADTS frame header.");
7379 }
7380 decoderConfig.description = buildAacAudioSpecificConfig({
7381 objectType: adtsFrame.objectType,
7382 sampleRate,
7383 numberOfChannels
7384 });
7385 requiresAdtsStripping = true;
7386 }
7387 const newTrackData = {
7388 muxer: this,
7389 track,
7390 type: "audio",
7391 info: {
7392 numberOfChannels: meta.decoderConfig.numberOfChannels,
7393 sampleRate: meta.decoderConfig.sampleRate,
7394 decoderConfig,
7395 requiresPcmTransformation: !this.isFragmented && PCM_AUDIO_CODECS.includes(track.source._codec),
7396 expectedNextPcmPacketTimestamp: null,
7397 requiresAdtsStripping,
7398 firstPacket: packet
7399 },
7400 timescale: decoderConfig.sampleRate,
7401 samples: [],
7402 sampleQueue: [],
7403 timestampProcessingQueue: [],
7404 timeToSampleTable: [],
7405 compositionTimeOffsetTable: [],
7406 lastTimescaleUnits: null,
7407 lastSample: null,
7408 startTimestampOffset: null,
7409 finalizedChunks: [],
7410 currentChunk: null,
7411 compactlyCodedChunkTable: [],
7412 closed: false
7413 };
7414 this.trackDatas.push(newTrackData);
7415 this.trackDatas.sort((a2, b) => a2.track.id - b.track.id);
7416 if (this.allTracksAreKnown()) {
7417 this.allTracksKnown.resolve();
7418 }
7419 return newTrackData;
7420 }
7421 getSubtitleTrackData(track, meta) {
7422 const existingTrackData = this.trackDatas.find((x) => x.track === track);
7423 if (existingTrackData) {
7424 return existingTrackData;
7425 }
7426 validateSubtitleMetadata(meta);
7427 assert(meta);
7428 assert(meta.config);
7429 const newTrackData = {
7430 muxer: this,
7431 track,
7432 type: "subtitle",
7433 info: {
7434 config: meta.config
7435 },
7436 timescale: 1e3,
7437 // Reasonable
7438 samples: [],
7439 sampleQueue: [],
7440 timestampProcessingQueue: [],
7441 timeToSampleTable: [],
7442 compositionTimeOffsetTable: [],
7443 lastTimescaleUnits: null,
7444 lastSample: null,
7445 startTimestampOffset: null,
7446 finalizedChunks: [],
7447 currentChunk: null,
7448 compactlyCodedChunkTable: [],
7449 closed: false,
7450 lastCueEndTimestamp: 0,
7451 cueQueue: [],
7452 nextSourceId: 0,
7453 cueToSourceId: /* @__PURE__ */ new WeakMap()
7454 };
7455 this.trackDatas.push(newTrackData);
7456 this.trackDatas.sort((a2, b) => a2.track.id - b.track.id);
7457 if (this.allTracksAreKnown()) {
7458 this.allTracksKnown.resolve();
7459 }
7460 return newTrackData;
7461 }
7462 async addEncodedVideoPacket(track, packet, meta) {
7463 const release = await this.mutex.acquire();
7464 try {
7465 const trackData = this.getVideoTrackData(track, packet, meta);
7466 let packetData = packet.data;
7467 if (trackData.info.requiresAnnexBTransformation) {
7468 const nalUnits = [...iterateNalUnitsInAnnexB(packetData)].map((loc) => packetData.subarray(loc.offset, loc.offset + loc.length));
7469 if (nalUnits.length === 0) {
7470 throw new Error("Failed to transform packet data. Make sure all packets are provided in Annex B format, as specified in ITU-T-REC-H.264 and ITU-T-REC-H.265.");
7471 }
7472 packetData = concatNalUnitsInLengthPrefixed(nalUnits, 4);
7473 }
7474 this.validateTimestamp(trackData.track, packet.timestamp, packet.type === "key");
7475 const internalSample = this.createSampleForTrack(trackData, packetData, packet.timestamp, packet.duration, packet.type);
7476 await this.registerSample(trackData, internalSample);
7477 } finally {
7478 release();
7479 }
7480 }
7481 async addEncodedAudioPacket(track, packet, meta) {
7482 const release = await this.mutex.acquire();
7483 try {
7484 const trackData = this.getAudioTrackData(track, packet, meta);
7485 let packetData = packet.data;
7486 if (trackData.info.requiresAdtsStripping) {
7487 const adtsFrame = readAdtsFrameHeader(FileSlice.tempFromBytes(packetData));
7488 if (!adtsFrame) {
7489 throw new Error("Expected ADTS frame, didn't get one.");
7490 }
7491 const headerLength = adtsFrame.crcCheck === null ? MIN_ADTS_FRAME_HEADER_SIZE : MAX_ADTS_FRAME_HEADER_SIZE;
7492 packetData = packetData.subarray(headerLength);
7493 }
7494 this.validateTimestamp(trackData.track, packet.timestamp, packet.type === "key");
7495 let timestamp = packet.timestamp;
7496 let duration = packet.duration;
7497 if (trackData.info.requiresPcmTransformation) {
7498 const pcmInfo = parsePcmCodec(trackData.info.decoderConfig.codec);
7499 const frameSize = pcmInfo.sampleSize * trackData.info.numberOfChannels;
7500 duration = packetData.byteLength / frameSize / trackData.info.sampleRate;
7501 if (trackData.info.expectedNextPcmPacketTimestamp !== null) {
7502 const diff = timestamp - trackData.info.expectedNextPcmPacketTimestamp;
7503 if (diff < 0.01) {
7504 timestamp = trackData.info.expectedNextPcmPacketTimestamp;
7505 } else {
7506 const paddedDuration = await this.padWithSilence(trackData, trackData.info.expectedNextPcmPacketTimestamp, diff);
7507 timestamp = trackData.info.expectedNextPcmPacketTimestamp + paddedDuration;
7508 }
7509 }
7510 trackData.info.expectedNextPcmPacketTimestamp = timestamp + duration;
7511 }
7512 const internalSample = this.createSampleForTrack(trackData, packetData, timestamp, duration, packet.type);
7513 await this.registerSample(trackData, internalSample);
7514 } finally {
7515 release();
7516 }
7517 }
7518 async padWithSilence(trackData, timestamp, duration) {
7519 const deltaInTimescale = intoTimescale(duration, trackData.timescale);
7520 duration = deltaInTimescale / trackData.timescale;
7521 if (deltaInTimescale > 0) {
7522 const { sampleSize, silentValue } = parsePcmCodec(trackData.info.decoderConfig.codec);
7523 const samplesNeeded = deltaInTimescale * trackData.info.numberOfChannels;
7524 const data = new Uint8Array(sampleSize * samplesNeeded).fill(silentValue);
7525 const paddingSample = this.createSampleForTrack(trackData, new Uint8Array(data.buffer), timestamp, duration, "key");
7526 await this.registerSample(trackData, paddingSample);
7527 }
7528 return duration;
7529 }
7530 async addSubtitleCue(track, cue, meta) {
7531 const release = await this.mutex.acquire();
7532 try {
7533 const trackData = this.getSubtitleTrackData(track, meta);
7534 this.validateTimestamp(trackData.track, cue.timestamp, true);
7535 if (track.source._codec === "webvtt") {
7536 trackData.cueQueue.push(cue);
7537 await this.processWebVTTCues(trackData, cue.timestamp);
7538 } else {
7539 }
7540 } finally {
7541 release();
7542 }
7543 }
7544 async processWebVTTCues(trackData, until) {
7545 while (trackData.cueQueue.length > 0) {
7546 const timestamps = /* @__PURE__ */ new Set([]);
7547 for (const cue of trackData.cueQueue) {
7548 assert(cue.timestamp <= until);
7549 assert(trackData.lastCueEndTimestamp <= cue.timestamp + cue.duration);
7550 timestamps.add(Math.max(cue.timestamp, trackData.lastCueEndTimestamp));
7551 timestamps.add(cue.timestamp + cue.duration);
7552 }
7553 const sortedTimestamps = [...timestamps].sort((a2, b) => a2 - b);
7554 const sampleStart = sortedTimestamps[0];
7555 const sampleEnd = sortedTimestamps[1] ?? sampleStart;
7556 if (until < sampleEnd) {
7557 break;
7558 }
7559 if (trackData.lastCueEndTimestamp < sampleStart) {
7560 this.auxWriter.seek(0);
7561 const box2 = vtte();
7562 this.auxBoxWriter.writeBox(box2);
7563 const body2 = this.auxTarget._getSlice(0, this.auxWriter.getPos());
7564 const sample2 = this.createSampleForTrack(trackData, body2, trackData.lastCueEndTimestamp, sampleStart - trackData.lastCueEndTimestamp, "key");
7565 await this.registerSample(trackData, sample2);
7566 trackData.lastCueEndTimestamp = sampleStart;
7567 }
7568 this.auxWriter.seek(0);
7569 for (let i2 = 0; i2 < trackData.cueQueue.length; i2++) {
7570 const cue = trackData.cueQueue[i2];
7571 if (cue.timestamp >= sampleEnd) {
7572 break;
7573 }
7574 inlineTimestampRegex.lastIndex = 0;
7575 const containsTimestamp = inlineTimestampRegex.test(cue.text);
7576 const endTimestamp = cue.timestamp + cue.duration;
7577 let sourceId = trackData.cueToSourceId.get(cue);
7578 if (sourceId === void 0 && sampleEnd < endTimestamp) {
7579 sourceId = trackData.nextSourceId++;
7580 trackData.cueToSourceId.set(cue, sourceId);
7581 }
7582 if (cue.notes) {
7583 const box3 = vtta(cue.notes);
7584 this.auxBoxWriter.writeBox(box3);
7585 }
7586 const box2 = vttc(cue.text, containsTimestamp ? sampleStart : null, cue.identifier ?? null, cue.settings ?? null, sourceId ?? null);
7587 this.auxBoxWriter.writeBox(box2);
7588 if (endTimestamp === sampleEnd) {
7589 trackData.cueQueue.splice(i2--, 1);
7590 }
7591 }
7592 const body = this.auxTarget._getSlice(0, this.auxWriter.getPos());
7593 const sample = this.createSampleForTrack(trackData, body, sampleStart, sampleEnd - sampleStart, "key");
7594 await this.registerSample(trackData, sample);
7595 trackData.lastCueEndTimestamp = sampleEnd;
7596 }
7597 }
7598 createSampleForTrack(trackData, data, timestamp, duration, type) {
7599 const sample = {
7600 timestamp,
7601 decodeTimestamp: timestamp,
7602 // This may be refined later
7603 duration,
7604 data,
7605 size: data.byteLength,
7606 type,
7607 timescaleUnitsToNextSample: intoTimescale(duration, trackData.timescale)
7608 // Will be refined
7609 };
7610 return sample;
7611 }
7612 processTimestamps(trackData, nextSample) {
7613 if (trackData.timestampProcessingQueue.length === 0) {
7614 return;
7615 }
7616 if (trackData.type === "audio" && trackData.info.requiresPcmTransformation) {
7617 if (!this.isFragmented) {
7618 trackData.startTimestampOffset ??= trackData.timestampProcessingQueue[0].timestamp;
7619 }
7620 let totalDuration = 0;
7621 for (let i2 = 0; i2 < trackData.timestampProcessingQueue.length; i2++) {
7622 const sample = trackData.timestampProcessingQueue[i2];
7623 const duration = intoTimescale(sample.duration, trackData.timescale);
7624 totalDuration += duration;
7625 }
7626 if (trackData.timeToSampleTable.length === 0) {
7627 trackData.timeToSampleTable.push({
7628 sampleCount: totalDuration,
7629 sampleDelta: 1
7630 });
7631 } else {
7632 const lastEntry = last(trackData.timeToSampleTable);
7633 lastEntry.sampleCount += totalDuration;
7634 }
7635 trackData.timestampProcessingQueue.length = 0;
7636 return;
7637 }
7638 const sortedTimestamps = trackData.timestampProcessingQueue.map((x) => x.timestamp).sort((a2, b) => a2 - b);
7639 if (!this.isFragmented) {
7640 trackData.startTimestampOffset ??= sortedTimestamps[0];
7641 }
7642 for (let i2 = 0; i2 < trackData.timestampProcessingQueue.length; i2++) {
7643 const sample = trackData.timestampProcessingQueue[i2];
7644 sample.decodeTimestamp = sortedTimestamps[i2];
7645 const sampleCompositionTimeOffset = intoTimescale(sample.timestamp - sample.decodeTimestamp, trackData.timescale);
7646 const durationInTimescale = intoTimescale(sample.duration, trackData.timescale);
7647 if (trackData.lastTimescaleUnits !== null) {
7648 assert(trackData.lastSample);
7649 const timescaleUnits = intoTimescale(sample.decodeTimestamp, trackData.timescale, false);
7650 const delta = Math.round(timescaleUnits - trackData.lastTimescaleUnits);
7651 assert(delta >= 0);
7652 trackData.lastTimescaleUnits += delta;
7653 trackData.lastSample.timescaleUnitsToNextSample = delta;
7654 if (!this.isFragmented) {
7655 let lastTableEntry = last(trackData.timeToSampleTable);
7656 assert(lastTableEntry);
7657 if (lastTableEntry.sampleCount === 1) {
7658 lastTableEntry.sampleDelta = delta;
7659 const entryBefore = trackData.timeToSampleTable[trackData.timeToSampleTable.length - 2];
7660 if (entryBefore && entryBefore.sampleDelta === delta) {
7661 entryBefore.sampleCount++;
7662 trackData.timeToSampleTable.pop();
7663 lastTableEntry = entryBefore;
7664 }
7665 } else if (lastTableEntry.sampleDelta !== delta) {
7666 lastTableEntry.sampleCount--;
7667 trackData.timeToSampleTable.push(lastTableEntry = {
7668 sampleCount: 1,
7669 sampleDelta: delta
7670 });
7671 }
7672 if (lastTableEntry.sampleDelta === durationInTimescale) {
7673 lastTableEntry.sampleCount++;
7674 } else {
7675 trackData.timeToSampleTable.push({
7676 sampleCount: 1,
7677 sampleDelta: durationInTimescale
7678 });
7679 }
7680 const lastCompositionTimeOffsetTableEntry = last(trackData.compositionTimeOffsetTable);
7681 assert(lastCompositionTimeOffsetTableEntry);
7682 if (lastCompositionTimeOffsetTableEntry.sampleCompositionTimeOffset === sampleCompositionTimeOffset) {
7683 lastCompositionTimeOffsetTableEntry.sampleCount++;
7684 } else {
7685 trackData.compositionTimeOffsetTable.push({
7686 sampleCount: 1,
7687 sampleCompositionTimeOffset
7688 });
7689 }
7690 }
7691 } else {
7692 trackData.lastTimescaleUnits = intoTimescale(sample.decodeTimestamp, trackData.timescale, false);
7693 if (!this.isFragmented) {
7694 trackData.timeToSampleTable.push({
7695 sampleCount: 1,
7696 sampleDelta: durationInTimescale
7697 });
7698 trackData.compositionTimeOffsetTable.push({
7699 sampleCount: 1,
7700 sampleCompositionTimeOffset
7701 });
7702 }
7703 }
7704 trackData.lastSample = sample;
7705 }
7706 trackData.timestampProcessingQueue.length = 0;
7707 assert(trackData.lastSample);
7708 assert(trackData.lastTimescaleUnits !== null);
7709 if (nextSample !== void 0 && trackData.lastSample.timescaleUnitsToNextSample === 0) {
7710 assert(nextSample.type === "key");
7711 const timescaleUnits = intoTimescale(nextSample.timestamp, trackData.timescale, false);
7712 const delta = Math.round(timescaleUnits - trackData.lastTimescaleUnits);
7713 trackData.lastSample.timescaleUnitsToNextSample = delta;
7714 }
7715 }
7716 async registerSample(trackData, sample) {
7717 if (sample.type === "key") {
7718 this.processTimestamps(trackData, sample);
7719 }
7720 trackData.timestampProcessingQueue.push(sample);
7721 if (this.isFragmented) {
7722 trackData.sampleQueue.push(sample);
7723 await this.interleaveSamples();
7724 } else if (this.fastStart === "reserve") {
7725 await this.registerSampleFastStartReserve(trackData, sample);
7726 } else {
7727 await this.addSampleToTrack(trackData, sample);
7728 }
7729 }
7730 async addSampleToTrack(trackData, sample) {
7731 if (!this.isFragmented) {
7732 trackData.samples.push(sample);
7733 if (this.fastStart === "reserve") {
7734 const maximumPacketCount = trackData.track.metadata.maximumPacketCount;
7735 assert(maximumPacketCount !== void 0);
7736 if (trackData.samples.length > maximumPacketCount) {
7737 throw new Error(\`Track #\${trackData.track.id} has already reached the maximum packet count (\${maximumPacketCount}). Either add less packets or increase the maximum packet count.\`);
7738 }
7739 }
7740 }
7741 let beginNewChunk = false;
7742 if (!trackData.currentChunk) {
7743 beginNewChunk = true;
7744 } else {
7745 trackData.currentChunk.startTimestamp = Math.min(trackData.currentChunk.startTimestamp, sample.timestamp);
7746 const currentChunkDuration = sample.timestamp - trackData.currentChunk.startTimestamp;
7747 if (this.isFragmented) {
7748 const keyFrameQueuedEverywhere = this.trackDatas.every((otherTrackData) => {
7749 if (trackData === otherTrackData) {
7750 return sample.type === "key";
7751 }
7752 const firstQueuedSample = otherTrackData.sampleQueue[0];
7753 if (firstQueuedSample) {
7754 return firstQueuedSample.type === "key";
7755 }
7756 return otherTrackData.closed;
7757 });
7758 if (currentChunkDuration >= this.minimumFragmentDuration && keyFrameQueuedEverywhere && sample.timestamp > this.maxWrittenTimestamp) {
7759 beginNewChunk = true;
7760 await this.finalizeFragment();
7761 }
7762 } else {
7763 beginNewChunk = currentChunkDuration >= 0.5;
7764 }
7765 }
7766 if (beginNewChunk) {
7767 if (trackData.currentChunk) {
7768 await this.finalizeCurrentChunk(trackData);
7769 }
7770 trackData.currentChunk = {
7771 startTimestamp: sample.timestamp,
7772 samples: [],
7773 offset: null,
7774 moofOffset: null
7775 };
7776 }
7777 assert(trackData.currentChunk);
7778 trackData.currentChunk.samples.push(sample);
7779 if (this.isFragmented) {
7780 this.maxWrittenTimestamp = Math.max(this.maxWrittenTimestamp, sample.timestamp);
7781 this.maxWrittenEndTimestamp = Math.max(this.maxWrittenEndTimestamp, sample.timestamp + sample.duration);
7782 this.minWrittenTimestamp = Math.min(this.minWrittenTimestamp, sample.timestamp);
7783 }
7784 }
7785 async finalizeCurrentChunk(trackData) {
7786 assert(!this.isFragmented);
7787 assert(this.writer);
7788 if (!trackData.currentChunk)
7789 return;
7790 trackData.finalizedChunks.push(trackData.currentChunk);
7791 this.finalizedChunks.push(trackData.currentChunk);
7792 let sampleCount = trackData.currentChunk.samples.length;
7793 if (trackData.type === "audio" && trackData.info.requiresPcmTransformation) {
7794 sampleCount = trackData.currentChunk.samples.reduce((acc, sample) => acc + intoTimescale(sample.duration, trackData.timescale), 0);
7795 }
7796 if (trackData.compactlyCodedChunkTable.length === 0 || last(trackData.compactlyCodedChunkTable).samplesPerChunk !== sampleCount) {
7797 trackData.compactlyCodedChunkTable.push({
7798 firstChunk: trackData.finalizedChunks.length,
7799 // 1-indexed
7800 samplesPerChunk: sampleCount
7801 });
7802 }
7803 if (this.fastStart === "in-memory") {
7804 trackData.currentChunk.offset = 0;
7805 return;
7806 }
7807 trackData.currentChunk.offset = this.writer.getPos();
7808 for (const sample of trackData.currentChunk.samples) {
7809 assert(sample.data);
7810 this.writer.write(sample.data);
7811 sample.data = null;
7812 }
7813 await this.writer.flush();
7814 }
7815 async interleaveSamples(isFinalCall = false) {
7816 assert(this.isFragmented);
7817 if (!isFinalCall && !this.allTracksAreKnown()) {
7818 return;
7819 }
7820 outer: while (true) {
7821 let trackWithMinTimestamp = null;
7822 let minTimestamp = Infinity;
7823 for (const trackData of this.trackDatas) {
7824 if (!isFinalCall && trackData.sampleQueue.length === 0 && !trackData.closed) {
7825 break outer;
7826 }
7827 if (trackData.sampleQueue.length > 0 && trackData.sampleQueue[0].timestamp < minTimestamp) {
7828 trackWithMinTimestamp = trackData;
7829 minTimestamp = trackData.sampleQueue[0].timestamp;
7830 }
7831 }
7832 if (!trackWithMinTimestamp) {
7833 break;
7834 }
7835 const sample = trackWithMinTimestamp.sampleQueue.shift();
7836 await this.addSampleToTrack(trackWithMinTimestamp, sample);
7837 }
7838 }
7839 async finalizeFragment(flushWriter = !this.isCmaf) {
7840 assert(this.isFragmented);
7841 const fragmentNumber = this.nextFragmentNumber++;
7842 if (fragmentNumber === 1) {
7843 const boxWriter = this.initBoxWriter ?? this.boxWriter;
7844 assert(boxWriter);
7845 if (this.format._options.onMoov) {
7846 boxWriter.writer.startTrackingWrites();
7847 }
7848 this.ensureOneEnabledTrack();
7849 const movieBox = moov(this);
7850 boxWriter.writeBox(movieBox);
7851 if (this.format._options.onMoov) {
7852 const { data, start } = boxWriter.writer.stopTrackingWrites();
7853 this.format._options.onMoov(data, start);
7854 }
7855 if (this.isCmaf) {
7856 assert(this.initWriter);
7857 await this.initWriter.flush();
7858 await this.initWriter.finalize();
7859 this.writer = await this.output._getRootWriter(true);
7860 this.boxWriter = new IsobmffBoxWriter(this.writer);
7861 const stypSize = this.boxWriter.measureBox(styp());
7862 const sidxSize = this.boxWriter.measureBox(sidx(this, 0));
7863 this.segmentHeaderSize = stypSize + sidxSize;
7864 this.writer.seek(this.segmentHeaderSize);
7865 }
7866 }
7867 assert(this.writer);
7868 assert(this.boxWriter);
7869 const tracksInFragment = this.trackDatas.filter((x) => x.currentChunk);
7870 const moofBox = moof(fragmentNumber, tracksInFragment);
7871 const moofOffset = this.writer.getPos();
7872 const mdatStartPos = moofOffset + this.boxWriter.measureBox(moofBox);
7873 let currentPos = mdatStartPos + MIN_BOX_HEADER_SIZE;
7874 let fragmentStartTimestamp = Infinity;
7875 for (const trackData of tracksInFragment) {
7876 trackData.currentChunk.offset = currentPos;
7877 trackData.currentChunk.moofOffset = moofOffset;
7878 for (const sample of trackData.currentChunk.samples) {
7879 currentPos += sample.size;
7880 }
7881 fragmentStartTimestamp = Math.min(fragmentStartTimestamp, trackData.currentChunk.startTimestamp);
7882 }
7883 const mdatSize = currentPos - mdatStartPos;
7884 const needsLargeMdatSize = mdatSize >= 2 ** 32;
7885 if (needsLargeMdatSize) {
7886 for (const trackData of tracksInFragment) {
7887 trackData.currentChunk.offset += MAX_BOX_HEADER_SIZE - MIN_BOX_HEADER_SIZE;
7888 }
7889 }
7890 if (this.format._options.onMoof) {
7891 this.writer.startTrackingWrites();
7892 }
7893 const newMoofBox = moof(fragmentNumber, tracksInFragment);
7894 this.boxWriter.writeBox(newMoofBox);
7895 if (this.format._options.onMoof) {
7896 const { data, start } = this.writer.stopTrackingWrites();
7897 this.format._options.onMoof(data, start, fragmentStartTimestamp);
7898 }
7899 assert(this.writer.getPos() === mdatStartPos);
7900 if (this.format._options.onMdat) {
7901 this.writer.startTrackingWrites();
7902 }
7903 const mdatBox = mdat(needsLargeMdatSize);
7904 mdatBox.size = mdatSize;
7905 this.boxWriter.writeBox(mdatBox);
7906 this.writer.seek(mdatStartPos + (needsLargeMdatSize ? MAX_BOX_HEADER_SIZE : MIN_BOX_HEADER_SIZE));
7907 for (const trackData of tracksInFragment) {
7908 for (const sample of trackData.currentChunk.samples) {
7909 this.writer.write(sample.data);
7910 sample.data = null;
7911 }
7912 }
7913 if (this.format._options.onMdat) {
7914 const { data, start } = this.writer.stopTrackingWrites();
7915 this.format._options.onMdat(data, start);
7916 }
7917 for (const trackData of tracksInFragment) {
7918 trackData.finalizedChunks.push(trackData.currentChunk);
7919 this.finalizedChunks.push(trackData.currentChunk);
7920 trackData.currentChunk = null;
7921 }
7922 if (flushWriter) {
7923 await this.writer.flush();
7924 }
7925 }
7926 async registerSampleFastStartReserve(trackData, sample) {
7927 assert(this.writer);
7928 assert(this.boxWriter);
7929 if (this.allTracksAreKnown()) {
7930 if (!this.mdat) {
7931 this.ensureOneEnabledTrack();
7932 const moovBox = moov(this);
7933 const moovSize = this.boxWriter.measureBox(moovBox);
7934 const reservedSize = moovSize + this.computeSampleTableSizeUpperBound() + 4096;
7935 assert(this.ftypSize !== null);
7936 this.writer.seek(this.ftypSize + reservedSize);
7937 if (this.format._options.onMdat) {
7938 this.writer.startTrackingWrites();
7939 }
7940 this.mdat = mdat(true);
7941 this.boxWriter.writeBox(this.mdat);
7942 for (const trackData2 of this.trackDatas) {
7943 for (const sample2 of trackData2.sampleQueue) {
7944 await this.addSampleToTrack(trackData2, sample2);
7945 }
7946 trackData2.sampleQueue.length = 0;
7947 }
7948 }
7949 await this.addSampleToTrack(trackData, sample);
7950 } else {
7951 trackData.sampleQueue.push(sample);
7952 }
7953 }
7954 computeSampleTableSizeUpperBound() {
7955 assert(this.fastStart === "reserve");
7956 let upperBound = 0;
7957 for (const trackData of this.trackDatas) {
7958 const n2 = trackData.track.metadata.maximumPacketCount;
7959 assert(n2 !== void 0);
7960 upperBound += (4 + 4) * Math.ceil(2 / 3 * n2);
7961 upperBound += 4 * n2;
7962 upperBound += (4 + 4) * Math.ceil(2 / 3 * n2);
7963 upperBound += (4 + 4 + 4) * Math.ceil(2 / 3 * n2);
7964 upperBound += 4 * n2;
7965 upperBound += 8 * n2;
7966 }
7967 return upperBound;
7968 }
7969 // eslint-disable-next-line @typescript-eslint/no-misused-promises
7970 async onTrackClose(track) {
7971 const release = await this.mutex.acquire();
7972 const trackData = this.trackDatas.find((x) => x.track === track);
7973 if (trackData) {
7974 trackData.closed = true;
7975 if (trackData.type === "subtitle" && track.source._codec === "webvtt") {
7976 await this.processWebVTTCues(trackData, Infinity);
7977 }
7978 this.processTimestamps(trackData);
7979 }
7980 if (this.allTracksAreKnown()) {
7981 this.allTracksKnown.resolve();
7982 }
7983 if (this.isFragmented) {
7984 await this.interleaveSamples();
7985 }
7986 release();
7987 }
7988 ensureOneEnabledTrack() {
7989 for (const type of ["video", "audio", "subtitle"]) {
7990 const tracks = this.trackDatas.filter((t2) => t2.type === type);
7991 if (tracks.length === 0) {
7992 continue;
7993 }
7994 const hasEnabled = tracks.some((t2) => t2.track.metadata.disposition?.default !== false);
7995 if (!hasEnabled) {
7996 const firstTrack = tracks[0];
7997 firstTrack.track.metadata.disposition = {
7998 ...firstTrack.track.metadata.disposition,
7999 default: true
8000 };
8001 }
8002 }
8003 }
8004 /** Finalizes the file, making it ready for use. Must be called after all video and audio chunks have been added. */
8005 async finalize() {
8006 const release = await this.mutex.acquire();
8007 this.allTracksKnown.resolve();
8008 this.ensureOneEnabledTrack();
8009 for (const trackData of this.trackDatas) {
8010 trackData.closed = true;
8011 if (trackData.type === "subtitle" && trackData.track.source._codec === "webvtt") {
8012 await this.processWebVTTCues(trackData, Infinity);
8013 }
8014 this.processTimestamps(trackData);
8015 }
8016 if (this.isFragmented) {
8017 await this.interleaveSamples(true);
8018 await this.finalizeFragment(false);
8019 } else {
8020 for (const trackData of this.trackDatas) {
8021 await this.finalizeCurrentChunk(trackData);
8022 assert(trackData.startTimestampOffset !== null);
8023 for (let i2 = 0; i2 < trackData.samples.length; i2++) {
8024 const sample = trackData.samples[i2];
8025 sample.timestamp -= trackData.startTimestampOffset;
8026 sample.decodeTimestamp -= trackData.startTimestampOffset;
8027 }
8028 }
8029 }
8030 assert(this.writer);
8031 assert(this.boxWriter);
8032 if (this.fastStart === "in-memory") {
8033 this.mdat = mdat(false);
8034 let mdatSize;
8035 for (let i2 = 0; i2 < 2; i2++) {
8036 const movieBox2 = moov(this);
8037 const movieBoxSize = this.boxWriter.measureBox(movieBox2);
8038 mdatSize = this.boxWriter.measureBox(this.mdat);
8039 let currentChunkPos = this.writer.getPos() + movieBoxSize + mdatSize;
8040 for (const chunk of this.finalizedChunks) {
8041 chunk.offset = currentChunkPos;
8042 for (const { data } of chunk.samples) {
8043 assert(data);
8044 currentChunkPos += data.byteLength;
8045 mdatSize += data.byteLength;
8046 }
8047 }
8048 if (currentChunkPos < 2 ** 32)
8049 break;
8050 if (mdatSize >= 2 ** 32)
8051 this.mdat.largeSize = true;
8052 }
8053 if (this.format._options.onMoov) {
8054 this.writer.startTrackingWrites();
8055 }
8056 const movieBox = moov(this);
8057 this.boxWriter.writeBox(movieBox);
8058 if (this.format._options.onMoov) {
8059 const { data, start } = this.writer.stopTrackingWrites();
8060 this.format._options.onMoov(data, start);
8061 }
8062 if (this.format._options.onMdat) {
8063 this.writer.startTrackingWrites();
8064 }
8065 this.mdat.size = mdatSize;
8066 this.boxWriter.writeBox(this.mdat);
8067 for (const chunk of this.finalizedChunks) {
8068 for (const sample of chunk.samples) {
8069 assert(sample.data);
8070 this.writer.write(sample.data);
8071 sample.data = null;
8072 }
8073 }
8074 if (this.format._options.onMdat) {
8075 const { data, start } = this.writer.stopTrackingWrites();
8076 this.format._options.onMdat(data, start);
8077 }
8078 } else if (this.isFragmented) {
8079 if (this.isCmaf) {
8080 const contentSize = this.segmentHeaderSize !== null ? this.writer.getPos() - this.segmentHeaderSize : 0;
8081 this.writer.seek(0);
8082 this.boxWriter.writeBox(styp());
8083 this.boxWriter.writeBox(sidx(this, contentSize));
8084 } else {
8085 const startPos = this.writer.getPos();
8086 const mfraBox = mfra(this.trackDatas);
8087 this.boxWriter.writeBox(mfraBox);
8088 const mfraBoxSize = this.writer.getPos() - startPos;
8089 this.writer.seek(this.writer.getPos() - 4);
8090 this.boxWriter.writeU32(mfraBoxSize);
8091 }
8092 } else {
8093 assert(this.mdat);
8094 const mdatPos = this.boxWriter.offsets.get(this.mdat);
8095 assert(mdatPos !== void 0);
8096 const mdatSize = this.writer.getPos() - mdatPos;
8097 this.mdat.size = mdatSize;
8098 this.mdat.largeSize = mdatSize >= 2 ** 32;
8099 this.boxWriter.patchBox(this.mdat);
8100 if (this.format._options.onMdat) {
8101 const { data, start } = this.writer.stopTrackingWrites();
8102 this.format._options.onMdat(data, start);
8103 }
8104 const movieBox = moov(this);
8105 if (this.fastStart === "reserve") {
8106 assert(this.ftypSize !== null);
8107 this.writer.seek(this.ftypSize);
8108 if (this.format._options.onMoov) {
8109 this.writer.startTrackingWrites();
8110 }
8111 this.boxWriter.writeBox(movieBox);
8112 const remainingSpace = this.boxWriter.offsets.get(this.mdat) - this.writer.getPos();
8113 this.boxWriter.writeBox(free(remainingSpace));
8114 } else {
8115 if (this.format._options.onMoov) {
8116 this.writer.startTrackingWrites();
8117 }
8118 this.boxWriter.writeBox(movieBox);
8119 }
8120 if (this.format._options.onMoov) {
8121 const { data, start } = this.writer.stopTrackingWrites();
8122 this.format._options.onMoov(data, start);
8123 }
8124 }
8125 release();
8126 }
8127 };
8128
8129 // node_modules/mediabunny/dist/modules/src/matroska/matroska-muxer.js
8130 var MIN_CLUSTER_TIMESTAMP_MS = -(2 ** 15);
8131 var MAX_CLUSTER_TIMESTAMP_MS = 2 ** 15 - 1;
8132 var APP_NAME = "Mediabunny";
8133 var SEGMENT_SIZE_BYTES = 6;
8134 var CLUSTER_SIZE_BYTES = 5;
8135 var TRACK_TYPE_MAP = {
8136 video: 1,
8137 audio: 2,
8138 subtitle: 17
8139 };
8140 var MatroskaMuxer = class extends Muxer {
8141 constructor(output, format) {
8142 super(output);
8143 this.trackDatas = [];
8144 this.allTracksKnown = promiseWithResolvers();
8145 this.segment = null;
8146 this.segmentInfo = null;
8147 this.seekHead = null;
8148 this.tracksElement = null;
8149 this.tagsElement = null;
8150 this.attachmentsElement = null;
8151 this.segmentDuration = null;
8152 this.cues = null;
8153 this.currentCluster = null;
8154 this.currentClusterStartMsTimestamp = null;
8155 this.currentClusterMaxMsTimestamp = null;
8156 this.trackDatasInCurrentCluster = /* @__PURE__ */ new Map();
8157 this.startTimestamp = Infinity;
8158 this.endTimestamp = -Infinity;
8159 this.format = format;
8160 }
8161 async start() {
8162 const release = await this.mutex.acquire();
8163 this.writer = await this.output._getRootWriter(!!this.format._options.appendOnly);
8164 this.ebmlWriter = new EBMLWriter(this.writer);
8165 this.writeEBMLHeader();
8166 this.createSegmentInfo();
8167 this.createCues();
8168 await this.writer.flush();
8169 release();
8170 }
8171 writeEBMLHeader() {
8172 if (this.format._options.onEbmlHeader) {
8173 this.writer.startTrackingWrites();
8174 }
8175 const ebmlHeader = { id: EBMLId.EBML, data: [
8176 { id: EBMLId.EBMLVersion, data: 1 },
8177 { id: EBMLId.EBMLReadVersion, data: 1 },
8178 { id: EBMLId.EBMLMaxIDLength, data: 4 },
8179 { id: EBMLId.EBMLMaxSizeLength, data: 8 },
8180 { id: EBMLId.DocType, data: this.format instanceof WebMOutputFormat ? "webm" : "matroska" },
8181 { id: EBMLId.DocTypeVersion, data: 2 },
8182 { id: EBMLId.DocTypeReadVersion, data: 2 }
8183 ] };
8184 this.ebmlWriter.writeEBML(ebmlHeader);
8185 if (this.format._options.onEbmlHeader) {
8186 const { data, start } = this.writer.stopTrackingWrites();
8187 this.format._options.onEbmlHeader(data, start);
8188 }
8189 }
8190 /**
8191 * Creates a SeekHead element which is positioned near the start of the file and allows the media player to seek to
8192 * relevant sections more easily. Since we don't know the positions of those sections yet, we'll set them later.
8193 */
8194 maybeCreateSeekHead(writeOffsets) {
8195 if (this.format._options.appendOnly) {
8196 return;
8197 }
8198 const kaxCues = new Uint8Array([28, 83, 187, 107]);
8199 const kaxInfo = new Uint8Array([21, 73, 169, 102]);
8200 const kaxTracks = new Uint8Array([22, 84, 174, 107]);
8201 const kaxAttachments = new Uint8Array([25, 65, 164, 105]);
8202 const kaxTags = new Uint8Array([18, 84, 195, 103]);
8203 const seekHead = { id: EBMLId.SeekHead, data: [
8204 { id: EBMLId.Seek, data: [
8205 { id: EBMLId.SeekID, data: kaxCues },
8206 {
8207 id: EBMLId.SeekPosition,
8208 size: 5,
8209 data: writeOffsets ? this.ebmlWriter.offsets.get(this.cues) - this.segmentDataOffset : 0
8210 }
8211 ] },
8212 { id: EBMLId.Seek, data: [
8213 { id: EBMLId.SeekID, data: kaxInfo },
8214 {
8215 id: EBMLId.SeekPosition,
8216 size: 5,
8217 data: writeOffsets ? this.ebmlWriter.offsets.get(this.segmentInfo) - this.segmentDataOffset : 0
8218 }
8219 ] },
8220 { id: EBMLId.Seek, data: [
8221 { id: EBMLId.SeekID, data: kaxTracks },
8222 {
8223 id: EBMLId.SeekPosition,
8224 size: 5,
8225 data: writeOffsets ? this.ebmlWriter.offsets.get(this.tracksElement) - this.segmentDataOffset : 0
8226 }
8227 ] },
8228 this.attachmentsElement ? { id: EBMLId.Seek, data: [
8229 { id: EBMLId.SeekID, data: kaxAttachments },
8230 {
8231 id: EBMLId.SeekPosition,
8232 size: 5,
8233 data: writeOffsets ? this.ebmlWriter.offsets.get(this.attachmentsElement) - this.segmentDataOffset : 0
8234 }
8235 ] } : null,
8236 this.tagsElement ? { id: EBMLId.Seek, data: [
8237 { id: EBMLId.SeekID, data: kaxTags },
8238 {
8239 id: EBMLId.SeekPosition,
8240 size: 5,
8241 data: writeOffsets ? this.ebmlWriter.offsets.get(this.tagsElement) - this.segmentDataOffset : 0
8242 }
8243 ] } : null
8244 ] };
8245 this.seekHead = seekHead;
8246 }
8247 createSegmentInfo() {
8248 const segmentDuration = { id: EBMLId.Duration, data: new EBMLFloat64(0) };
8249 this.segmentDuration = segmentDuration;
8250 const segmentInfo = { id: EBMLId.Info, data: [
8251 { id: EBMLId.TimestampScale, data: 1e6 },
8252 { id: EBMLId.MuxingApp, data: APP_NAME },
8253 { id: EBMLId.WritingApp, data: APP_NAME },
8254 !this.format._options.appendOnly ? segmentDuration : null
8255 ] };
8256 this.segmentInfo = segmentInfo;
8257 }
8258 createTracks() {
8259 const tracksElement = { id: EBMLId.Tracks, data: [] };
8260 this.tracksElement = tracksElement;
8261 for (const trackData of this.trackDatas) {
8262 const codecId = CODEC_STRING_MAP[trackData.track.source._codec];
8263 assert(codecId);
8264 let seekPreRollNs = 0;
8265 if (trackData.type === "audio" && trackData.track.source._codec === "opus") {
8266 seekPreRollNs = 1e6 * 80;
8267 const description = trackData.info.decoderConfig.description;
8268 if (description) {
8269 const bytes2 = toUint8Array(description);
8270 const header = parseOpusIdentificationHeader(bytes2);
8271 seekPreRollNs = Math.round(1e9 * (header.preSkip / OPUS_SAMPLE_RATE));
8272 }
8273 }
8274 tracksElement.data.push({ id: EBMLId.TrackEntry, data: [
8275 { id: EBMLId.TrackNumber, data: trackData.track.id },
8276 { id: EBMLId.TrackUID, data: trackData.track.id },
8277 { id: EBMLId.TrackType, data: TRACK_TYPE_MAP[trackData.type] },
8278 trackData.track.metadata.disposition?.default === false ? { id: EBMLId.FlagDefault, data: 0 } : null,
8279 trackData.track.metadata.disposition?.forced ? { id: EBMLId.FlagForced, data: 1 } : null,
8280 trackData.track.metadata.disposition?.hearingImpaired ? { id: EBMLId.FlagHearingImpaired, data: 1 } : null,
8281 trackData.track.metadata.disposition?.visuallyImpaired ? { id: EBMLId.FlagVisualImpaired, data: 1 } : null,
8282 trackData.track.metadata.disposition?.original ? { id: EBMLId.FlagOriginal, data: 1 } : null,
8283 trackData.track.metadata.disposition?.commentary ? { id: EBMLId.FlagCommentary, data: 1 } : null,
8284 { id: EBMLId.FlagLacing, data: 0 },
8285 { id: EBMLId.Language, data: trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE },
8286 { id: EBMLId.CodecID, data: codecId },
8287 { id: EBMLId.CodecDelay, data: 0 },
8288 { id: EBMLId.SeekPreRoll, data: seekPreRollNs },
8289 trackData.track.metadata.name !== void 0 ? { id: EBMLId.Name, data: new EBMLUnicodeString(trackData.track.metadata.name) } : null,
8290 trackData.type === "video" ? this.videoSpecificTrackInfo(trackData) : null,
8291 trackData.type === "audio" ? this.audioSpecificTrackInfo(trackData) : null,
8292 trackData.type === "subtitle" ? this.subtitleSpecificTrackInfo(trackData) : null
8293 ] });
8294 }
8295 }
8296 videoSpecificTrackInfo(trackData) {
8297 const { frameRate, rotation } = trackData.track.metadata;
8298 const elements = [
8299 trackData.info.decoderConfig.description ? {
8300 id: EBMLId.CodecPrivate,
8301 data: toUint8Array(trackData.info.decoderConfig.description)
8302 } : null,
8303 frameRate ? {
8304 id: EBMLId.DefaultDuration,
8305 data: 1e9 / frameRate
8306 } : null
8307 ];
8308 const flippedRotation = rotation ? normalizeRotation(-rotation) : 0;
8309 const hasNonSquarePixelAspectRatio = !!trackData.info.aspectRatio && trackData.info.aspectRatio.num * trackData.info.height !== trackData.info.aspectRatio.den * trackData.info.width;
8310 const colorSpace = trackData.info.decoderConfig.colorSpace;
8311 const videoElement = { id: EBMLId.Video, data: [
8312 { id: EBMLId.PixelWidth, data: trackData.info.width },
8313 { id: EBMLId.PixelHeight, data: trackData.info.height },
8314 hasNonSquarePixelAspectRatio ? { id: EBMLId.DisplayWidth, data: trackData.info.aspectRatio.num } : null,
8315 hasNonSquarePixelAspectRatio ? { id: EBMLId.DisplayHeight, data: trackData.info.aspectRatio.den } : null,
8316 hasNonSquarePixelAspectRatio ? { id: EBMLId.DisplayUnit, data: 3 } : null,
8317 // 3 = display aspect ratio
8318 trackData.info.alphaMode ? { id: EBMLId.AlphaMode, data: 1 } : null,
8319 colorSpaceIsComplete(colorSpace) ? {
8320 id: EBMLId.Colour,
8321 data: [
8322 {
8323 id: EBMLId.MatrixCoefficients,
8324 data: MATRIX_COEFFICIENTS_MAP[colorSpace.matrix]
8325 },
8326 {
8327 id: EBMLId.TransferCharacteristics,
8328 data: TRANSFER_CHARACTERISTICS_MAP[colorSpace.transfer]
8329 },
8330 {
8331 id: EBMLId.Primaries,
8332 data: COLOR_PRIMARIES_MAP[colorSpace.primaries]
8333 },
8334 {
8335 id: EBMLId.Range,
8336 data: colorSpace.fullRange ? 2 : 1
8337 }
8338 ]
8339 } : null,
8340 flippedRotation ? {
8341 id: EBMLId.Projection,
8342 data: [
8343 {
8344 id: EBMLId.ProjectionType,
8345 data: 0
8346 // rectangular
8347 },
8348 {
8349 id: EBMLId.ProjectionPoseRoll,
8350 data: new EBMLFloat32((flippedRotation + 180) % 360 - 180)
8351 // [0, 270] -> [-180, 90]
8352 }
8353 ]
8354 } : null
8355 ] };
8356 elements.push(videoElement);
8357 return elements;
8358 }
8359 audioSpecificTrackInfo(trackData) {
8360 const pcmInfo = PCM_AUDIO_CODECS.includes(trackData.track.source._codec) ? parsePcmCodec(trackData.track.source._codec) : null;
8361 return [
8362 trackData.info.decoderConfig.description ? {
8363 id: EBMLId.CodecPrivate,
8364 data: toUint8Array(trackData.info.decoderConfig.description)
8365 } : null,
8366 { id: EBMLId.Audio, data: [
8367 { id: EBMLId.SamplingFrequency, data: new EBMLFloat32(trackData.info.sampleRate) },
8368 { id: EBMLId.Channels, data: trackData.info.numberOfChannels },
8369 pcmInfo ? { id: EBMLId.BitDepth, data: 8 * pcmInfo.sampleSize } : null
8370 ] }
8371 ];
8372 }
8373 subtitleSpecificTrackInfo(trackData) {
8374 return [
8375 { id: EBMLId.CodecPrivate, data: textEncoder.encode(trackData.info.config.description) }
8376 ];
8377 }
8378 maybeCreateTags() {
8379 const simpleTags = [];
8380 const addSimpleTag = (key, value) => {
8381 simpleTags.push({ id: EBMLId.SimpleTag, data: [
8382 { id: EBMLId.TagName, data: new EBMLUnicodeString(key) },
8383 typeof value === "string" ? { id: EBMLId.TagString, data: new EBMLUnicodeString(value) } : { id: EBMLId.TagBinary, data: value }
8384 ] });
8385 };
8386 const metadataTags = this.output._metadataTags;
8387 const writtenTags = /* @__PURE__ */ new Set();
8388 for (const { key, value } of keyValueIterator(metadataTags)) {
8389 switch (key) {
8390 case "title":
8391 {
8392 addSimpleTag("TITLE", value);
8393 writtenTags.add("TITLE");
8394 }
8395 ;
8396 break;
8397 case "description":
8398 {
8399 addSimpleTag("DESCRIPTION", value);
8400 writtenTags.add("DESCRIPTION");
8401 }
8402 ;
8403 break;
8404 case "artist":
8405 {
8406 addSimpleTag("ARTIST", value);
8407 writtenTags.add("ARTIST");
8408 }
8409 ;
8410 break;
8411 case "album":
8412 {
8413 addSimpleTag("ALBUM", value);
8414 writtenTags.add("ALBUM");
8415 }
8416 ;
8417 break;
8418 case "albumArtist":
8419 {
8420 addSimpleTag("ALBUM_ARTIST", value);
8421 writtenTags.add("ALBUM_ARTIST");
8422 }
8423 ;
8424 break;
8425 case "genre":
8426 {
8427 addSimpleTag("GENRE", value);
8428 writtenTags.add("GENRE");
8429 }
8430 ;
8431 break;
8432 case "comment":
8433 {
8434 addSimpleTag("COMMENT", value);
8435 writtenTags.add("COMMENT");
8436 }
8437 ;
8438 break;
8439 case "lyrics":
8440 {
8441 addSimpleTag("LYRICS", value);
8442 writtenTags.add("LYRICS");
8443 }
8444 ;
8445 break;
8446 case "date":
8447 {
8448 addSimpleTag("DATE", value.toISOString().slice(0, 10));
8449 writtenTags.add("DATE");
8450 }
8451 ;
8452 break;
8453 case "trackNumber":
8454 {
8455 const string = metadataTags.tracksTotal !== void 0 ? \`\${value}/\${metadataTags.tracksTotal}\` : value.toString();
8456 addSimpleTag("PART_NUMBER", string);
8457 writtenTags.add("PART_NUMBER");
8458 }
8459 ;
8460 break;
8461 case "discNumber":
8462 {
8463 const string = metadataTags.discsTotal !== void 0 ? \`\${value}/\${metadataTags.discsTotal}\` : value.toString();
8464 addSimpleTag("DISC", string);
8465 writtenTags.add("DISC");
8466 }
8467 ;
8468 break;
8469 case "tracksTotal":
8470 case "discsTotal":
8471 {
8472 }
8473 ;
8474 break;
8475 case "images":
8476 case "raw":
8477 {
8478 }
8479 ;
8480 break;
8481 default:
8482 assertNever(key);
8483 }
8484 }
8485 if (metadataTags.raw) {
8486 for (const key in metadataTags.raw) {
8487 const value = metadataTags.raw[key];
8488 if (value == null || writtenTags.has(key)) {
8489 continue;
8490 }
8491 if (typeof value === "string" || value instanceof Uint8Array) {
8492 addSimpleTag(key, value);
8493 }
8494 }
8495 }
8496 if (simpleTags.length === 0) {
8497 return;
8498 }
8499 this.tagsElement = {
8500 id: EBMLId.Tags,
8501 data: [{ id: EBMLId.Tag, data: [
8502 { id: EBMLId.Targets, data: [
8503 { id: EBMLId.TargetTypeValue, data: 50 },
8504 { id: EBMLId.TargetType, data: "MOVIE" }
8505 ] },
8506 ...simpleTags
8507 ] }]
8508 };
8509 }
8510 maybeCreateAttachments() {
8511 const metadataTags = this.output._metadataTags;
8512 const elements = [];
8513 const existingFileUids = /* @__PURE__ */ new Set();
8514 const images = metadataTags.images ?? [];
8515 for (const image of images) {
8516 let imageName = image.name;
8517 if (imageName === void 0) {
8518 const baseName = image.kind === "coverFront" ? "cover" : image.kind === "coverBack" ? "back" : "image";
8519 imageName = baseName + (imageMimeTypeToExtension(image.mimeType) ?? "");
8520 }
8521 let fileUid;
8522 while (true) {
8523 fileUid = 0n;
8524 for (let i2 = 0; i2 < 8; i2++) {
8525 fileUid <<= 8n;
8526 fileUid |= BigInt(Math.floor(Math.random() * 256));
8527 }
8528 if (fileUid !== 0n && !existingFileUids.has(fileUid)) {
8529 break;
8530 }
8531 }
8532 existingFileUids.add(fileUid);
8533 elements.push({
8534 id: EBMLId.AttachedFile,
8535 data: [
8536 image.description !== void 0 ? { id: EBMLId.FileDescription, data: new EBMLUnicodeString(image.description) } : null,
8537 { id: EBMLId.FileName, data: new EBMLUnicodeString(imageName) },
8538 { id: EBMLId.FileMediaType, data: image.mimeType },
8539 { id: EBMLId.FileData, data: image.data },
8540 { id: EBMLId.FileUID, data: fileUid }
8541 ]
8542 });
8543 }
8544 for (const [key, value] of Object.entries(metadataTags.raw ?? {})) {
8545 if (!(value instanceof AttachedFile)) {
8546 continue;
8547 }
8548 const keyIsNumeric = /^\\d+$/.test(key);
8549 if (!keyIsNumeric) {
8550 continue;
8551 }
8552 if (images.find((x) => x.mimeType === value.mimeType && uint8ArraysAreEqual(x.data, value.data))) {
8553 continue;
8554 }
8555 elements.push({
8556 id: EBMLId.AttachedFile,
8557 data: [
8558 value.description !== void 0 ? { id: EBMLId.FileDescription, data: new EBMLUnicodeString(value.description) } : null,
8559 { id: EBMLId.FileName, data: new EBMLUnicodeString(value.name ?? "") },
8560 { id: EBMLId.FileMediaType, data: value.mimeType ?? "" },
8561 { id: EBMLId.FileData, data: value.data },
8562 { id: EBMLId.FileUID, data: BigInt(key) }
8563 ]
8564 });
8565 }
8566 if (elements.length === 0) {
8567 return;
8568 }
8569 this.attachmentsElement = { id: EBMLId.Attachments, data: elements };
8570 }
8571 createSegment() {
8572 this.createTracks();
8573 this.maybeCreateTags();
8574 this.maybeCreateAttachments();
8575 this.maybeCreateSeekHead(false);
8576 const segment = {
8577 id: EBMLId.Segment,
8578 size: this.format._options.appendOnly ? -1 : SEGMENT_SIZE_BYTES,
8579 data: [
8580 this.seekHead,
8581 // null if append-only
8582 this.segmentInfo,
8583 this.tracksElement,
8584 // Matroska spec says put this at the end of the file, but I think placing it before the first cluster
8585 // makes more sense, and FFmpeg agrees (argumentum ad ffmpegum fallacy)
8586 this.attachmentsElement,
8587 this.tagsElement
8588 ]
8589 };
8590 this.segment = segment;
8591 if (this.format._options.onSegmentHeader) {
8592 this.writer.startTrackingWrites();
8593 }
8594 this.ebmlWriter.writeEBML(segment);
8595 if (this.format._options.onSegmentHeader) {
8596 const { data, start } = this.writer.stopTrackingWrites();
8597 this.format._options.onSegmentHeader(data, start);
8598 }
8599 }
8600 createCues() {
8601 this.cues = { id: EBMLId.Cues, data: [] };
8602 }
8603 get segmentDataOffset() {
8604 assert(this.segment);
8605 return this.ebmlWriter.dataOffsets.get(this.segment);
8606 }
8607 allTracksAreKnown() {
8608 for (const track of this.output._tracks) {
8609 if (!track.source._closed && !this.trackDatas.some((x) => x.track === track)) {
8610 return false;
8611 }
8612 }
8613 return true;
8614 }
8615 async getMimeType() {
8616 await this.allTracksKnown.promise;
8617 const codecStrings = this.trackDatas.map((trackData) => {
8618 if (trackData.type === "video") {
8619 return trackData.info.decoderConfig.codec;
8620 } else if (trackData.type === "audio") {
8621 return trackData.info.decoderConfig.codec;
8622 } else {
8623 const map = {
8624 webvtt: "wvtt"
8625 };
8626 return map[trackData.track.source._codec];
8627 }
8628 });
8629 return buildMatroskaMimeType({
8630 isWebM: this.format instanceof WebMOutputFormat,
8631 hasVideo: this.trackDatas.some((x) => x.type === "video"),
8632 hasAudio: this.trackDatas.some((x) => x.type === "audio"),
8633 codecStrings
8634 });
8635 }
8636 getVideoTrackData(track, packet, meta) {
8637 const existingTrackData = this.trackDatas.find((x) => x.track === track);
8638 if (existingTrackData) {
8639 return existingTrackData;
8640 }
8641 validateVideoChunkMetadata(meta);
8642 assert(meta);
8643 assert(meta.decoderConfig);
8644 assert(meta.decoderConfig.codedWidth !== void 0);
8645 assert(meta.decoderConfig.codedHeight !== void 0);
8646 const displayAspectWidth = meta.decoderConfig.displayAspectWidth;
8647 const displayAspectHeight = meta.decoderConfig.displayAspectHeight;
8648 const aspectRatio = displayAspectWidth === void 0 || displayAspectHeight === void 0 ? null : simplifyRational({
8649 num: displayAspectWidth,
8650 den: displayAspectHeight
8651 });
8652 const newTrackData = {
8653 track,
8654 type: "video",
8655 info: {
8656 width: meta.decoderConfig.codedWidth,
8657 height: meta.decoderConfig.codedHeight,
8658 aspectRatio,
8659 decoderConfig: meta.decoderConfig,
8660 alphaMode: !!packet.sideData.alpha
8661 // The first packet determines if this track has alpha or not
8662 },
8663 chunkQueue: [],
8664 lastWrittenMsTimestamp: null,
8665 closed: false
8666 };
8667 if (track.source._codec === "vp9") {
8668 newTrackData.info.decoderConfig = {
8669 ...newTrackData.info.decoderConfig,
8670 description: new Uint8Array(generateVp9CodecConfigurationFromCodecString(newTrackData.info.decoderConfig.codec))
8671 };
8672 } else if (track.source._codec === "av1") {
8673 newTrackData.info.decoderConfig = {
8674 ...newTrackData.info.decoderConfig,
8675 description: new Uint8Array(generateAv1CodecConfigurationFromCodecString(newTrackData.info.decoderConfig.codec))
8676 };
8677 }
8678 this.trackDatas.push(newTrackData);
8679 this.trackDatas.sort((a2, b) => a2.track.id - b.track.id);
8680 if (this.allTracksAreKnown()) {
8681 this.allTracksKnown.resolve();
8682 }
8683 return newTrackData;
8684 }
8685 getAudioTrackData(track, packet, meta) {
8686 const existingTrackData = this.trackDatas.find((x) => x.track === track);
8687 if (existingTrackData) {
8688 return existingTrackData;
8689 }
8690 validateAudioChunkMetadata(meta);
8691 assert(meta);
8692 assert(meta.decoderConfig);
8693 const decoderConfig = { ...meta.decoderConfig };
8694 let requiresAdtsStripping = false;
8695 if (track.source._codec === "aac" && !decoderConfig.description) {
8696 const adtsFrame = readAdtsFrameHeader(FileSlice.tempFromBytes(packet.data));
8697 if (!adtsFrame) {
8698 throw new Error("Couldn't parse ADTS header from the AAC packet. Make sure the packets are in ADTS format (as specified in ISO 13818-7) when not providing a description, or provide a description (must be an AudioSpecificConfig as specified in ISO 14496-3) and ensure the packets are raw AAC data.");
8699 }
8700 const sampleRate = aacFrequencyTable[adtsFrame.samplingFrequencyIndex];
8701 const numberOfChannels = aacChannelMap[adtsFrame.channelConfiguration];
8702 if (sampleRate === void 0 || numberOfChannels === void 0) {
8703 throw new Error("Invalid ADTS frame header.");
8704 }
8705 decoderConfig.description = buildAacAudioSpecificConfig({
8706 objectType: adtsFrame.objectType,
8707 sampleRate,
8708 numberOfChannels
8709 });
8710 requiresAdtsStripping = true;
8711 }
8712 const newTrackData = {
8713 track,
8714 type: "audio",
8715 info: {
8716 numberOfChannels: meta.decoderConfig.numberOfChannels,
8717 sampleRate: meta.decoderConfig.sampleRate,
8718 decoderConfig,
8719 requiresAdtsStripping
8720 },
8721 chunkQueue: [],
8722 lastWrittenMsTimestamp: null,
8723 closed: false
8724 };
8725 this.trackDatas.push(newTrackData);
8726 this.trackDatas.sort((a2, b) => a2.track.id - b.track.id);
8727 if (this.allTracksAreKnown()) {
8728 this.allTracksKnown.resolve();
8729 }
8730 return newTrackData;
8731 }
8732 getSubtitleTrackData(track, meta) {
8733 const existingTrackData = this.trackDatas.find((x) => x.track === track);
8734 if (existingTrackData) {
8735 return existingTrackData;
8736 }
8737 validateSubtitleMetadata(meta);
8738 assert(meta);
8739 assert(meta.config);
8740 const newTrackData = {
8741 track,
8742 type: "subtitle",
8743 info: {
8744 config: meta.config
8745 },
8746 chunkQueue: [],
8747 lastWrittenMsTimestamp: null,
8748 closed: false
8749 };
8750 this.trackDatas.push(newTrackData);
8751 this.trackDatas.sort((a2, b) => a2.track.id - b.track.id);
8752 if (this.allTracksAreKnown()) {
8753 this.allTracksKnown.resolve();
8754 }
8755 return newTrackData;
8756 }
8757 async addEncodedVideoPacket(track, packet, meta) {
8758 const release = await this.mutex.acquire();
8759 try {
8760 const trackData = this.getVideoTrackData(track, packet, meta);
8761 const isKeyFrame = packet.type === "key";
8762 this.validateTimestamp(trackData.track, packet.timestamp, isKeyFrame);
8763 let timestamp = packet.timestamp;
8764 let duration = packet.duration;
8765 if (track.metadata.frameRate !== void 0) {
8766 timestamp = roundToDivisor(timestamp, track.metadata.frameRate);
8767 duration = roundToDivisor(duration, track.metadata.frameRate);
8768 }
8769 const additions = trackData.info.alphaMode ? packet.sideData.alpha ?? null : null;
8770 const videoChunk = this.createInternalChunk(packet.data, timestamp, duration, packet.type, additions);
8771 if (track.source._codec === "vp9")
8772 this.fixVP9ColorSpace(trackData, videoChunk);
8773 trackData.chunkQueue.push(videoChunk);
8774 await this.interleaveChunks();
8775 } finally {
8776 release();
8777 }
8778 }
8779 async addEncodedAudioPacket(track, packet, meta) {
8780 const release = await this.mutex.acquire();
8781 try {
8782 const trackData = this.getAudioTrackData(track, packet, meta);
8783 let packetData = packet.data;
8784 if (trackData.info.requiresAdtsStripping) {
8785 const adtsFrame = readAdtsFrameHeader(FileSlice.tempFromBytes(packetData));
8786 if (!adtsFrame) {
8787 throw new Error("Expected ADTS frame, didn't get one.");
8788 }
8789 const headerLength = adtsFrame.crcCheck === null ? MIN_ADTS_FRAME_HEADER_SIZE : MAX_ADTS_FRAME_HEADER_SIZE;
8790 packetData = packetData.subarray(headerLength);
8791 }
8792 const isKeyFrame = packet.type === "key";
8793 this.validateTimestamp(trackData.track, packet.timestamp, isKeyFrame);
8794 const audioChunk = this.createInternalChunk(packetData, packet.timestamp, packet.duration, packet.type);
8795 trackData.chunkQueue.push(audioChunk);
8796 await this.interleaveChunks();
8797 } finally {
8798 release();
8799 }
8800 }
8801 async addSubtitleCue(track, cue, meta) {
8802 const release = await this.mutex.acquire();
8803 try {
8804 const trackData = this.getSubtitleTrackData(track, meta);
8805 this.validateTimestamp(trackData.track, cue.timestamp, true);
8806 let bodyText = cue.text;
8807 const timestampMs = Math.round(cue.timestamp * 1e3);
8808 inlineTimestampRegex.lastIndex = 0;
8809 bodyText = bodyText.replace(inlineTimestampRegex, (match) => {
8810 const time = parseSubtitleTimestamp(match.slice(1, -1));
8811 const offsetTime = time - timestampMs;
8812 return \`<\${formatSubtitleTimestamp(offsetTime)}>\`;
8813 });
8814 const body = textEncoder.encode(bodyText);
8815 const additions = \`\${cue.settings ?? ""}
8816 \${cue.identifier ?? ""}
8817 \${cue.notes ?? ""}\`;
8818 const subtitleChunk = this.createInternalChunk(body, cue.timestamp, cue.duration, "key", additions.trim() ? textEncoder.encode(additions) : null);
8819 trackData.chunkQueue.push(subtitleChunk);
8820 await this.interleaveChunks();
8821 } finally {
8822 release();
8823 }
8824 }
8825 async interleaveChunks(isFinalCall = false) {
8826 if (!isFinalCall && !this.allTracksAreKnown()) {
8827 return;
8828 }
8829 outer: while (true) {
8830 let trackWithMinTimestamp = null;
8831 let minTimestamp = Infinity;
8832 for (const trackData of this.trackDatas) {
8833 if (!isFinalCall && trackData.chunkQueue.length === 0 && !trackData.closed) {
8834 break outer;
8835 }
8836 if (trackData.chunkQueue.length > 0 && trackData.chunkQueue[0].timestamp < minTimestamp) {
8837 trackWithMinTimestamp = trackData;
8838 minTimestamp = trackData.chunkQueue[0].timestamp;
8839 }
8840 }
8841 if (!trackWithMinTimestamp) {
8842 break;
8843 }
8844 const chunk = trackWithMinTimestamp.chunkQueue.shift();
8845 this.writeBlock(trackWithMinTimestamp, chunk);
8846 }
8847 if (!isFinalCall) {
8848 await this.writer.flush();
8849 }
8850 }
8851 /**
8852 * Due to [a bug in Chromium](https://bugs.chromium.org/p/chromium/issues/detail?id=1377842), VP9 streams often
8853 * lack color space information. This method patches in that information.
8854 */
8855 fixVP9ColorSpace(trackData, chunk) {
8856 if (chunk.type !== "key")
8857 return;
8858 if (!trackData.info.decoderConfig.colorSpace || !trackData.info.decoderConfig.colorSpace.matrix)
8859 return;
8860 const bitstream = new Bitstream(chunk.data);
8861 bitstream.skipBits(2);
8862 const profileLowBit = bitstream.readBits(1);
8863 const profileHighBit = bitstream.readBits(1);
8864 const profile = (profileHighBit << 1) + profileLowBit;
8865 if (profile === 3)
8866 bitstream.skipBits(1);
8867 const showExistingFrame = bitstream.readBits(1);
8868 if (showExistingFrame)
8869 return;
8870 const frameType = bitstream.readBits(1);
8871 if (frameType !== 0)
8872 return;
8873 bitstream.skipBits(2);
8874 const syncCode = bitstream.readBits(24);
8875 if (syncCode !== 4817730)
8876 return;
8877 if (profile >= 2)
8878 bitstream.skipBits(1);
8879 const colorSpaceID = {
8880 rgb: 7,
8881 bt709: 2,
8882 bt470bg: 1,
8883 smpte170m: 3
8884 }[trackData.info.decoderConfig.colorSpace.matrix];
8885 writeBits(chunk.data, bitstream.pos, bitstream.pos + 3, colorSpaceID);
8886 }
8887 /** Converts a read-only external chunk into an internal one for easier use. */
8888 createInternalChunk(data, timestamp, duration, type, additions = null) {
8889 const internalChunk = {
8890 data,
8891 type,
8892 timestamp,
8893 duration,
8894 additions
8895 };
8896 return internalChunk;
8897 }
8898 /** Writes a block containing media data to the file. */
8899 writeBlock(trackData, chunk) {
8900 if (!this.segment) {
8901 this.createSegment();
8902 }
8903 const msTimestamp = Math.round(1e3 * chunk.timestamp);
8904 const keyFrameQueuedEverywhere = this.trackDatas.every((otherTrackData) => {
8905 if (trackData === otherTrackData) {
8906 return chunk.type === "key";
8907 }
8908 const firstQueuedSample = otherTrackData.chunkQueue[0];
8909 if (firstQueuedSample) {
8910 return firstQueuedSample.type === "key";
8911 }
8912 return otherTrackData.closed;
8913 });
8914 let shouldCreateNewCluster = false;
8915 if (!this.currentCluster) {
8916 shouldCreateNewCluster = true;
8917 } else {
8918 assert(this.currentClusterStartMsTimestamp !== null);
8919 assert(this.currentClusterMaxMsTimestamp !== null);
8920 const relativeTimestamp2 = msTimestamp - this.currentClusterStartMsTimestamp;
8921 shouldCreateNewCluster = keyFrameQueuedEverywhere && msTimestamp > this.currentClusterMaxMsTimestamp && relativeTimestamp2 >= 1e3 * (this.format._options.minimumClusterDuration ?? 1) || relativeTimestamp2 > MAX_CLUSTER_TIMESTAMP_MS;
8922 }
8923 if (shouldCreateNewCluster) {
8924 this.createNewCluster(msTimestamp);
8925 }
8926 const relativeTimestamp = msTimestamp - this.currentClusterStartMsTimestamp;
8927 if (relativeTimestamp < MIN_CLUSTER_TIMESTAMP_MS) {
8928 return;
8929 }
8930 const prelude = new Uint8Array(4);
8931 const view2 = new DataView(prelude.buffer);
8932 view2.setUint8(0, 128 | trackData.track.id);
8933 view2.setInt16(1, relativeTimestamp, false);
8934 const msDuration = Math.round(1e3 * chunk.duration);
8935 if (!chunk.additions) {
8936 view2.setUint8(3, Number(chunk.type === "key") << 7);
8937 const simpleBlock = { id: EBMLId.SimpleBlock, data: [
8938 prelude,
8939 chunk.data
8940 ] };
8941 this.ebmlWriter.writeEBML(simpleBlock);
8942 } else {
8943 const blockGroup = { id: EBMLId.BlockGroup, data: [
8944 { id: EBMLId.Block, data: [
8945 prelude,
8946 chunk.data
8947 ] },
8948 chunk.type === "delta" ? {
8949 id: EBMLId.ReferenceBlock,
8950 data: new EBMLSignedInt(trackData.lastWrittenMsTimestamp - msTimestamp)
8951 } : null,
8952 chunk.additions ? { id: EBMLId.BlockAdditions, data: [
8953 { id: EBMLId.BlockMore, data: [
8954 { id: EBMLId.BlockAddID, data: 1 },
8955 // Some players expect BlockAddID to come first
8956 { id: EBMLId.BlockAdditional, data: chunk.additions }
8957 ] }
8958 ] } : null,
8959 msDuration > 0 ? { id: EBMLId.BlockDuration, data: msDuration } : null
8960 ] };
8961 this.ebmlWriter.writeEBML(blockGroup);
8962 }
8963 this.startTimestamp = Math.min(this.startTimestamp, msTimestamp);
8964 this.endTimestamp = Math.max(this.endTimestamp, msTimestamp + msDuration);
8965 trackData.lastWrittenMsTimestamp = msTimestamp;
8966 if (!this.trackDatasInCurrentCluster.has(trackData)) {
8967 this.trackDatasInCurrentCluster.set(trackData, {
8968 firstMsTimestamp: msTimestamp
8969 });
8970 }
8971 this.currentClusterMaxMsTimestamp = Math.max(this.currentClusterMaxMsTimestamp, msTimestamp);
8972 }
8973 /** Creates a new Cluster element to contain media chunks. */
8974 createNewCluster(msTimestamp) {
8975 if (this.currentCluster) {
8976 this.finalizeCurrentCluster();
8977 }
8978 if (this.format._options.onCluster) {
8979 this.writer.startTrackingWrites();
8980 }
8981 this.currentCluster = {
8982 id: EBMLId.Cluster,
8983 size: this.format._options.appendOnly ? -1 : CLUSTER_SIZE_BYTES,
8984 data: [
8985 { id: EBMLId.Timestamp, data: msTimestamp }
8986 ]
8987 };
8988 this.ebmlWriter.writeEBML(this.currentCluster);
8989 this.currentClusterStartMsTimestamp = msTimestamp;
8990 this.currentClusterMaxMsTimestamp = msTimestamp;
8991 this.trackDatasInCurrentCluster.clear();
8992 }
8993 finalizeCurrentCluster() {
8994 assert(this.currentCluster);
8995 if (!this.format._options.appendOnly) {
8996 const clusterSize = this.writer.getPos() - this.ebmlWriter.dataOffsets.get(this.currentCluster);
8997 const endPos = this.writer.getPos();
8998 this.writer.seek(this.ebmlWriter.offsets.get(this.currentCluster) + 4);
8999 this.ebmlWriter.writeVarInt(clusterSize, CLUSTER_SIZE_BYTES);
9000 this.writer.seek(endPos);
9001 }
9002 if (this.format._options.onCluster) {
9003 assert(this.currentClusterStartMsTimestamp !== null);
9004 const { data, start } = this.writer.stopTrackingWrites();
9005 this.format._options.onCluster(data, start, this.currentClusterStartMsTimestamp / 1e3);
9006 }
9007 const clusterOffsetFromSegment = this.ebmlWriter.offsets.get(this.currentCluster) - this.segmentDataOffset;
9008 const groupedByTimestamp = /* @__PURE__ */ new Map();
9009 for (const [trackData, { firstMsTimestamp }] of this.trackDatasInCurrentCluster) {
9010 if (!groupedByTimestamp.has(firstMsTimestamp)) {
9011 groupedByTimestamp.set(firstMsTimestamp, []);
9012 }
9013 groupedByTimestamp.get(firstMsTimestamp).push(trackData);
9014 }
9015 const groupedAndSortedByTimestamp = [...groupedByTimestamp.entries()].sort((a2, b) => a2[0] - b[0]);
9016 for (const [msTimestamp, trackDatas] of groupedAndSortedByTimestamp) {
9017 assert(this.cues);
9018 this.cues.data.push({ id: EBMLId.CuePoint, data: [
9019 { id: EBMLId.CueTime, data: msTimestamp },
9020 // Create CueTrackPositions for each track that starts at this timestamp
9021 ...trackDatas.map((trackData) => {
9022 return { id: EBMLId.CueTrackPositions, data: [
9023 { id: EBMLId.CueTrack, data: trackData.track.id },
9024 { id: EBMLId.CueClusterPosition, data: clusterOffsetFromSegment }
9025 ] };
9026 })
9027 ] });
9028 }
9029 }
9030 // eslint-disable-next-line @typescript-eslint/no-misused-promises
9031 async onTrackClose(track) {
9032 const release = await this.mutex.acquire();
9033 const trackData = this.trackDatas.find((x) => x.track === track);
9034 if (trackData) {
9035 trackData.closed = true;
9036 }
9037 if (this.allTracksAreKnown()) {
9038 this.allTracksKnown.resolve();
9039 }
9040 await this.interleaveChunks();
9041 release();
9042 }
9043 /** Finalizes the file, making it ready for use. Must be called after all media chunks have been added. */
9044 async finalize() {
9045 const release = await this.mutex.acquire();
9046 this.allTracksKnown.resolve();
9047 for (const trackData of this.trackDatas) {
9048 trackData.closed = true;
9049 }
9050 if (!this.segment) {
9051 this.createSegment();
9052 }
9053 await this.interleaveChunks(true);
9054 if (this.currentCluster) {
9055 this.finalizeCurrentCluster();
9056 }
9057 assert(this.cues);
9058 this.ebmlWriter.writeEBML(this.cues);
9059 if (!this.format._options.appendOnly) {
9060 const segmentSize = this.writer.getPos() - this.segmentDataOffset;
9061 this.writer.seek(this.ebmlWriter.offsets.get(this.segment) + 4);
9062 this.ebmlWriter.writeVarInt(segmentSize, SEGMENT_SIZE_BYTES);
9063 const duration = this.startTimestamp === Infinity ? 0 : this.endTimestamp - this.startTimestamp;
9064 this.segmentDuration.data = new EBMLFloat64(duration);
9065 this.writer.seek(this.ebmlWriter.offsets.get(this.segmentDuration));
9066 this.ebmlWriter.writeEBML(this.segmentDuration);
9067 assert(this.seekHead);
9068 this.writer.seek(this.ebmlWriter.offsets.get(this.seekHead));
9069 this.maybeCreateSeekHead(true);
9070 this.ebmlWriter.writeEBML(this.seekHead);
9071 }
9072 release();
9073 }
9074 };
9075
9076 // node_modules/mediabunny/dist/modules/src/media-source.js
9077 var MediaSource = class {
9078 constructor() {
9079 this._connectedTrack = null;
9080 this._closingPromise = null;
9081 this._closed = false;
9082 }
9083 /** @internal */
9084 _ensureValidAdd() {
9085 if (!this._connectedTrack) {
9086 throw new Error("Source is not connected to an output track.");
9087 }
9088 if (this._connectedTrack.output.state === "canceled") {
9089 throw new Error("Output has been canceled.");
9090 }
9091 if (this._connectedTrack.output.state === "finalizing" || this._connectedTrack.output.state === "finalized") {
9092 throw new Error("Output has been finalized.");
9093 }
9094 if (this._connectedTrack.output.state === "pending") {
9095 throw new Error("Output has not started.");
9096 }
9097 if (this._closed) {
9098 throw new Error("Source is closed.");
9099 }
9100 }
9101 /** @internal */
9102 async _start() {
9103 }
9104 /** @internal */
9105 // eslint-disable-next-line @typescript-eslint/no-unused-vars
9106 async _flushAndClose(forceClose) {
9107 }
9108 /**
9109 * Closes this source. This prevents future samples from being added and signals to the output file that no further
9110 * samples will come in for this track. Calling \`.close()\` is optional but recommended after adding the
9111 * last sample - for improved performance and reduced memory usage.
9112 */
9113 close() {
9114 if (this._closingPromise) {
9115 return;
9116 }
9117 const connectedTrack = this._connectedTrack;
9118 if (!connectedTrack) {
9119 throw new Error("Cannot call close without connecting the source to an output track.");
9120 }
9121 if (connectedTrack.output.state === "pending") {
9122 throw new Error("Cannot call close before output has been started.");
9123 }
9124 this._closingPromise = (async () => {
9125 await this._flushAndClose(false);
9126 this._closed = true;
9127 if (connectedTrack.output.state === "finalizing" || connectedTrack.output.state === "finalized") {
9128 return;
9129 }
9130 connectedTrack.output._muxer.onTrackClose(connectedTrack);
9131 })();
9132 }
9133 /** @internal */
9134 async _flushOrWaitForOngoingClose(forceClose) {
9135 return this._closingPromise ??= (async () => {
9136 await this._flushAndClose(forceClose);
9137 this._closed = true;
9138 })();
9139 }
9140 };
9141 var VideoSource = class extends MediaSource {
9142 /** Internal constructor. */
9143 constructor(codec) {
9144 super();
9145 this._connectedTrack = null;
9146 if (!VIDEO_CODECS.includes(codec)) {
9147 throw new TypeError(\`Invalid video codec '\${codec}'. Must be one of: \${VIDEO_CODECS.join(", ")}.\`);
9148 }
9149 this._codec = codec;
9150 }
9151 };
9152 var maybeEnsureIsKeyPacket = (track, packet) => {
9153 if (track.metadata.hasOnlyKeyPackets && packet.type !== "key") {
9154 throw new Error("Cannot add non-key packets to a hasOnlyKeyPackets video track.");
9155 }
9156 };
9157 var VideoEncoderWrapper = class {
9158 constructor(source, encodingConfig) {
9159 this.source = source;
9160 this.encodingConfig = encodingConfig;
9161 this.ensureEncoderPromise = null;
9162 this.encoderInitialized = false;
9163 this.encoder = null;
9164 this.muxer = null;
9165 this.lastMultipleOfKeyFrameInterval = -1;
9166 this.emittedEncoderPackets = 0;
9167 this.codedWidth = null;
9168 this.codedHeight = null;
9169 this.outputWidth = null;
9170 this.outputHeight = null;
9171 this.frameRateLastSample = null;
9172 this.frameRateLastTimestamp = null;
9173 this.frameRateLastEndTimestamp = null;
9174 this.preciseTimings = [];
9175 this.customEncoder = null;
9176 this.customEncoderCallSerializer = new CallSerializer();
9177 this.customEncoderQueueSize = 0;
9178 this.alphaEncoder = null;
9179 this.splitter = null;
9180 this.splitterCreationFailed = false;
9181 this.alphaFrameQueue = [];
9182 this.error = null;
9183 this.closed = false;
9184 this.lastMuxerPromise = Promise.resolve();
9185 }
9186 async add(videoSample, shouldClose, encodeOptions) {
9187 const originalSample = videoSample;
9188 try {
9189 this.checkForEncoderError();
9190 this.source._ensureValidAdd();
9191 const config = this.encodingConfig;
9192 const sizeChangeBehavior = config.sizeChangeBehavior ?? "deny";
9193 let isSizeChange = false;
9194 if (this.codedWidth !== null && this.codedHeight !== null) {
9195 if (videoSample.codedWidth !== this.codedWidth || videoSample.codedHeight !== this.codedHeight) {
9196 isSizeChange = true;
9197 if (sizeChangeBehavior === "deny") {
9198 throw new Error(\`Video sample size must remain constant. Expected \${this.codedWidth}x\${this.codedHeight}, got \${videoSample.codedWidth}x\${videoSample.codedHeight}. To allow the sample size to change over time, set \\\`sizeChangeBehavior\\\` to a value other than 'deny' in the encoding options.\`);
9199 }
9200 }
9201 } else {
9202 this.codedWidth = videoSample.codedWidth;
9203 this.codedHeight = videoSample.codedHeight;
9204 }
9205 const hasTransformConfig = config.transform?.width !== void 0 || config.transform?.height !== void 0 || config.transform?.rotate !== void 0 || config.transform?.crop !== void 0 || config.transform?.force === true;
9206 const needsTransform = hasTransformConfig || isSizeChange && sizeChangeBehavior !== "passThrough";
9207 if (needsTransform) {
9208 let targetWidth = config.transform?.width;
9209 let targetHeight = config.transform?.height;
9210 let appliedFit = config.transform?.fit ?? "fill";
9211 if (isSizeChange && sizeChangeBehavior !== "passThrough") {
9212 assert(this.outputWidth);
9213 assert(this.outputHeight);
9214 assert(sizeChangeBehavior !== "deny");
9215 targetWidth = this.outputWidth;
9216 targetHeight = this.outputHeight;
9217 appliedFit = sizeChangeBehavior;
9218 }
9219 const transformed = await videoSample.transform({
9220 width: targetWidth,
9221 height: targetHeight,
9222 roundDimensionsTo: 2,
9223 crop: config.transform?.crop,
9224 rotate: config.transform?.rotate,
9225 fit: appliedFit,
9226 alpha: config.alpha
9227 });
9228 if (this.outputWidth === null || this.outputHeight === null) {
9229 this.outputWidth = transformed.displayWidth;
9230 this.outputHeight = transformed.displayHeight;
9231 }
9232 if (shouldClose) {
9233 videoSample.close();
9234 }
9235 videoSample = transformed;
9236 shouldClose = true;
9237 } else {
9238 if (this.outputWidth === null || this.outputHeight === null) {
9239 this.outputWidth = videoSample.codedWidth;
9240 this.outputHeight = videoSample.codedHeight;
9241 }
9242 }
9243 const frameRate = config.transform?.frameRate;
9244 if (frameRate !== void 0) {
9245 const originalEndTimestamp = videoSample.timestamp + videoSample.duration;
9246 const alignedTimestamp = floorToDivisor(videoSample.timestamp, frameRate);
9247 if (this.frameRateLastSample !== null) {
9248 if (alignedTimestamp <= this.frameRateLastTimestamp) {
9249 this.frameRateLastSample.close();
9250 this.frameRateLastSample = videoSample.clone();
9251 this.frameRateLastEndTimestamp = originalEndTimestamp;
9252 return;
9253 } else {
9254 await this.padFrameRate(alignedTimestamp, encodeOptions);
9255 }
9256 }
9257 if (videoSample === originalSample) {
9258 videoSample = videoSample.clone();
9259 shouldClose = true;
9260 }
9261 videoSample.setTimestamp(alignedTimestamp);
9262 videoSample.setDuration(1 / frameRate);
9263 this.frameRateLastSample?.close();
9264 this.frameRateLastSample = videoSample.clone();
9265 this.frameRateLastTimestamp = alignedTimestamp;
9266 this.frameRateLastEndTimestamp = originalEndTimestamp;
9267 }
9268 await this.processAndEncode(videoSample, encodeOptions);
9269 } finally {
9270 if (shouldClose) {
9271 videoSample.close();
9272 }
9273 }
9274 }
9275 /**
9276 * Runs the process function (if any) and encodes the resulting samples.
9277 */
9278 async processAndEncode(videoSample, encodeOptions) {
9279 const config = this.encodingConfig;
9280 let samplesToEncode;
9281 if (config.transform?.process) {
9282 let processed = config.transform.process(videoSample);
9283 if (processed instanceof Promise) {
9284 processed = await processed;
9285 }
9286 if (processed === null) {
9287 return;
9288 }
9289 if (!Array.isArray(processed)) {
9290 processed = [processed];
9291 }
9292 samplesToEncode = processed.map((x) => {
9293 if (x instanceof VideoSample) {
9294 return x;
9295 }
9296 if (typeof VideoFrame !== "undefined" && x instanceof VideoFrame) {
9297 return new VideoSample(x);
9298 }
9299 return new VideoSample(x, {
9300 timestamp: videoSample.timestamp,
9301 duration: videoSample.duration
9302 });
9303 });
9304 } else {
9305 samplesToEncode = [videoSample];
9306 }
9307 try {
9308 for (const sampleToEncode of samplesToEncode) {
9309 if (!this.encoderInitialized) {
9310 if (!this.ensureEncoderPromise) {
9311 this.ensureEncoder(sampleToEncode);
9312 }
9313 if (!this.encoderInitialized) {
9314 await this.ensureEncoderPromise;
9315 }
9316 }
9317 assert(this.encoderInitialized);
9318 if (this.closed) {
9319 break;
9320 }
9321 const keyFrameInterval = this.encodingConfig.keyFrameInterval ?? 2;
9322 const multipleOfKeyFrameInterval = Math.floor(sampleToEncode.timestamp / keyFrameInterval);
9323 const mergedEncodeOptions = { ...sampleToEncode.encodeOptions, ...encodeOptions };
9324 const finalEncodeOptions = {
9325 ...mergedEncodeOptions,
9326 keyFrame: mergedEncodeOptions.keyFrame !== void 0 ? mergedEncodeOptions.keyFrame : keyFrameInterval === 0 || multipleOfKeyFrameInterval !== this.lastMultipleOfKeyFrameInterval
9327 };
9328 this.lastMultipleOfKeyFrameInterval = multipleOfKeyFrameInterval;
9329 this.encodingConfig.onEncodedSample?.(sampleToEncode);
9330 if (this.customEncoder) {
9331 this.customEncoderQueueSize++;
9332 const clonedSample = sampleToEncode.clone();
9333 const promise = this.customEncoderCallSerializer.call(() => this.customEncoder.encode(clonedSample, finalEncodeOptions)).then(() => this.customEncoderQueueSize--).catch((error) => this.error ??= error).finally(() => {
9334 clonedSample.close();
9335 });
9336 if (this.customEncoderQueueSize >= 4) {
9337 await promise;
9338 }
9339 } else {
9340 assert(this.encoder);
9341 const videoFrame = sampleToEncode.toVideoFrame();
9342 const preciseTimingIndex = binarySearchLessOrEqual(this.preciseTimings, videoFrame.timestamp, (x) => x.microsecondTimestamp);
9343 const existingEntry = preciseTimingIndex !== -1 ? this.preciseTimings[preciseTimingIndex] : null;
9344 if (existingEntry && existingEntry.microsecondTimestamp === videoFrame.timestamp) {
9345 if (existingEntry.timestamp !== sampleToEncode.timestamp) {
9346 existingEntry.timestampIsValid = false;
9347 }
9348 if (existingEntry.duration !== sampleToEncode.duration) {
9349 existingEntry.durationIsValid = false;
9350 }
9351 } else {
9352 this.preciseTimings.splice(preciseTimingIndex + 1, 0, {
9353 microsecondTimestamp: videoFrame.timestamp,
9354 timestamp: sampleToEncode.timestamp,
9355 duration: sampleToEncode.duration,
9356 timestampIsValid: true,
9357 durationIsValid: true
9358 });
9359 if (this.preciseTimings.length > 128) {
9360 this.preciseTimings.shift();
9361 }
9362 }
9363 if (!this.alphaEncoder) {
9364 this.encoder.encode(videoFrame, finalEncodeOptions);
9365 videoFrame.close();
9366 } else {
9367 const frameDefinitelyHasNoAlpha = !!videoFrame.format && !videoFrame.format.includes("A");
9368 if (frameDefinitelyHasNoAlpha || this.splitterCreationFailed) {
9369 this.alphaFrameQueue.push(null);
9370 this.encoder.encode(videoFrame, finalEncodeOptions);
9371 videoFrame.close();
9372 } else {
9373 const width = videoFrame.displayWidth;
9374 const height = videoFrame.displayHeight;
9375 if (!this.splitter) {
9376 this.splitter = new ColorAlphaSplitter(width, height);
9377 }
9378 const { colorFrame, alphaFrame } = await this.splitter.update(videoFrame);
9379 this.alphaFrameQueue.push(alphaFrame);
9380 this.encoder.encode(colorFrame, finalEncodeOptions);
9381 colorFrame.close();
9382 }
9383 }
9384 if (this.encoder.encodeQueueSize >= 4) {
9385 await new Promise((resolve) => this.encoder.addEventListener("dequeue", resolve, { once: true }));
9386 }
9387 }
9388 await this.lastMuxerPromise;
9389 }
9390 } finally {
9391 for (const sample of samplesToEncode) {
9392 if (sample !== videoSample) {
9393 sample.close();
9394 }
9395 }
9396 }
9397 }
9398 /** Repeats the last frame rate sample to fill the gap up to the given timestamp. */
9399 async padFrameRate(until, encodeOptions) {
9400 const frameRate = this.encodingConfig.transform.frameRate;
9401 assert(this.frameRateLastSample);
9402 const frameDifference = Math.round((until - this.frameRateLastTimestamp) * frameRate);
9403 for (let i2 = 1; i2 < frameDifference; i2++) {
9404 const sample = this.frameRateLastSample.clone();
9405 sample.setTimestamp(this.frameRateLastTimestamp + i2 / frameRate);
9406 sample.setDuration(1 / frameRate);
9407 await this.processAndEncode(sample, encodeOptions);
9408 sample.close();
9409 }
9410 }
9411 ensureEncoder(videoSample) {
9412 this.ensureEncoderPromise = (async () => {
9413 const encoderConfig = buildVideoEncoderConfig({
9414 ...this.encodingConfig,
9415 width: videoSample.codedWidth,
9416 height: videoSample.codedHeight,
9417 squarePixelWidth: videoSample.squarePixelWidth,
9418 squarePixelHeight: videoSample.squarePixelHeight,
9419 framerate: this.source._connectedTrack?.metadata.frameRate
9420 });
9421 this.encodingConfig.onEncoderConfig?.(encoderConfig);
9422 const MatchingCustomEncoder = customVideoEncoders.find((x) => x.supports(this.encodingConfig.codec, encoderConfig));
9423 if (MatchingCustomEncoder) {
9424 this.customEncoder = new MatchingCustomEncoder();
9425 this.customEncoder.codec = this.encodingConfig.codec;
9426 this.customEncoder.config = encoderConfig;
9427 this.customEncoder.onPacket = (packet, meta) => {
9428 if (!(packet instanceof EncodedPacket)) {
9429 throw new TypeError("The first argument passed to onPacket must be an EncodedPacket.");
9430 }
9431 if (meta !== void 0 && (!meta || typeof meta !== "object")) {
9432 throw new TypeError("The second argument passed to onPacket must be an object or undefined.");
9433 }
9434 maybeEnsureIsKeyPacket(this.source._connectedTrack, packet);
9435 this.encodingConfig.onEncodedPacket?.(packet, meta);
9436 this.lastMuxerPromise = this.muxer.addEncodedVideoPacket(this.source._connectedTrack, packet, meta).catch((error) => {
9437 this.error ??= error;
9438 });
9439 };
9440 await this.customEncoder.init();
9441 } else {
9442 if (typeof VideoEncoder === "undefined") {
9443 throw new Error("VideoEncoder is not supported by this browser.");
9444 }
9445 encoderConfig.alpha = "discard";
9446 if (this.encodingConfig.alpha === "keep") {
9447 encoderConfig.latencyMode = "quality";
9448 }
9449 const hasOddDimension = encoderConfig.width % 2 === 1 || encoderConfig.height % 2 === 1;
9450 if (hasOddDimension && (this.encodingConfig.codec === "avc" || this.encodingConfig.codec === "hevc")) {
9451 throw new Error(\`The dimensions \${encoderConfig.width}x\${encoderConfig.height} are not supported for codec '\${this.encodingConfig.codec}'; both width and height must be even numbers. Make sure to round your dimensions to the nearest even number.\`);
9452 }
9453 const support = await VideoEncoder.isConfigSupported(encoderConfig);
9454 if (!support.supported) {
9455 throw new Error(\`This specific encoder configuration (\${encoderConfig.codec}, \${encoderConfig.bitrate} bps, \${encoderConfig.width}x\${encoderConfig.height}, hardware acceleration: \${encoderConfig.hardwareAcceleration ?? "no-preference"}) is not supported by this browser. Consider using another codec or changing your video parameters.\`);
9456 }
9457 const colorChunkQueue = [];
9458 const nullAlphaChunkQueue = [];
9459 let encodedAlphaChunkCount = 0;
9460 let alphaEncoderQueue = 0;
9461 const addPacket = (colorChunk, alphaChunk, meta) => {
9462 const sideData = {};
9463 if (alphaChunk) {
9464 const alphaData = new Uint8Array(alphaChunk.byteLength);
9465 alphaChunk.copyTo(alphaData);
9466 sideData.alpha = alphaData;
9467 }
9468 let packet = EncodedPacket.fromEncodedChunk(colorChunk, sideData);
9469 const preciseTimingIndex = binarySearchLessOrEqual(this.preciseTimings, colorChunk.timestamp, (x) => x.microsecondTimestamp);
9470 const entry = preciseTimingIndex !== -1 ? this.preciseTimings[preciseTimingIndex] : null;
9471 let actualType = null;
9472 if (this.emittedEncoderPackets === 0 && packet.type === "delta" && meta?.decoderConfig) {
9473 actualType = determineVideoPacketType(this.encodingConfig.codec, meta.decoderConfig, packet.data);
9474 }
9475 if (entry && entry.microsecondTimestamp === colorChunk.timestamp || actualType !== null) {
9476 packet = packet.clone({
9477 timestamp: entry?.timestampIsValid ? entry.timestamp : void 0,
9478 duration: entry?.durationIsValid ? entry.duration : void 0,
9479 type: actualType ?? void 0
9480 });
9481 }
9482 maybeEnsureIsKeyPacket(this.source._connectedTrack, packet);
9483 this.encodingConfig.onEncodedPacket?.(packet, meta);
9484 this.lastMuxerPromise = this.muxer.addEncodedVideoPacket(this.source._connectedTrack, packet, meta).catch((error) => {
9485 this.error ??= error;
9486 });
9487 this.emittedEncoderPackets++;
9488 };
9489 const stack = new Error("Encoding error").stack;
9490 this.encoder = new VideoEncoder({
9491 output: (chunk, meta) => {
9492 if (!this.alphaEncoder) {
9493 addPacket(chunk, null, meta);
9494 return;
9495 }
9496 const alphaFrame = this.alphaFrameQueue.shift();
9497 assert(alphaFrame !== void 0);
9498 if (alphaFrame) {
9499 this.alphaEncoder.encode(alphaFrame, {
9500 // Crucial: The alpha frame is forced to be a key frame whenever the color frame
9501 // also is. Without this, playback can glitch and even crash in some browsers.
9502 // This is the reason why the two encoders are wired in series and not in parallel.
9503 keyFrame: chunk.type === "key"
9504 });
9505 alphaEncoderQueue++;
9506 alphaFrame.close();
9507 colorChunkQueue.push({ chunk, meta });
9508 } else {
9509 if (alphaEncoderQueue === 0) {
9510 addPacket(chunk, null, meta);
9511 } else {
9512 nullAlphaChunkQueue.push(encodedAlphaChunkCount + alphaEncoderQueue);
9513 colorChunkQueue.push({ chunk, meta });
9514 }
9515 }
9516 },
9517 error: (error) => {
9518 error.stack = stack;
9519 this.error ??= error;
9520 }
9521 });
9522 this.encoder.configure(encoderConfig);
9523 if (this.encodingConfig.alpha === "keep") {
9524 const stack2 = new Error("Encoding error").stack;
9525 this.alphaEncoder = new VideoEncoder({
9526 // We ignore the alpha chunk's metadata
9527 // eslint-disable-next-line @typescript-eslint/no-unused-vars
9528 output: (chunk, meta) => {
9529 alphaEncoderQueue--;
9530 const colorChunk = colorChunkQueue.shift();
9531 assert(colorChunk !== void 0);
9532 addPacket(colorChunk.chunk, chunk, colorChunk.meta);
9533 encodedAlphaChunkCount++;
9534 while (nullAlphaChunkQueue.length > 0 && nullAlphaChunkQueue[0] === encodedAlphaChunkCount) {
9535 nullAlphaChunkQueue.shift();
9536 const colorChunk2 = colorChunkQueue.shift();
9537 assert(colorChunk2 !== void 0);
9538 addPacket(colorChunk2.chunk, null, colorChunk2.meta);
9539 }
9540 },
9541 error: (error) => {
9542 error.stack = stack2;
9543 this.error ??= error;
9544 }
9545 });
9546 this.alphaEncoder.configure(encoderConfig);
9547 }
9548 }
9549 assert(this.source._connectedTrack);
9550 this.muxer = this.source._connectedTrack.output._muxer;
9551 this.encoderInitialized = true;
9552 })();
9553 }
9554 async flushAndClose(forceClose) {
9555 if (!forceClose) {
9556 this.checkForEncoderError();
9557 }
9558 if (!forceClose && this.frameRateLastSample) {
9559 const frameRate = this.encodingConfig.transform.frameRate;
9560 const alignedEnd = floorToDivisor(this.frameRateLastEndTimestamp, frameRate);
9561 await this.padFrameRate(alignedEnd);
9562 }
9563 this.closed = true;
9564 this.frameRateLastSample?.close();
9565 this.frameRateLastSample = null;
9566 if (this.customEncoder) {
9567 if (!forceClose) {
9568 void this.customEncoderCallSerializer.call(() => this.customEncoder.flush());
9569 }
9570 await this.customEncoderCallSerializer.call(() => this.customEncoder.close());
9571 } else if (this.encoder) {
9572 if (!forceClose) {
9573 await this.encoder.flush();
9574 await this.alphaEncoder?.flush();
9575 }
9576 if (this.encoder.state !== "closed") {
9577 this.encoder.close();
9578 }
9579 if (this.alphaEncoder && this.alphaEncoder.state !== "closed") {
9580 this.alphaEncoder.close();
9581 }
9582 this.alphaFrameQueue.forEach((x) => x?.close());
9583 this.splitter?.close();
9584 }
9585 if (!forceClose) {
9586 this.checkForEncoderError();
9587 }
9588 }
9589 getQueueSize() {
9590 if (this.customEncoder) {
9591 return this.customEncoderQueueSize;
9592 } else {
9593 return this.encoder?.encodeQueueSize ?? 0;
9594 }
9595 }
9596 checkForEncoderError() {
9597 if (this.error) {
9598 throw this.error;
9599 }
9600 }
9601 };
9602 var splitterGpuUnavailable = false;
9603 var ColorAlphaSplitter = class _ColorAlphaSplitter {
9604 constructor(initialWidth, initialHeight) {
9605 this.canvas = null;
9606 this.gl = null;
9607 this.colorProgram = null;
9608 this.alphaProgram = null;
9609 this.vao = null;
9610 this.sourceTexture = null;
9611 this.alphaResolutionLocation = null;
9612 this.worker = null;
9613 this.pendingRequests = /* @__PURE__ */ new Map();
9614 this.nextRequestId = 0;
9615 const canMakeCanvas = typeof OffscreenCanvas !== "undefined" || typeof document !== "undefined" && typeof document.createElement === "function";
9616 if (!_ColorAlphaSplitter.forceCpu && canMakeCanvas && !splitterGpuUnavailable) {
9617 try {
9618 if (typeof OffscreenCanvas !== "undefined") {
9619 this.canvas = new OffscreenCanvas(initialWidth, initialHeight);
9620 } else {
9621 this.canvas = document.createElement("canvas");
9622 this.canvas.width = initialWidth;
9623 this.canvas.height = initialHeight;
9624 }
9625 const gl = this.canvas.getContext("webgl2", {
9626 alpha: true
9627 // Needed due to the YUV thing we do for alpha
9628 });
9629 if (!gl) {
9630 throw new Error("Couldn't acquire WebGL 2 context.");
9631 }
9632 this.gl = gl;
9633 this.colorProgram = this.createColorProgram();
9634 this.alphaProgram = this.createAlphaProgram();
9635 this.vao = this.createVAO();
9636 this.sourceTexture = this.createTexture();
9637 this.alphaResolutionLocation = this.gl.getUniformLocation(this.alphaProgram, "u_resolution");
9638 this.gl.useProgram(this.colorProgram);
9639 this.gl.uniform1i(this.gl.getUniformLocation(this.colorProgram, "u_sourceTexture"), 0);
9640 this.gl.useProgram(this.alphaProgram);
9641 this.gl.uniform1i(this.gl.getUniformLocation(this.alphaProgram, "u_sourceTexture"), 0);
9642 } catch (error) {
9643 this.gl = null;
9644 this.canvas = null;
9645 splitterGpuUnavailable = true;
9646 Logging._warn("Falling back to CPU for color/alpha splitting.", error);
9647 }
9648 }
9649 }
9650 async update(sourceFrame) {
9651 if (this.gl) {
9652 return this.updateGpu(sourceFrame);
9653 } else {
9654 return this.updateCpu(sourceFrame);
9655 }
9656 }
9657 updateGpu(sourceFrame) {
9658 assert(this.gl);
9659 assert(this.canvas);
9660 if (sourceFrame.displayWidth !== this.canvas.width || sourceFrame.displayHeight !== this.canvas.height) {
9661 this.canvas.width = sourceFrame.displayWidth;
9662 this.canvas.height = sourceFrame.displayHeight;
9663 }
9664 this.gl.activeTexture(this.gl.TEXTURE0);
9665 this.gl.bindTexture(this.gl.TEXTURE_2D, this.sourceTexture);
9666 this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, sourceFrame);
9667 const colorFrame = this.runColorProgram(sourceFrame);
9668 const alphaFrame = this.runAlphaProgram(sourceFrame);
9669 sourceFrame.close();
9670 return { colorFrame, alphaFrame };
9671 }
9672 createVertexShader() {
9673 assert(this.gl);
9674 return this.createShader(this.gl.VERTEX_SHADER, \`#version 300 es
9675 in vec2 a_position;
9676 in vec2 a_texCoord;
9677 out vec2 v_texCoord;
9678
9679 void main() {
9680 gl_Position = vec4(a_position, 0.0, 1.0);
9681 v_texCoord = a_texCoord;
9682 }
9683 \`);
9684 }
9685 createColorProgram() {
9686 assert(this.gl);
9687 const vertexShader = this.createVertexShader();
9688 const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, \`#version 300 es
9689 precision highp float;
9690
9691 uniform sampler2D u_sourceTexture;
9692 in vec2 v_texCoord;
9693 out vec4 fragColor;
9694
9695 void main() {
9696 vec4 source = texture(u_sourceTexture, v_texCoord);
9697 fragColor = vec4(source.rgb, 1.0);
9698 }
9699 \`);
9700 const program = this.gl.createProgram();
9701 this.gl.attachShader(program, vertexShader);
9702 this.gl.attachShader(program, fragmentShader);
9703 this.gl.linkProgram(program);
9704 return program;
9705 }
9706 createAlphaProgram() {
9707 assert(this.gl);
9708 const vertexShader = this.createVertexShader();
9709 const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, \`#version 300 es
9710 precision highp float;
9711
9712 uniform sampler2D u_sourceTexture;
9713 uniform vec2 u_resolution; // The width and height of the canvas
9714 in vec2 v_texCoord;
9715 out vec4 fragColor;
9716
9717 // This function determines the value for a single byte in the YUV stream
9718 float getByteValue(float byteOffset) {
9719 float width = u_resolution.x;
9720 float height = u_resolution.y;
9721
9722 float yPlaneSize = width * height;
9723
9724 if (byteOffset < yPlaneSize) {
9725 // This byte is in the luma plane. Find the corresponding pixel coordinates to sample from
9726 float y = floor(byteOffset / width);
9727 float x = mod(byteOffset, width);
9728
9729 // Add 0.5 to sample the center of the texel
9730 vec2 sampleCoord = (vec2(x, y) + 0.5) / u_resolution;
9731
9732 // The luma value is the alpha from the source texture
9733 return texture(u_sourceTexture, sampleCoord).a;
9734 } else {
9735 // Write a fixed value for chroma and beyond
9736 return 128.0 / 255.0;
9737 }
9738 }
9739
9740 void main() {
9741 // Each fragment writes 4 bytes (R, G, B, A)
9742 float pixelIndex = floor(gl_FragCoord.y) * u_resolution.x + floor(gl_FragCoord.x);
9743 float baseByteOffset = pixelIndex * 4.0;
9744
9745 vec4 result;
9746 for (int i = 0; i < 4; i++) {
9747 float currentByteOffset = baseByteOffset + float(i);
9748 result[i] = getByteValue(currentByteOffset);
9749 }
9750
9751 fragColor = result;
9752 }
9753 \`);
9754 const program = this.gl.createProgram();
9755 this.gl.attachShader(program, vertexShader);
9756 this.gl.attachShader(program, fragmentShader);
9757 this.gl.linkProgram(program);
9758 return program;
9759 }
9760 createShader(type, source) {
9761 assert(this.gl);
9762 const shader = this.gl.createShader(type);
9763 this.gl.shaderSource(shader, source);
9764 this.gl.compileShader(shader);
9765 if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
9766 Logging._error("Shader compile error:", this.gl.getShaderInfoLog(shader));
9767 }
9768 return shader;
9769 }
9770 createVAO() {
9771 assert(this.gl);
9772 assert(this.colorProgram);
9773 const vao = this.gl.createVertexArray();
9774 this.gl.bindVertexArray(vao);
9775 const vertices = new Float32Array([
9776 -1,
9777 -1,
9778 0,
9779 1,
9780 1,
9781 -1,
9782 1,
9783 1,
9784 -1,
9785 1,
9786 0,
9787 0,
9788 1,
9789 1,
9790 1,
9791 0
9792 ]);
9793 const buffer = this.gl.createBuffer();
9794 this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
9795 this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);
9796 const positionLocation = this.gl.getAttribLocation(this.colorProgram, "a_position");
9797 const texCoordLocation = this.gl.getAttribLocation(this.colorProgram, "a_texCoord");
9798 this.gl.enableVertexAttribArray(positionLocation);
9799 this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 16, 0);
9800 this.gl.enableVertexAttribArray(texCoordLocation);
9801 this.gl.vertexAttribPointer(texCoordLocation, 2, this.gl.FLOAT, false, 16, 8);
9802 return vao;
9803 }
9804 createTexture() {
9805 assert(this.gl);
9806 const texture = this.gl.createTexture();
9807 this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
9808 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
9809 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
9810 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
9811 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
9812 return texture;
9813 }
9814 runColorProgram(sourceFrame) {
9815 assert(this.gl);
9816 assert(this.canvas);
9817 this.gl.useProgram(this.colorProgram);
9818 this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
9819 this.gl.clear(this.gl.COLOR_BUFFER_BIT);
9820 this.gl.bindVertexArray(this.vao);
9821 this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
9822 return new VideoFrame(this.canvas, {
9823 timestamp: sourceFrame.timestamp,
9824 duration: sourceFrame.duration ?? void 0,
9825 alpha: "discard"
9826 });
9827 }
9828 runAlphaProgram(sourceFrame) {
9829 assert(this.gl);
9830 assert(this.canvas);
9831 this.gl.useProgram(this.alphaProgram);
9832 this.gl.uniform2f(this.alphaResolutionLocation, this.canvas.width, this.canvas.height);
9833 this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
9834 this.gl.clear(this.gl.COLOR_BUFFER_BIT);
9835 this.gl.bindVertexArray(this.vao);
9836 this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
9837 const { width, height } = this.canvas;
9838 const chromaSamples = Math.ceil(width / 2) * Math.ceil(height / 2);
9839 const yuvSize = width * height + chromaSamples * 2;
9840 const requiredHeight = Math.ceil(yuvSize / (width * 4));
9841 let yuv = new Uint8Array(4 * width * requiredHeight);
9842 this.gl.readPixels(0, 0, width, requiredHeight, this.gl.RGBA, this.gl.UNSIGNED_BYTE, yuv);
9843 yuv = yuv.subarray(0, yuvSize);
9844 assert(yuv[width * height] === 128);
9845 assert(yuv[yuv.length - 1] === 128);
9846 const init = {
9847 format: "I420",
9848 codedWidth: width,
9849 codedHeight: height,
9850 timestamp: sourceFrame.timestamp,
9851 duration: sourceFrame.duration ?? void 0,
9852 transfer: [yuv.buffer]
9853 };
9854 return new VideoFrame(yuv, init);
9855 }
9856 updateCpu(sourceFrame) {
9857 if (!this.worker) {
9858 const blob = new Blob([\`(\${colorAlphaSplitterWorkerCode.toString()})()\`], { type: "application/javascript" });
9859 const url2 = URL.createObjectURL(blob);
9860 this.worker = new Worker(url2);
9861 URL.revokeObjectURL(url2);
9862 this.worker.addEventListener("message", (event) => {
9863 const data = event.data;
9864 const pending2 = this.pendingRequests.get(data.id);
9865 if (!pending2) {
9866 return;
9867 }
9868 this.pendingRequests.delete(data.id);
9869 if ("error" in data) {
9870 pending2.reject(new Error(data.error));
9871 } else {
9872 pending2.resolve({ colorFrame: data.colorFrame, alphaFrame: data.alphaFrame });
9873 }
9874 });
9875 this.worker.addEventListener("error", (event) => {
9876 const error = new Error(event.message || "Color/alpha splitter worker error.");
9877 for (const pending2 of this.pendingRequests.values()) {
9878 pending2.reject(error);
9879 }
9880 this.pendingRequests.clear();
9881 });
9882 }
9883 const id = this.nextRequestId++;
9884 const pending = promiseWithResolvers();
9885 this.pendingRequests.set(id, pending);
9886 this.worker.postMessage({ id, sourceFrame }, { transfer: [sourceFrame] });
9887 return pending.promise;
9888 }
9889 close() {
9890 this.gl?.getExtension("WEBGL_lose_context")?.loseContext();
9891 this.gl = null;
9892 this.canvas = null;
9893 this.worker?.terminate();
9894 this.worker = null;
9895 const error = new Error("Color/alpha splitter closed.");
9896 for (const pending of this.pendingRequests.values()) {
9897 pending.reject(error);
9898 }
9899 this.pendingRequests.clear();
9900 }
9901 };
9902 ColorAlphaSplitter.forceCpu = true;
9903 var colorAlphaSplitterWorkerCode = () => {
9904 let cpuSourceBuffer = null;
9905 let chain = Promise.resolve();
9906 self.addEventListener("message", (event) => {
9907 const { id, sourceFrame } = event.data;
9908 chain = chain.then(async () => {
9909 try {
9910 const { colorFrame, alphaFrame } = await split(sourceFrame);
9911 self.postMessage({ id, colorFrame, alphaFrame }, { transfer: [colorFrame, alphaFrame] });
9912 } catch (error) {
9913 self.postMessage({ id, error: error.message });
9914 } finally {
9915 sourceFrame.close();
9916 }
9917 });
9918 });
9919 const split = async (sourceFrame) => {
9920 const format = sourceFrame.format;
9921 if (!format) {
9922 throw new Error("CPU color/alpha splitting requires a known VideoFrame format.");
9923 }
9924 const width = sourceFrame.codedWidth;
9925 const height = sourceFrame.codedHeight;
9926 const sourceSize = sourceFrame.allocationSize();
9927 if (!cpuSourceBuffer || cpuSourceBuffer.byteLength !== sourceSize) {
9928 cpuSourceBuffer = new Uint8Array(sourceSize);
9929 }
9930 await sourceFrame.copyTo(cpuSourceBuffer);
9931 if (format === "RGBA" || format === "BGRA") {
9932 return splitInterleavedRgba(cpuSourceBuffer, width, height, format, sourceFrame);
9933 } else if (format === "I420A" || format === "I420AP10" || format === "I420AP12" || format === "I422A" || format === "I422AP10" || format === "I422AP12" || format === "I444A" || format === "I444AP10" || format === "I444AP12") {
9934 return splitPlanarYuvA(cpuSourceBuffer, width, height, format, sourceFrame);
9935 }
9936 throw new Error(\`CPU color/alpha splitting does not support format '\${format}'.\`);
9937 };
9938 const splitInterleavedRgba = (source, width, height, format, sourceFrame) => {
9939 const pixelCount = width * height;
9940 const chromaW = Math.ceil(width / 2);
9941 const chromaH = Math.ceil(height / 2);
9942 const alphaSize = pixelCount + chromaW * chromaH * 2;
9943 const alphaBuffer = new Uint8Array(alphaSize);
9944 for (let i2 = 0, j = 3; i2 < pixelCount; i2++, j += 4) {
9945 alphaBuffer[i2] = source[j];
9946 }
9947 alphaBuffer.fill(128, pixelCount);
9948 const colorFrame = new VideoFrame(source, {
9949 format: format === "RGBA" ? "RGBX" : "BGRX",
9950 codedWidth: width,
9951 codedHeight: height,
9952 timestamp: sourceFrame.timestamp,
9953 duration: sourceFrame.duration ?? void 0
9954 // No transfer!
9955 });
9956 const alphaInit = {
9957 format: "I420",
9958 codedWidth: width,
9959 codedHeight: height,
9960 timestamp: sourceFrame.timestamp,
9961 duration: sourceFrame.duration ?? void 0,
9962 transfer: [alphaBuffer.buffer]
9963 };
9964 const alphaFrame = new VideoFrame(alphaBuffer, alphaInit);
9965 return { colorFrame, alphaFrame };
9966 };
9967 const splitPlanarYuvA = (source, width, height, format, sourceFrame) => {
9968 const is10 = format.includes("P10");
9969 const is12 = format.includes("P12");
9970 const bytesPerSample = is10 || is12 ? 2 : 1;
9971 let chromaW;
9972 let chromaH;
9973 if (format.startsWith("I420")) {
9974 chromaW = Math.ceil(width / 2);
9975 chromaH = Math.ceil(height / 2);
9976 } else if (format.startsWith("I422")) {
9977 chromaW = Math.ceil(width / 2);
9978 chromaH = height;
9979 } else {
9980 chromaW = width;
9981 chromaH = height;
9982 }
9983 const ySamples = width * height;
9984 const uvSamples = chromaW * chromaH;
9985 const yBytes = ySamples * bytesPerSample;
9986 const uvBytes = uvSamples * bytesPerSample;
9987 const aBytes = ySamples * bytesPerSample;
9988 const colorBytes = yBytes + uvBytes * 2;
9989 const colorFormat = format.replace("A", "");
9990 const alphaChromaW = Math.ceil(width / 2);
9991 const alphaChromaH = Math.ceil(height / 2);
9992 const alphaUvSamples = alphaChromaW * alphaChromaH;
9993 const alphaUvBytes = alphaUvSamples * bytesPerSample;
9994 const alphaSize = aBytes + 2 * alphaUvBytes;
9995 const alphaBuffer = new Uint8Array(alphaSize);
9996 const aPlaneStart = colorBytes;
9997 alphaBuffer.set(source.subarray(aPlaneStart, aPlaneStart + aBytes), 0);
9998 const uvOffset = aBytes;
9999 const neutralChroma = is10 ? 512 : is12 ? 2048 : 128;
10000 if (bytesPerSample === 1) {
10001 alphaBuffer.fill(neutralChroma, uvOffset);
10002 } else {
10003 const uvView = new Uint16Array(alphaBuffer.buffer, uvOffset, 2 * alphaUvSamples);
10004 uvView.fill(neutralChroma);
10005 }
10006 const alphaFormat = is10 ? "I420P10" : is12 ? "I420P12" : "I420";
10007 const colorFrame = new VideoFrame(source.subarray(0, colorBytes), {
10008 format: colorFormat,
10009 codedWidth: width,
10010 codedHeight: height,
10011 timestamp: sourceFrame.timestamp,
10012 duration: sourceFrame.duration ?? void 0
10013 });
10014 const alphaInit = {
10015 format: alphaFormat,
10016 codedWidth: width,
10017 codedHeight: height,
10018 timestamp: sourceFrame.timestamp,
10019 duration: sourceFrame.duration ?? void 0,
10020 transfer: [alphaBuffer.buffer]
10021 };
10022 const alphaFrame = new VideoFrame(alphaBuffer, alphaInit);
10023 return { colorFrame, alphaFrame };
10024 };
10025 };
10026 var VideoSampleSource = class extends VideoSource {
10027 /**
10028 * Creates a new {@link VideoSampleSource} whose samples are encoded according to the specified
10029 * {@link VideoEncodingConfig}.
10030 */
10031 constructor(encodingConfig) {
10032 validateVideoEncodingConfig(encodingConfig);
10033 super(encodingConfig.codec);
10034 this._encoder = new VideoEncoderWrapper(this, encodingConfig);
10035 }
10036 /**
10037 * Encodes a video sample (frame) and then adds it to the output.
10038 *
10039 * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise
10040 * to respect writer and encoder backpressure.
10041 */
10042 add(videoSample, encodeOptions) {
10043 if (!(videoSample instanceof VideoSample)) {
10044 throw new TypeError("videoSample must be a VideoSample.");
10045 }
10046 return this._encoder.add(videoSample, false, encodeOptions);
10047 }
10048 /** @internal */
10049 _flushAndClose(forceClose) {
10050 return this._encoder.flushAndClose(forceClose);
10051 }
10052 };
10053 var AudioSource = class extends MediaSource {
10054 /** Internal constructor. */
10055 constructor(codec) {
10056 super();
10057 this._connectedTrack = null;
10058 if (!AUDIO_CODECS.includes(codec)) {
10059 throw new TypeError(\`Invalid audio codec '\${codec}'. Must be one of: \${AUDIO_CODECS.join(", ")}.\`);
10060 }
10061 this._codec = codec;
10062 }
10063 };
10064 var SubtitleSource = class extends MediaSource {
10065 /** Internal constructor. */
10066 constructor(codec) {
10067 super();
10068 this._connectedTrack = null;
10069 if (!SUBTITLE_CODECS.includes(codec)) {
10070 throw new TypeError(\`Invalid subtitle codec '\${codec}'. Must be one of: \${SUBTITLE_CODECS.join(", ")}.\`);
10071 }
10072 this._codec = codec;
10073 }
10074 };
10075
10076 // node_modules/mediabunny/dist/modules/src/output-format.js
10077 var OutputFormat = class {
10078 /** Returns a list of video codecs that this output format can contain. */
10079 getSupportedVideoCodecs() {
10080 return this.getSupportedCodecs().filter((codec) => VIDEO_CODECS.includes(codec));
10081 }
10082 /** Returns a list of audio codecs that this output format can contain. */
10083 getSupportedAudioCodecs() {
10084 return this.getSupportedCodecs().filter((codec) => AUDIO_CODECS.includes(codec));
10085 }
10086 /** Returns a list of subtitle codecs that this output format can contain. */
10087 getSupportedSubtitleCodecs() {
10088 return this.getSupportedCodecs().filter((codec) => SUBTITLE_CODECS.includes(codec));
10089 }
10090 /** @internal */
10091 // eslint-disable-next-line @typescript-eslint/no-unused-vars
10092 _codecUnsupportedHint(codec) {
10093 return "";
10094 }
10095 };
10096 var IsobmffOutputFormat = class extends OutputFormat {
10097 /** Internal constructor. */
10098 constructor(options = {}) {
10099 if (!options || typeof options !== "object") {
10100 throw new TypeError("options must be an object.");
10101 }
10102 if (options.fastStart !== void 0 && ![false, "in-memory", "reserve", "fragmented"].includes(options.fastStart)) {
10103 throw new TypeError("options.fastStart, when provided, must be false, 'in-memory', 'reserve', or 'fragmented'.");
10104 }
10105 if (options.minimumFragmentDuration !== void 0 && (!Number.isFinite(options.minimumFragmentDuration) || options.minimumFragmentDuration < 0)) {
10106 throw new TypeError("options.minimumFragmentDuration, when provided, must be a non-negative number.");
10107 }
10108 if (options.onFtyp !== void 0 && typeof options.onFtyp !== "function") {
10109 throw new TypeError("options.onFtyp, when provided, must be a function.");
10110 }
10111 if (options.onMoov !== void 0 && typeof options.onMoov !== "function") {
10112 throw new TypeError("options.onMoov, when provided, must be a function.");
10113 }
10114 if (options.onMdat !== void 0 && typeof options.onMdat !== "function") {
10115 throw new TypeError("options.onMdat, when provided, must be a function.");
10116 }
10117 if (options.onMoof !== void 0 && typeof options.onMoof !== "function") {
10118 throw new TypeError("options.onMoof, when provided, must be a function.");
10119 }
10120 if (options.metadataFormat !== void 0 && !["mdir", "mdta", "udta", "auto"].includes(options.metadataFormat)) {
10121 throw new TypeError("options.metadataFormat, when provided, must be either 'auto', 'mdir', 'mdta', or 'udta'.");
10122 }
10123 super();
10124 this._options = options;
10125 }
10126 getSupportedTrackCounts() {
10127 const max = 2 ** 32 - 1;
10128 return {
10129 video: { min: 0, max },
10130 audio: { min: 0, max },
10131 subtitle: { min: 0, max },
10132 total: { min: 1, max }
10133 };
10134 }
10135 get supportsVideoRotationMetadata() {
10136 return true;
10137 }
10138 get supportsTimestampedMediaData() {
10139 return true;
10140 }
10141 /** @internal */
10142 _createMuxer(output) {
10143 return new IsobmffMuxer(output, this);
10144 }
10145 };
10146 var Mp4OutputFormat = class extends IsobmffOutputFormat {
10147 /** Creates a new {@link Mp4OutputFormat} configured with the specified \`options\`. */
10148 constructor(options) {
10149 super(options);
10150 }
10151 /** @internal */
10152 get _name() {
10153 return "MP4";
10154 }
10155 get fileExtension() {
10156 return ".mp4";
10157 }
10158 get mimeType() {
10159 return "video/mp4";
10160 }
10161 getSupportedCodecs() {
10162 return [
10163 ...VIDEO_CODECS,
10164 ...NON_PCM_AUDIO_CODECS,
10165 // These are supported via ISO/IEC 23003-5:
10166 "pcm-s16",
10167 "pcm-s16be",
10168 "pcm-s24",
10169 "pcm-s24be",
10170 "pcm-s32",
10171 "pcm-s32be",
10172 "pcm-f32",
10173 "pcm-f32be",
10174 "pcm-f64",
10175 "pcm-f64be",
10176 ...SUBTITLE_CODECS
10177 ];
10178 }
10179 /** @internal */
10180 _codecUnsupportedHint(codec) {
10181 if (new MovOutputFormat().getSupportedCodecs().includes(codec)) {
10182 return " Switching to MOV will grant support for this codec.";
10183 }
10184 return "";
10185 }
10186 };
10187 var CmafOutputFormat = class extends IsobmffOutputFormat {
10188 /** Creates a new {@link CmafOutputFormat} configured with the specified \`options\`. */
10189 constructor(options) {
10190 super(options);
10191 }
10192 /** @internal */
10193 get _name() {
10194 return "CMAF";
10195 }
10196 get fileExtension() {
10197 return ".m4s";
10198 }
10199 get mimeType() {
10200 return "video/mp4";
10201 }
10202 getSupportedCodecs() {
10203 return [
10204 ...VIDEO_CODECS,
10205 ...NON_PCM_AUDIO_CODECS,
10206 // These are supported via ISO/IEC 23003-5:
10207 "pcm-s16",
10208 "pcm-s16be",
10209 "pcm-s24",
10210 "pcm-s24be",
10211 "pcm-s32",
10212 "pcm-s32be",
10213 "pcm-f32",
10214 "pcm-f32be",
10215 "pcm-f64",
10216 "pcm-f64be",
10217 ...SUBTITLE_CODECS
10218 ];
10219 }
10220 };
10221 var MovOutputFormat = class extends IsobmffOutputFormat {
10222 /** Creates a new {@link MovOutputFormat} configured with the specified \`options\`. */
10223 constructor(options) {
10224 super(options);
10225 }
10226 /** @internal */
10227 get _name() {
10228 return "MOV";
10229 }
10230 get fileExtension() {
10231 return ".mov";
10232 }
10233 get mimeType() {
10234 return "video/quicktime";
10235 }
10236 getSupportedCodecs() {
10237 return [
10238 ...VIDEO_CODECS,
10239 ...AUDIO_CODECS
10240 ];
10241 }
10242 /** @internal */
10243 _codecUnsupportedHint(codec) {
10244 if (new Mp4OutputFormat().getSupportedCodecs().includes(codec)) {
10245 return " Switching to MP4 will grant support for this codec.";
10246 }
10247 return "";
10248 }
10249 };
10250 var MkvOutputFormat = class extends OutputFormat {
10251 /** Creates a new {@link MkvOutputFormat} configured with the specified \`options\`. */
10252 constructor(options = {}) {
10253 if (!options || typeof options !== "object") {
10254 throw new TypeError("options must be an object.");
10255 }
10256 if (options.appendOnly !== void 0 && typeof options.appendOnly !== "boolean") {
10257 throw new TypeError("options.appendOnly, when provided, must be a boolean.");
10258 }
10259 if (options.minimumClusterDuration !== void 0 && (!Number.isFinite(options.minimumClusterDuration) || options.minimumClusterDuration < 0)) {
10260 throw new TypeError("options.minimumClusterDuration, when provided, must be a non-negative number.");
10261 }
10262 if (options.onEbmlHeader !== void 0 && typeof options.onEbmlHeader !== "function") {
10263 throw new TypeError("options.onEbmlHeader, when provided, must be a function.");
10264 }
10265 if (options.onSegmentHeader !== void 0 && typeof options.onSegmentHeader !== "function") {
10266 throw new TypeError("options.onHeader, when provided, must be a function.");
10267 }
10268 if (options.onCluster !== void 0 && typeof options.onCluster !== "function") {
10269 throw new TypeError("options.onCluster, when provided, must be a function.");
10270 }
10271 super();
10272 this._options = options;
10273 }
10274 /** @internal */
10275 _createMuxer(output) {
10276 return new MatroskaMuxer(output, this);
10277 }
10278 /** @internal */
10279 get _name() {
10280 return "Matroska";
10281 }
10282 getSupportedTrackCounts() {
10283 const max = 127;
10284 return {
10285 video: { min: 0, max },
10286 audio: { min: 0, max },
10287 subtitle: { min: 0, max },
10288 total: { min: 1, max }
10289 };
10290 }
10291 get fileExtension() {
10292 return ".mkv";
10293 }
10294 get mimeType() {
10295 return "video/x-matroska";
10296 }
10297 getSupportedCodecs() {
10298 return [
10299 ...VIDEO_CODECS,
10300 ...NON_PCM_AUDIO_CODECS,
10301 ...PCM_AUDIO_CODECS.filter((codec) => !["pcm-s8", "pcm-f32be", "pcm-f64be", "ulaw", "alaw"].includes(codec)),
10302 ...SUBTITLE_CODECS
10303 ];
10304 }
10305 get supportsVideoRotationMetadata() {
10306 return false;
10307 }
10308 get supportsTimestampedMediaData() {
10309 return true;
10310 }
10311 };
10312 var WebMOutputFormat = class extends MkvOutputFormat {
10313 /** Creates a new {@link WebMOutputFormat} configured with the specified \`options\`. */
10314 constructor(options) {
10315 super(options);
10316 }
10317 getSupportedCodecs() {
10318 return [
10319 ...VIDEO_CODECS.filter((codec) => ["vp8", "vp9", "av1"].includes(codec)),
10320 ...AUDIO_CODECS.filter((codec) => ["opus", "vorbis"].includes(codec)),
10321 ...SUBTITLE_CODECS
10322 ];
10323 }
10324 /** @internal */
10325 get _name() {
10326 return "WebM";
10327 }
10328 get fileExtension() {
10329 return ".webm";
10330 }
10331 get mimeType() {
10332 return "video/webm";
10333 }
10334 /** @internal */
10335 _codecUnsupportedHint(codec) {
10336 if (new MkvOutputFormat().getSupportedCodecs().includes(codec)) {
10337 return " Switching to MKV will grant support for this codec.";
10338 }
10339 return "";
10340 }
10341 };
10342
10343 // node_modules/mediabunny/dist/modules/src/output.js
10344 var ALL_TRACK_TYPES = ["video", "audio", "subtitle"];
10345 var OutputTrack = class _OutputTrack {
10346 /** @internal */
10347 constructor(id, output, type, source, metadata) {
10348 this.id = id;
10349 this.output = output;
10350 this.type = type;
10351 this.source = source;
10352 this.metadata = metadata;
10353 }
10354 /** Returns true if and only if this track is a video track. */
10355 isVideoTrack() {
10356 return this.type === "video";
10357 }
10358 /** Returns true if and only if this track is an audio track. */
10359 isAudioTrack() {
10360 return this.type === "audio";
10361 }
10362 /** Returns true if and only if this track is a subtitle track. */
10363 isSubtitleTrack() {
10364 return this.type === "subtitle";
10365 }
10366 /**
10367 * Returns true if and only if this track can be paired with the given other track. Pairability can be set using
10368 * the {@link BaseTrackMetadata.group} option.
10369 */
10370 canBePairedWith(other) {
10371 if (!(other instanceof _OutputTrack)) {
10372 throw new TypeError("other must be an OutputTrack.");
10373 }
10374 if (this === other) {
10375 return false;
10376 }
10377 const thisGroups = toArray(this.metadata.group);
10378 const otherGroups = toArray(other.metadata.group);
10379 for (const aGroup of thisGroups) {
10380 const pairableInSameGroup = this.type !== other.type && otherGroups.some((bGroup) => aGroup === bGroup);
10381 if (pairableInSameGroup) {
10382 return true;
10383 }
10384 const pairableAcrossGroups = otherGroups.some((bGroup) => aGroup._pairedGroups.has(bGroup));
10385 if (pairableAcrossGroups) {
10386 return true;
10387 }
10388 }
10389 return false;
10390 }
10391 };
10392 var OutputVideoTrack = class extends OutputTrack {
10393 /** @internal */
10394 constructor(id, output, source, metadata) {
10395 super(id, output, "video", source, metadata);
10396 }
10397 };
10398 var OutputAudioTrack = class extends OutputTrack {
10399 /** @internal */
10400 constructor(id, output, source, metadata) {
10401 super(id, output, "audio", source, metadata);
10402 }
10403 };
10404 var OutputSubtitleTrack = class extends OutputTrack {
10405 /** @internal */
10406 constructor(id, output, source, metadata) {
10407 super(id, output, "subtitle", source, metadata);
10408 }
10409 };
10410 var OutputTrackGroup = class _OutputTrackGroup {
10411 /** Creates a new {@link OutputTrackGroup}. */
10412 constructor() {
10413 this._pairedGroups = /* @__PURE__ */ new Set();
10414 }
10415 /**
10416 * Marks this group as being pairable with another group, symmetrically. Output tracks where each track is assigned
10417 * to one half of a group pairing are then considered pairable.
10418 *
10419 * You cannot pair a group with itself.
10420 */
10421 pairWith(other) {
10422 if (!(other instanceof _OutputTrackGroup)) {
10423 throw new TypeError("other must be an OutputTrackGroup.");
10424 }
10425 if (this === other) {
10426 throw new TypeError("Cannot pair a group with itself.");
10427 }
10428 this._pairedGroups.add(other);
10429 other._pairedGroups.add(this);
10430 }
10431 };
10432 var validateBaseTrackMetadata = (metadata) => {
10433 if (!metadata || typeof metadata !== "object") {
10434 throw new TypeError("metadata must be an object.");
10435 }
10436 if (metadata.languageCode !== void 0 && !isIso639Dash2LanguageCode(metadata.languageCode)) {
10437 throw new TypeError("metadata.languageCode, when provided, must be a three-letter, ISO 639-2/T language code.");
10438 }
10439 if (metadata.name !== void 0 && typeof metadata.name !== "string") {
10440 throw new TypeError("metadata.name, when provided, must be a string.");
10441 }
10442 if (metadata.disposition !== void 0) {
10443 validateTrackDisposition(metadata.disposition);
10444 }
10445 if (metadata.maximumPacketCount !== void 0 && (!Number.isInteger(metadata.maximumPacketCount) || metadata.maximumPacketCount < 0)) {
10446 throw new TypeError("metadata.maximumPacketCount, when provided, must be a non-negative integer.");
10447 }
10448 if (metadata.group !== void 0 && !(metadata.group instanceof OutputTrackGroup) && (!Array.isArray(metadata.group) || metadata.group.some((group) => !(group instanceof OutputTrackGroup)))) {
10449 throw new TypeError("metadata.group, when provided, must be an OutputTrackGroup instance or an array of OutputTrackGroup instances.");
10450 }
10451 };
10452 var Output = class extends EventEmitter {
10453 /**
10454 * The target to which the root file will be written. Throws when using {@link PathedTarget} with an async callback;
10455 * prefer the \`'target'\` event for those cases.
10456 */
10457 get target() {
10458 const errorMessage = "Output.target cannot be used when using PathedTarget with an async callback. Use the 'target' event instead.";
10459 if (this._rootTargetPromise) {
10460 throw new TypeError(errorMessage);
10461 }
10462 const rootTargetResult = this._getRootTarget();
10463 if (rootTargetResult instanceof Promise) {
10464 throw new TypeError(errorMessage);
10465 }
10466 return rootTargetResult;
10467 }
10468 /**
10469 * Creates a new instance of {@link Output} which can then be used to create a new media file according to the
10470 * specified {@link OutputOptions}.
10471 */
10472 constructor(options) {
10473 super();
10474 this.state = "pending";
10475 this.defaultTrackGroup = new OutputTrackGroup();
10476 this._onFinalize = null;
10477 this._unfinalizedTargets = /* @__PURE__ */ new Set();
10478 this._rootWriterPromise = null;
10479 this._tracks = [];
10480 this._startPromise = null;
10481 this._cancelPromise = null;
10482 this._finalizePromise = null;
10483 this._mutex = new AsyncMutex();
10484 this._metadataTags = {};
10485 this._rootTarget = null;
10486 this._rootTargetPromise = null;
10487 this._firstMediaStreamTimestamp = null;
10488 if (!options || typeof options !== "object") {
10489 throw new TypeError("options must be an object.");
10490 }
10491 if (!(options.format instanceof OutputFormat)) {
10492 throw new TypeError("options.format must be an OutputFormat.");
10493 }
10494 if (!(options.target instanceof Target || options.target instanceof PathedTarget)) {
10495 throw new TypeError("options.target must be a Target or a PathedTarget.");
10496 }
10497 if (options.target instanceof Target) {
10498 this._rememberTarget(options.target);
10499 }
10500 if (options.initTarget !== void 0 && !(options.initTarget instanceof Target) && typeof options.initTarget !== "function") {
10501 throw new Error("options.initTarget, when provided, must be a Target or a function that returns or resolves to a Target.");
10502 }
10503 if (options.onFinalize !== void 0 && typeof options.onFinalize !== "function") {
10504 throw new TypeError("options.onFinalize, when provided, must be a function.");
10505 }
10506 this.format = options.format;
10507 this._target = options.target;
10508 this._onFinalize = options.onFinalize ?? null;
10509 this._initTarget = options.initTarget ?? null;
10510 if (this._initTarget instanceof Target) {
10511 this._rememberTarget(this._initTarget);
10512 }
10513 this._muxer = options.format._createMuxer(this);
10514 }
10515 /** @internal */
10516 _getTargetValidated(request) {
10517 assert(this._target instanceof PathedTarget);
10518 const result = this._target.getTarget(request);
10519 const handleResult = (result2) => {
10520 if (!(result2 instanceof Target)) {
10521 throw new TypeError("getTarget must return a Target.");
10522 }
10523 return result2;
10524 };
10525 if (result instanceof Promise) {
10526 return result.then(handleResult);
10527 } else {
10528 return handleResult(result);
10529 }
10530 }
10531 /** @internal */
10532 async _getTarget(request) {
10533 assert(this._target instanceof PathedTarget);
10534 const target = await this._getTargetValidated(request);
10535 this._emit("target", { target, request, isRoot: request.isRoot });
10536 if (this.state === "canceled") {
10537 await target._close();
10538 } else {
10539 this._rememberTarget(target);
10540 }
10541 return target;
10542 }
10543 /** @internal */
10544 _rememberTarget(target) {
10545 this._unfinalizedTargets.add(target);
10546 target.on("finalized", () => this._unfinalizedTargets.delete(target), { once: true });
10547 }
10548 /** @internal */
10549 async _getInitTarget() {
10550 assert(this._initTarget !== null);
10551 if (this._initTarget instanceof Target) {
10552 return this._initTarget;
10553 }
10554 const target = await this._initTarget();
10555 if (this.state === "canceled") {
10556 await target._close();
10557 } else {
10558 this._rememberTarget(target);
10559 }
10560 return target;
10561 }
10562 /** @internal */
10563 _hasInitTarget() {
10564 return this._initTarget !== null;
10565 }
10566 /** @internal */
10567 _getRootTarget() {
10568 if (this._rootTarget) {
10569 return this._rootTarget;
10570 }
10571 if (this._rootTargetPromise) {
10572 return this._rootTargetPromise;
10573 }
10574 if (this._target instanceof Target) {
10575 this._emit("target", { target: this._target, request: null, isRoot: true });
10576 this._rootTarget = this._target;
10577 return this._target;
10578 }
10579 const request = {
10580 path: this._target.rootPath,
10581 isRoot: true,
10582 mimeType: this.format.mimeType
10583 };
10584 const result = this._getTargetValidated(request);
10585 const handleResult = (target) => {
10586 if (this.state === "canceled") {
10587 void target._close();
10588 } else {
10589 this._rememberTarget(target);
10590 }
10591 this._emit("target", { target, request, isRoot: true });
10592 this._rootTarget = target;
10593 return target;
10594 };
10595 if (result instanceof Promise) {
10596 return this._rootTargetPromise = result.then(handleResult);
10597 } else {
10598 return handleResult(result);
10599 }
10600 }
10601 /** @internal */
10602 _getRootWriter(isMonotonic) {
10603 return this._rootWriterPromise ??= (async () => {
10604 const target = await this._getRootTarget();
10605 const writer = new Writer(target, typeof isMonotonic === "boolean" ? isMonotonic : isMonotonic(target));
10606 writer.start();
10607 return writer;
10608 })();
10609 }
10610 /** Adds a video track to the output with the given source. Can only be called before the output is started. */
10611 addVideoTrack(source, metadata = {}) {
10612 if (!(source instanceof VideoSource)) {
10613 throw new TypeError("source must be a VideoSource.");
10614 }
10615 validateBaseTrackMetadata(metadata);
10616 if (metadata.rotation !== void 0 && ![0, 90, 180, 270].includes(metadata.rotation)) {
10617 throw new TypeError(\`Invalid video rotation: \${metadata.rotation}. Has to be 0, 90, 180 or 270.\`);
10618 }
10619 if (!this.format.supportsVideoRotationMetadata && metadata.rotation) {
10620 throw new Error(\`\${this.format._name} does not support video rotation metadata.\`);
10621 }
10622 if (metadata.frameRate !== void 0 && (!Number.isFinite(metadata.frameRate) || metadata.frameRate <= 0)) {
10623 throw new TypeError(\`Invalid video frame rate: \${metadata.frameRate}. Must be a positive number.\`);
10624 }
10625 const metadataCopy = { ...metadata };
10626 metadataCopy.group ??= this.defaultTrackGroup;
10627 return this._addTrack(new OutputVideoTrack(this._tracks.length + 1, this, source, metadataCopy));
10628 }
10629 /** Adds an audio track to the output with the given source. Can only be called before the output is started. */
10630 addAudioTrack(source, metadata = {}) {
10631 if (!(source instanceof AudioSource)) {
10632 throw new TypeError("source must be an AudioSource.");
10633 }
10634 validateBaseTrackMetadata(metadata);
10635 const metadataCopy = { ...metadata };
10636 metadataCopy.group ??= this.defaultTrackGroup;
10637 return this._addTrack(new OutputAudioTrack(this._tracks.length + 1, this, source, metadataCopy));
10638 }
10639 /** Adds a subtitle track to the output with the given source. Can only be called before the output is started. */
10640 addSubtitleTrack(source, metadata = {}) {
10641 if (!(source instanceof SubtitleSource)) {
10642 throw new TypeError("source must be a SubtitleSource.");
10643 }
10644 validateBaseTrackMetadata(metadata);
10645 const metadataCopy = { ...metadata };
10646 metadataCopy.group ??= this.defaultTrackGroup;
10647 return this._addTrack(new OutputSubtitleTrack(this._tracks.length + 1, this, source, metadataCopy));
10648 }
10649 /**
10650 * Sets descriptive metadata tags about the media file, such as title, author, date, or cover art. When called
10651 * multiple times, only the metadata from the last call will be used.
10652 *
10653 * Can only be called before the output is started.
10654 */
10655 setMetadataTags(tags) {
10656 validateMetadataTags(tags);
10657 if (this.state !== "pending") {
10658 throw new Error("Cannot set metadata tags after output has been started or canceled.");
10659 }
10660 this._metadataTags = tags;
10661 }
10662 /** @internal */
10663 _addTrack(track) {
10664 if (this.state !== "pending") {
10665 throw new Error("Cannot add track after output has been started or canceled.");
10666 }
10667 if (track.source._connectedTrack) {
10668 throw new Error("Source is already used for a track.");
10669 }
10670 const supportedTrackCounts = this.format.getSupportedTrackCounts();
10671 const presentTracksOfThisType = this._tracks.reduce((count, t2) => count + (t2.type === track.type ? 1 : 0), 0);
10672 const maxCount = supportedTrackCounts[track.type].max;
10673 if (presentTracksOfThisType === maxCount) {
10674 throw new Error(maxCount === 0 ? \`\${this.format._name} does not support \${track.type} tracks.\` : \`\${this.format._name} does not support more than \${maxCount} \${track.type} track\${maxCount === 1 ? "" : "s"}.\`);
10675 }
10676 const maxTotalCount = supportedTrackCounts.total.max;
10677 if (this._tracks.length === maxTotalCount) {
10678 throw new Error(\`\${this.format._name} does not support more than \${maxTotalCount} tracks\${maxTotalCount === 1 ? "" : "s"} in total.\`);
10679 }
10680 if (track.isVideoTrack()) {
10681 const supportedVideoCodecs = this.format.getSupportedVideoCodecs();
10682 if (supportedVideoCodecs.length === 0) {
10683 throw new Error(\`\${this.format._name} does not support video tracks.\` + this.format._codecUnsupportedHint(track.source._codec));
10684 } else if (!supportedVideoCodecs.includes(track.source._codec)) {
10685 throw new Error(\`Codec '\${track.source._codec}' cannot be contained within \${this.format._name}. Supported video codecs are: \${supportedVideoCodecs.map((codec) => \`'\${codec}'\`).join(", ")}.\` + this.format._codecUnsupportedHint(track.source._codec));
10686 }
10687 } else if (track.isAudioTrack()) {
10688 const supportedAudioCodecs = this.format.getSupportedAudioCodecs();
10689 if (supportedAudioCodecs.length === 0) {
10690 throw new Error(\`\${this.format._name} does not support audio tracks.\` + this.format._codecUnsupportedHint(track.source._codec));
10691 } else if (!supportedAudioCodecs.includes(track.source._codec)) {
10692 throw new Error(\`Codec '\${track.source._codec}' cannot be contained within \${this.format._name}. Supported audio codecs are: \${supportedAudioCodecs.map((codec) => \`'\${codec}'\`).join(", ")}.\` + this.format._codecUnsupportedHint(track.source._codec));
10693 }
10694 } else if (track.isSubtitleTrack()) {
10695 const supportedSubtitleCodecs = this.format.getSupportedSubtitleCodecs();
10696 if (supportedSubtitleCodecs.length === 0) {
10697 throw new Error(\`\${this.format._name} does not support subtitle tracks.\` + this.format._codecUnsupportedHint(track.source._codec));
10698 } else if (!supportedSubtitleCodecs.includes(track.source._codec)) {
10699 throw new Error(\`Codec '\${track.source._codec}' cannot be contained within \${this.format._name}. Supported subtitle codecs are: \${supportedSubtitleCodecs.map((codec) => \`'\${codec}'\`).join(", ")}.\` + this.format._codecUnsupportedHint(track.source._codec));
10700 }
10701 }
10702 this._tracks.push(track);
10703 track.source._connectedTrack = track;
10704 return track;
10705 }
10706 /**
10707 * Starts the creation of the output file. This method should be called after all tracks have been added. Only after
10708 * the output has started can media samples be added to the tracks.
10709 *
10710 * @returns A promise that resolves when the output has successfully started and is ready to receive media samples.
10711 */
10712 async start() {
10713 const supportedTrackCounts = this.format.getSupportedTrackCounts();
10714 for (const trackType of ALL_TRACK_TYPES) {
10715 const presentTracksOfThisType = this._tracks.reduce((count, track) => count + (track.type === trackType ? 1 : 0), 0);
10716 const minCount = supportedTrackCounts[trackType].min;
10717 if (presentTracksOfThisType < minCount) {
10718 throw new Error(minCount === supportedTrackCounts[trackType].max ? \`\${this.format._name} requires exactly \${minCount} \${trackType} track\${minCount === 1 ? "" : "s"}.\` : \`\${this.format._name} requires at least \${minCount} \${trackType} track\${minCount === 1 ? "" : "s"}.\`);
10719 }
10720 }
10721 const totalMinCount = supportedTrackCounts.total.min;
10722 if (this._tracks.length < totalMinCount) {
10723 throw new Error(totalMinCount === supportedTrackCounts.total.max ? \`\${this.format._name} requires exactly \${totalMinCount} track\${totalMinCount === 1 ? "" : "s"}.\` : \`\${this.format._name} requires at least \${totalMinCount} track\${totalMinCount === 1 ? "" : "s"}.\`);
10724 }
10725 if (this.state === "canceled") {
10726 throw new Error("Output has been canceled.");
10727 }
10728 if (this._startPromise) {
10729 Logging._warn("Output has already been started.");
10730 return this._startPromise;
10731 }
10732 return this._startPromise = (async () => {
10733 this.state = "started";
10734 const release = await this._mutex.acquire();
10735 try {
10736 await this._muxer.start();
10737 const promises = this._tracks.map((track) => track.source._start());
10738 await Promise.all(promises);
10739 } finally {
10740 release();
10741 }
10742 })();
10743 }
10744 /**
10745 * Resolves with the full MIME type of the output file, including track codecs.
10746 *
10747 * The returned promise will resolve only once the precise codec strings of all tracks are known.
10748 */
10749 getMimeType() {
10750 return this._muxer.getMimeType();
10751 }
10752 /**
10753 * Cancels the creation of the output file, releasing internal resources like encoders and preventing further
10754 * samples from being added.
10755 *
10756 * @returns A promise that resolves once all internal resources have been released.
10757 */
10758 async cancel() {
10759 if (this._cancelPromise) {
10760 Logging._warn("Output has already been canceled.");
10761 return this._cancelPromise;
10762 } else if (this.state === "finalizing" || this.state === "finalized") {
10763 if (this.state === "finalized") {
10764 Logging._warn("Output has already been finalized.");
10765 }
10766 return;
10767 }
10768 return this._cancelPromise = (async () => {
10769 this.state = "canceled";
10770 const release = await this._mutex.acquire();
10771 try {
10772 const promises = this._tracks.map((x) => x.source._flushOrWaitForOngoingClose(true));
10773 await Promise.all(promises);
10774 await Promise.all([...this._unfinalizedTargets].map((target) => target._close()));
10775 this._unfinalizedTargets.clear();
10776 } finally {
10777 release();
10778 }
10779 })();
10780 }
10781 /**
10782 * Finalizes the output file. This method must be called after all media samples across all tracks have been added.
10783 * Once the Promise returned by this method completes, the output file is ready.
10784 */
10785 async finalize() {
10786 if (this.state === "pending") {
10787 throw new Error("Cannot finalize before starting.");
10788 }
10789 if (this.state === "canceled") {
10790 throw new Error("Cannot finalize after canceling.");
10791 }
10792 if (this._finalizePromise) {
10793 Logging._warn("Output has already been finalized.");
10794 return this._finalizePromise;
10795 }
10796 return this._finalizePromise = (async () => {
10797 this.state = "finalizing";
10798 const release = await this._mutex.acquire();
10799 try {
10800 const promises = this._tracks.map((x) => x.source._flushOrWaitForOngoingClose(false));
10801 await Promise.all(promises);
10802 await this._muxer.finalize();
10803 if (this._rootWriterPromise) {
10804 const rootWriter = await this._rootWriterPromise;
10805 if (!rootWriter.finalized) {
10806 await rootWriter.flush();
10807 await rootWriter.finalize();
10808 }
10809 }
10810 if (this._onFinalize) {
10811 await this._onFinalize();
10812 }
10813 this.state = "finalized";
10814 } finally {
10815 release();
10816 }
10817 })();
10818 }
10819 };
10820
10821 // node_modules/mediabunny/dist/modules/src/index.js
10822 var MEDIABUNNY_LOADED_SYMBOL = /* @__PURE__ */ Symbol.for("mediabunny loaded");
10823 if (globalThis[MEDIABUNNY_LOADED_SYMBOL]) {
10824 Logging._error("[WARNING]\\nMediabunny was loaded twice. This will likely cause Mediabunny not to work correctly. Check if multiple dependencies are importing different versions of Mediabunny, or if something is being bundled incorrectly.");
10825 }
10826 globalThis[MEDIABUNNY_LOADED_SYMBOL] = true;
10827
10828 // packages/video-conversion/src/index.ts
10829 var inProgressOperations = /* @__PURE__ */ new Set();
10830 var GIF_DEFAULT_FRAME_DURATION_US = 1e5;
10831 var UNSUPPORTED_ERROR_PREFIX = "Unsupported";
10832 var SIZE_LIMIT_ERROR_PREFIX = \`\${UNSUPPORTED_ERROR_PREFIX}: GIF exceeds maximum conversion size\`;
10833 var DEFAULT_MAX_TOTAL_PIXELS = 3e8;
10834 var operationLock = Promise.resolve();
10835 async function cancelOperations(id) {
10836 return inProgressOperations.delete(id);
10837 }
10838 function padToEven(value) {
10839 return value % 2 === 0 ? value : value + 1;
10840 }
10841 async function convertGifToVideo(id, gifSource, outputMimeType, maxDimensions, maxTotalPixels) {
10842 inProgressOperations.add(id);
10843 const previousLock = operationLock;
10844 let releaseLock = () => {
10845 };
10846 operationLock = new Promise((resolve) => {
10847 releaseLock = resolve;
10848 });
10849 try {
10850 await previousLock;
10851 if (!inProgressOperations.has(id)) {
10852 throw new Error("Operation cancelled");
10853 }
10854 if (typeof ImageDecoder === "undefined" || typeof VideoEncoder === "undefined") {
10855 throw new Error(
10856 \`\${UNSUPPORTED_ERROR_PREFIX}: WebCodecs unavailable\`
10857 );
10858 }
10859 const isWebm = outputMimeType === "video/webm";
10860 const codec = isWebm ? "vp9" : "avc";
10861 if (!await canEncodeVideo(codec)) {
10862 throw new Error(
10863 \`\${UNSUPPORTED_ERROR_PREFIX}: encoder codec not supported\`
10864 );
10865 }
10866 if (!inProgressOperations.has(id)) {
10867 throw new Error("Operation cancelled");
10868 }
10869 const data = gifSource instanceof ArrayBuffer ? gifSource : await gifSource.arrayBuffer();
10870 if (!inProgressOperations.has(id)) {
10871 throw new Error("Operation cancelled");
10872 }
10873 const decoder = new ImageDecoder({
10874 data,
10875 type: "image/gif"
10876 });
10877 try {
10878 await decoder.tracks.ready;
10879 if (!inProgressOperations.has(id)) {
10880 throw new Error("Operation cancelled");
10881 }
10882 const track = decoder.tracks.selectedTrack;
10883 const frameCount = track?.frameCount ?? 0;
10884 if (frameCount === 0) {
10885 throw new Error("GIF contains no decodable frames");
10886 }
10887 const pixelBudget = maxTotalPixels ?? DEFAULT_MAX_TOTAL_PIXELS;
10888 if (pixelBudget > 0) {
10889 const { image: probe } = await decoder.decode({
10890 frameIndex: 0
10891 });
10892 const probeWidth = probe.displayWidth;
10893 const probeHeight = probe.displayHeight;
10894 probe.close();
10895 if (!inProgressOperations.has(id)) {
10896 throw new Error("Operation cancelled");
10897 }
10898 const totalPixels = probeWidth * probeHeight * frameCount;
10899 if (totalPixels > pixelBudget) {
10900 throw new Error(
10901 \`\${SIZE_LIMIT_ERROR_PREFIX} (\${probeWidth}x\${probeHeight} x \${frameCount} frames = \${totalPixels} pixels; limit is \${pixelBudget})\`
10902 );
10903 }
10904 }
10905 const source = new VideoSampleSource({
10906 codec,
10907 bitrate: QUALITY_HIGH,
10908 /*
10909 * A sparser key frame cadence than mediabunny's 2s default
10910 * roughly halves the output size for long GIFs at no
10911 * encode-time or quality cost. These looping, autoplaying
10912 * GIF replacements don't need fine seek granularity.
10913 */
10914 keyFrameInterval: 10
10915 });
10916 const target = new BufferTarget();
10917 const output = new Output({
10918 format: isWebm ? new WebMOutputFormat() : new Mp4OutputFormat(),
10919 target
10920 });
10921 output.addVideoTrack(source);
10922 await output.start();
10923 let timestampSec = 0;
10924 for (let i2 = 0; i2 < frameCount; i2++) {
10925 if (!inProgressOperations.has(id)) {
10926 throw new Error("Operation cancelled");
10927 }
10928 const { image } = await decoder.decode({ frameIndex: i2 });
10929 const durationUs = image.duration ?? GIF_DEFAULT_FRAME_DURATION_US;
10930 const durationSec = durationUs / 1e6;
10931 const srcW = image.displayWidth;
10932 const srcH = image.displayHeight;
10933 let targetW = srcW;
10934 let targetH = srcH;
10935 if (maxDimensions && (srcW > maxDimensions || srcH > maxDimensions)) {
10936 const scale = Math.min(
10937 maxDimensions / srcW,
10938 maxDimensions / srcH
10939 );
10940 targetW = Math.round(srcW * scale);
10941 targetH = Math.round(srcH * scale);
10942 }
10943 targetW = padToEven(targetW);
10944 targetH = padToEven(targetH);
10945 let frameForEncode = image;
10946 if (targetW !== srcW || targetH !== srcH) {
10947 const canvas = new OffscreenCanvas(targetW, targetH);
10948 const ctx = canvas.getContext("2d");
10949 if (!ctx) {
10950 throw new Error("Failed to create 2D canvas context");
10951 }
10952 ctx.drawImage(image, 0, 0, targetW, targetH);
10953 frameForEncode = new VideoFrame(canvas, {
10954 timestamp: Math.round(timestampSec * 1e6),
10955 duration: durationUs
10956 });
10957 image.close();
10958 }
10959 const sample = new VideoSample(frameForEncode, {
10960 timestamp: timestampSec,
10961 duration: durationSec
10962 });
10963 try {
10964 await source.add(sample);
10965 } finally {
10966 sample.close();
10967 frameForEncode.close();
10968 }
10969 timestampSec += durationSec;
10970 }
10971 await output.finalize();
10972 const out = target.buffer;
10973 if (!out || out.byteLength === 0) {
10974 throw new Error("Encoder produced empty output");
10975 }
10976 return out;
10977 } finally {
10978 decoder.close();
10979 }
10980 } finally {
10981 inProgressOperations.delete(id);
10982 releaseLock();
10983 }
10984 }
10985
10986 // packages/video-conversion/src/worker.ts
10987 var api = {
10988 cancelOperations,
10989 convertGifToVideo
10990 };
10991 expose(api);
10992 /*! Bundled license information:
10993
10994 mediabunny/dist/modules/src/misc.js:
10995 mediabunny/dist/modules/src/logging.js:
10996 mediabunny/dist/modules/src/metadata.js:
10997 mediabunny/dist/modules/shared/bitstream.js:
10998 mediabunny/dist/modules/shared/aac-misc.js:
10999 mediabunny/dist/modules/src/codec.js:
11000 mediabunny/dist/modules/shared/ac3-misc.js:
11001 mediabunny/dist/modules/src/codec-data.js:
11002 mediabunny/dist/modules/src/packet.js:
11003 mediabunny/dist/modules/src/isobmff/isobmff-misc.js:
11004 mediabunny/dist/modules/src/isobmff/isobmff-reader.js:
11005 mediabunny/dist/modules/src/matroska/ebml.js:
11006 mediabunny/dist/modules/src/matroska/matroska-misc.js:
11007 mediabunny/dist/modules/src/adts/adts-reader.js:
11008 mediabunny/dist/modules/src/sample.js:
11009 mediabunny/dist/modules/src/encode.js:
11010 mediabunny/dist/modules/src/custom-coder.js:
11011 mediabunny/dist/modules/src/reader.js:
11012 mediabunny/dist/modules/src/muxer.js:
11013 mediabunny/dist/modules/src/subtitles.js:
11014 mediabunny/dist/modules/src/isobmff/isobmff-boxes.js:
11015 mediabunny/dist/modules/src/writer.js:
11016 mediabunny/dist/modules/src/target.js:
11017 mediabunny/dist/modules/src/isobmff/isobmff-muxer.js:
11018 mediabunny/dist/modules/src/matroska/matroska-muxer.js:
11019 mediabunny/dist/modules/src/media-source.js:
11020 mediabunny/dist/modules/src/output-format.js:
11021 mediabunny/dist/modules/src/output.js:
11022 mediabunny/dist/modules/src/index.js:
11023 (*!
11024 * Copyright (c) 2026-present, Vanilagy and contributors
11025 *
11026 * This Source Code Form is subject to the terms of the Mozilla Public
11027 * License, v. 2.0. If a copy of the MPL was not distributed with this
11028 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
11029 *)
11030 */
11031 //# sourceMappingURL=worker.mjs.map
11032 `;var B,v,T;function F(){if(v===void 0){let e=new Blob([O],{type:"application/javascript"});T=URL.createObjectURL(e),B=new Worker(T,{type:"module"}),v=_(B)}return v}async function ce(e,n,t,a,i){return F().convertGifToVideo(e,n,t,a,i)}async function de(e){return F().cancelOperations(e)}function le(){v&&(I(v),v=void 0,B=void 0),T&&(URL.revokeObjectURL(T),T=void 0)}export{de as cancelGifToVideoOperations,ce as convertGifToVideo,le as terminateVideoConversionWorker};
11033