@fluxerjs/voice 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,2582 @@
1
- import "./chunk-EBO3CZXG.mjs";
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoColorSpace.js
34
+ var require_VideoColorSpace = __commonJS({
35
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoColorSpace.js"(exports) {
36
+ "use strict";
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.VideoColorSpace = void 0;
39
+ var VideoColorSpace = class {
40
+ constructor(init) {
41
+ this.primaries = init?.primaries ?? null;
42
+ this.transfer = init?.transfer ?? null;
43
+ this.matrix = init?.matrix ?? null;
44
+ this.fullRange = init?.fullRange ?? null;
45
+ }
46
+ toJSON() {
47
+ return {
48
+ primaries: this.primaries,
49
+ transfer: this.transfer,
50
+ matrix: this.matrix,
51
+ fullRange: this.fullRange
52
+ };
53
+ }
54
+ };
55
+ exports.VideoColorSpace = VideoColorSpace;
56
+ }
57
+ });
58
+
59
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/types.js
60
+ var require_types = __commonJS({
61
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/types.js"(exports) {
62
+ "use strict";
63
+ Object.defineProperty(exports, "__esModule", { value: true });
64
+ exports.DOMException = exports.WebCodecsDOMException = exports.DOMRectReadOnly = void 0;
65
+ exports.createDOMException = createDOMException;
66
+ var DOMRectReadOnly = class {
67
+ constructor(x = 0, y = 0, width = 0, height = 0) {
68
+ this.x = x;
69
+ this.y = y;
70
+ this.width = width;
71
+ this.height = height;
72
+ this.top = y;
73
+ this.right = x + width;
74
+ this.bottom = y + height;
75
+ this.left = x;
76
+ }
77
+ toJSON() {
78
+ return { x: this.x, y: this.y, width: this.width, height: this.height };
79
+ }
80
+ };
81
+ exports.DOMRectReadOnly = DOMRectReadOnly;
82
+ var WebCodecsDOMException = class _WebCodecsDOMException extends Error {
83
+ constructor(message, name) {
84
+ super(message);
85
+ this.name = name ?? "Error";
86
+ this.code = _WebCodecsDOMException.ERROR_CODES[this.name] ?? 0;
87
+ Object.setPrototypeOf(this, _WebCodecsDOMException.prototype);
88
+ }
89
+ };
90
+ exports.WebCodecsDOMException = WebCodecsDOMException;
91
+ exports.DOMException = WebCodecsDOMException;
92
+ WebCodecsDOMException.INDEX_SIZE_ERR = 1;
93
+ WebCodecsDOMException.DOMSTRING_SIZE_ERR = 2;
94
+ WebCodecsDOMException.HIERARCHY_REQUEST_ERR = 3;
95
+ WebCodecsDOMException.WRONG_DOCUMENT_ERR = 4;
96
+ WebCodecsDOMException.INVALID_CHARACTER_ERR = 5;
97
+ WebCodecsDOMException.NO_DATA_ALLOWED_ERR = 6;
98
+ WebCodecsDOMException.NO_MODIFICATION_ALLOWED_ERR = 7;
99
+ WebCodecsDOMException.NOT_FOUND_ERR = 8;
100
+ WebCodecsDOMException.NOT_SUPPORTED_ERR = 9;
101
+ WebCodecsDOMException.INUSE_ATTRIBUTE_ERR = 10;
102
+ WebCodecsDOMException.INVALID_STATE_ERR = 11;
103
+ WebCodecsDOMException.SYNTAX_ERR = 12;
104
+ WebCodecsDOMException.INVALID_MODIFICATION_ERR = 13;
105
+ WebCodecsDOMException.NAMESPACE_ERR = 14;
106
+ WebCodecsDOMException.INVALID_ACCESS_ERR = 15;
107
+ WebCodecsDOMException.VALIDATION_ERR = 16;
108
+ WebCodecsDOMException.TYPE_MISMATCH_ERR = 17;
109
+ WebCodecsDOMException.SECURITY_ERR = 18;
110
+ WebCodecsDOMException.NETWORK_ERR = 19;
111
+ WebCodecsDOMException.ABORT_ERR = 20;
112
+ WebCodecsDOMException.URL_MISMATCH_ERR = 21;
113
+ WebCodecsDOMException.QUOTA_EXCEEDED_ERR = 22;
114
+ WebCodecsDOMException.TIMEOUT_ERR = 23;
115
+ WebCodecsDOMException.INVALID_NODE_TYPE_ERR = 24;
116
+ WebCodecsDOMException.DATA_CLONE_ERR = 25;
117
+ WebCodecsDOMException.ERROR_CODES = {
118
+ IndexSizeError: 1,
119
+ HierarchyRequestError: 3,
120
+ WrongDocumentError: 4,
121
+ InvalidCharacterError: 5,
122
+ NoModificationAllowedError: 7,
123
+ NotFoundError: 8,
124
+ NotSupportedError: 9,
125
+ InUseAttributeError: 10,
126
+ InvalidStateError: 11,
127
+ SyntaxError: 12,
128
+ InvalidModificationError: 13,
129
+ NamespaceError: 14,
130
+ InvalidAccessError: 15,
131
+ TypeMismatchError: 17,
132
+ SecurityError: 18,
133
+ NetworkError: 19,
134
+ AbortError: 20,
135
+ URLMismatchError: 21,
136
+ QuotaExceededError: 22,
137
+ TimeoutError: 23,
138
+ InvalidNodeTypeError: 24,
139
+ DataCloneError: 25,
140
+ EncodingError: 0,
141
+ NotReadableError: 0,
142
+ UnknownError: 0,
143
+ ConstraintError: 0,
144
+ DataError: 0,
145
+ TransactionInactiveError: 0,
146
+ ReadOnlyError: 0,
147
+ VersionError: 0,
148
+ OperationError: 0
149
+ };
150
+ function createDOMException(message, name) {
151
+ return new WebCodecsDOMException(message, name);
152
+ }
153
+ }
154
+ });
155
+
156
+ // ../../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js
157
+ var require_node_gyp_build = __commonJS({
158
+ "../../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js"(exports, module) {
159
+ "use strict";
160
+ var fs = __require("fs");
161
+ var path = __require("path");
162
+ var os = __require("os");
163
+ var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
164
+ var vars = process.config && process.config.variables || {};
165
+ var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
166
+ var abi = process.versions.modules;
167
+ var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
168
+ var arch = process.env.npm_config_arch || os.arch();
169
+ var platform = process.env.npm_config_platform || os.platform();
170
+ var libc = process.env.LIBC || (isAlpine(platform) ? "musl" : "glibc");
171
+ var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
172
+ var uv = (process.versions.uv || "").split(".")[0];
173
+ module.exports = load;
174
+ function load(dir) {
175
+ return runtimeRequire(load.resolve(dir));
176
+ }
177
+ load.resolve = load.path = function(dir) {
178
+ dir = path.resolve(dir || ".");
179
+ try {
180
+ var name = runtimeRequire(path.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
181
+ if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
182
+ } catch (err) {
183
+ }
184
+ if (!prebuildsOnly) {
185
+ var release = getFirst(path.join(dir, "build/Release"), matchBuild);
186
+ if (release) return release;
187
+ var debug = getFirst(path.join(dir, "build/Debug"), matchBuild);
188
+ if (debug) return debug;
189
+ }
190
+ var prebuild = resolve(dir);
191
+ if (prebuild) return prebuild;
192
+ var nearby = resolve(path.dirname(process.execPath));
193
+ if (nearby) return nearby;
194
+ var target = [
195
+ "platform=" + platform,
196
+ "arch=" + arch,
197
+ "runtime=" + runtime,
198
+ "abi=" + abi,
199
+ "uv=" + uv,
200
+ armv ? "armv=" + armv : "",
201
+ "libc=" + libc,
202
+ "node=" + process.versions.node,
203
+ process.versions.electron ? "electron=" + process.versions.electron : "",
204
+ typeof __webpack_require__ === "function" ? "webpack=true" : ""
205
+ // eslint-disable-line
206
+ ].filter(Boolean).join(" ");
207
+ throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
208
+ function resolve(dir2) {
209
+ var tuples = readdirSync(path.join(dir2, "prebuilds")).map(parseTuple);
210
+ var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
211
+ if (!tuple) return;
212
+ var prebuilds = path.join(dir2, "prebuilds", tuple.name);
213
+ var parsed = readdirSync(prebuilds).map(parseTags);
214
+ var candidates = parsed.filter(matchTags(runtime, abi));
215
+ var winner = candidates.sort(compareTags(runtime))[0];
216
+ if (winner) return path.join(prebuilds, winner.file);
217
+ }
218
+ };
219
+ function readdirSync(dir) {
220
+ try {
221
+ return fs.readdirSync(dir);
222
+ } catch (err) {
223
+ return [];
224
+ }
225
+ }
226
+ function getFirst(dir, filter) {
227
+ var files = readdirSync(dir).filter(filter);
228
+ return files[0] && path.join(dir, files[0]);
229
+ }
230
+ function matchBuild(name) {
231
+ return /\.node$/.test(name);
232
+ }
233
+ function parseTuple(name) {
234
+ var arr = name.split("-");
235
+ if (arr.length !== 2) return;
236
+ var platform2 = arr[0];
237
+ var architectures = arr[1].split("+");
238
+ if (!platform2) return;
239
+ if (!architectures.length) return;
240
+ if (!architectures.every(Boolean)) return;
241
+ return { name, platform: platform2, architectures };
242
+ }
243
+ function matchTuple(platform2, arch2) {
244
+ return function(tuple) {
245
+ if (tuple == null) return false;
246
+ if (tuple.platform !== platform2) return false;
247
+ return tuple.architectures.includes(arch2);
248
+ };
249
+ }
250
+ function compareTuples(a, b) {
251
+ return a.architectures.length - b.architectures.length;
252
+ }
253
+ function parseTags(file) {
254
+ var arr = file.split(".");
255
+ var extension = arr.pop();
256
+ var tags = { file, specificity: 0 };
257
+ if (extension !== "node") return;
258
+ for (var i = 0; i < arr.length; i++) {
259
+ var tag = arr[i];
260
+ if (tag === "node" || tag === "electron" || tag === "node-webkit") {
261
+ tags.runtime = tag;
262
+ } else if (tag === "napi") {
263
+ tags.napi = true;
264
+ } else if (tag.slice(0, 3) === "abi") {
265
+ tags.abi = tag.slice(3);
266
+ } else if (tag.slice(0, 2) === "uv") {
267
+ tags.uv = tag.slice(2);
268
+ } else if (tag.slice(0, 4) === "armv") {
269
+ tags.armv = tag.slice(4);
270
+ } else if (tag === "glibc" || tag === "musl") {
271
+ tags.libc = tag;
272
+ } else {
273
+ continue;
274
+ }
275
+ tags.specificity++;
276
+ }
277
+ return tags;
278
+ }
279
+ function matchTags(runtime2, abi2) {
280
+ return function(tags) {
281
+ if (tags == null) return false;
282
+ if (tags.runtime && tags.runtime !== runtime2 && !runtimeAgnostic(tags)) return false;
283
+ if (tags.abi && tags.abi !== abi2 && !tags.napi) return false;
284
+ if (tags.uv && tags.uv !== uv) return false;
285
+ if (tags.armv && tags.armv !== armv) return false;
286
+ if (tags.libc && tags.libc !== libc) return false;
287
+ return true;
288
+ };
289
+ }
290
+ function runtimeAgnostic(tags) {
291
+ return tags.runtime === "node" && tags.napi;
292
+ }
293
+ function compareTags(runtime2) {
294
+ return function(a, b) {
295
+ if (a.runtime !== b.runtime) {
296
+ return a.runtime === runtime2 ? -1 : 1;
297
+ } else if (a.abi !== b.abi) {
298
+ return a.abi ? -1 : 1;
299
+ } else if (a.specificity !== b.specificity) {
300
+ return a.specificity > b.specificity ? -1 : 1;
301
+ } else {
302
+ return 0;
303
+ }
304
+ };
305
+ }
306
+ function isNwjs() {
307
+ return !!(process.versions && process.versions.nw);
308
+ }
309
+ function isElectron() {
310
+ if (process.versions && process.versions.electron) return true;
311
+ if (process.env.ELECTRON_RUN_AS_NODE) return true;
312
+ return typeof window !== "undefined" && window.process && window.process.type === "renderer";
313
+ }
314
+ function isAlpine(platform2) {
315
+ return platform2 === "linux" && fs.existsSync("/etc/alpine-release");
316
+ }
317
+ load.parseTags = parseTags;
318
+ load.matchTags = matchTags;
319
+ load.compareTags = compareTags;
320
+ load.parseTuple = parseTuple;
321
+ load.matchTuple = matchTuple;
322
+ load.compareTuples = compareTuples;
323
+ }
324
+ });
325
+
326
+ // ../../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/index.js
327
+ var require_node_gyp_build2 = __commonJS({
328
+ "../../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/index.js"(exports, module) {
329
+ "use strict";
330
+ var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
331
+ if (typeof runtimeRequire.addon === "function") {
332
+ module.exports = runtimeRequire.addon.bind(runtimeRequire);
333
+ } else {
334
+ module.exports = require_node_gyp_build();
335
+ }
336
+ }
337
+ });
338
+
339
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/native.js
340
+ var require_native = __commonJS({
341
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/native.js"(exports) {
342
+ "use strict";
343
+ var __importDefault = exports && exports.__importDefault || function(mod) {
344
+ return mod && mod.__esModule ? mod : { "default": mod };
345
+ };
346
+ Object.defineProperty(exports, "__esModule", { value: true });
347
+ exports.native = void 0;
348
+ var path_1 = __importDefault(__require("path"));
349
+ var nodeGypBuild = require_node_gyp_build2();
350
+ var native;
351
+ try {
352
+ exports.native = native = nodeGypBuild(path_1.default.join(__dirname, ".."));
353
+ } catch (error) {
354
+ exports.native = native = new Proxy({}, {
355
+ get() {
356
+ throw error;
357
+ }
358
+ });
359
+ }
360
+ }
361
+ });
362
+
363
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoFrame.js
364
+ var require_VideoFrame = __commonJS({
365
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoFrame.js"(exports) {
366
+ "use strict";
367
+ Object.defineProperty(exports, "__esModule", { value: true });
368
+ exports.VideoFrame = void 0;
369
+ var VideoColorSpace_1 = require_VideoColorSpace();
370
+ var types_1 = require_types();
371
+ var native_1 = require_native();
372
+ var VideoFrame2 = class _VideoFrame {
373
+ // Per WebCodecs spec, after close() these should return null/0
374
+ // Note: timestamp is preserved after close per spec
375
+ get format() {
376
+ return this._closed ? null : this._format;
377
+ }
378
+ get codedWidth() {
379
+ return this._closed ? 0 : this._codedWidth;
380
+ }
381
+ get codedHeight() {
382
+ return this._closed ? 0 : this._codedHeight;
383
+ }
384
+ get displayWidth() {
385
+ return this._closed ? 0 : this._displayWidth;
386
+ }
387
+ get displayHeight() {
388
+ return this._closed ? 0 : this._displayHeight;
389
+ }
390
+ get timestamp() {
391
+ return this._timestamp;
392
+ }
393
+ get duration() {
394
+ return this._closed ? null : this._duration;
395
+ }
396
+ get colorSpace() {
397
+ return this._colorSpace;
398
+ }
399
+ get visibleRect() {
400
+ return this._closed ? null : this._visibleRect;
401
+ }
402
+ constructor(dataOrImage, init) {
403
+ this._closed = false;
404
+ this._buffer = null;
405
+ if (dataOrImage instanceof _VideoFrame) {
406
+ if (dataOrImage._closed) {
407
+ throw new types_1.DOMException("Source VideoFrame is closed", "InvalidStateError");
408
+ }
409
+ this._native = dataOrImage._native ? dataOrImage._native.clone() : null;
410
+ this._buffer = dataOrImage._buffer ? new Uint8Array(dataOrImage._buffer) : null;
411
+ this._format = dataOrImage._format;
412
+ this._codedWidth = dataOrImage._codedWidth;
413
+ this._codedHeight = dataOrImage._codedHeight;
414
+ this._displayWidth = init?.displayWidth ?? dataOrImage._displayWidth;
415
+ this._displayHeight = init?.displayHeight ?? dataOrImage._displayHeight;
416
+ this._timestamp = init?.timestamp ?? dataOrImage._timestamp;
417
+ this._duration = init?.duration ?? dataOrImage._duration;
418
+ this._colorSpace = dataOrImage._colorSpace;
419
+ this._visibleRect = dataOrImage._visibleRect;
420
+ } else {
421
+ const bufferInit = init;
422
+ if (!bufferInit?.format || !bufferInit.codedWidth || !bufferInit.codedHeight) {
423
+ throw new TypeError("format, codedWidth, and codedHeight are required");
424
+ }
425
+ if (bufferInit.timestamp === void 0) {
426
+ throw new TypeError("timestamp is required");
427
+ }
428
+ let buffer;
429
+ if (dataOrImage instanceof ArrayBuffer) {
430
+ buffer = new Uint8Array(dataOrImage);
431
+ } else {
432
+ buffer = new Uint8Array(dataOrImage.buffer, dataOrImage.byteOffset, dataOrImage.byteLength);
433
+ }
434
+ this._buffer = new Uint8Array(buffer);
435
+ if (native_1.native) {
436
+ try {
437
+ this._native = native_1.native.createVideoFrame(Buffer.from(buffer), bufferInit.format, bufferInit.codedWidth, bufferInit.codedHeight);
438
+ } catch (e) {
439
+ this._native = null;
440
+ }
441
+ }
442
+ this._format = bufferInit.format;
443
+ this._codedWidth = bufferInit.codedWidth;
444
+ this._codedHeight = bufferInit.codedHeight;
445
+ this._displayWidth = bufferInit.displayWidth ?? bufferInit.codedWidth;
446
+ this._displayHeight = bufferInit.displayHeight ?? bufferInit.codedHeight;
447
+ this._timestamp = bufferInit.timestamp;
448
+ this._duration = bufferInit.duration ?? null;
449
+ const isRgbFormat = ["RGBA", "RGBX", "BGRA", "BGRX"].includes(bufferInit.format);
450
+ const defaultColorSpace = isRgbFormat ? { primaries: "bt709", transfer: "iec61966-2-1", matrix: "rgb", fullRange: true } : { primaries: "bt709", transfer: "bt709", matrix: "bt709", fullRange: false };
451
+ this._colorSpace = new VideoColorSpace_1.VideoColorSpace({
452
+ primaries: bufferInit.colorSpace?.primaries ?? defaultColorSpace.primaries,
453
+ transfer: bufferInit.colorSpace?.transfer ?? defaultColorSpace.transfer,
454
+ matrix: bufferInit.colorSpace?.matrix ?? defaultColorSpace.matrix,
455
+ fullRange: bufferInit.colorSpace?.fullRange ?? defaultColorSpace.fullRange
456
+ });
457
+ this._visibleRect = bufferInit.visibleRect ? new types_1.DOMRectReadOnly(bufferInit.visibleRect.x, bufferInit.visibleRect.y, bufferInit.visibleRect.width, bufferInit.visibleRect.height) : new types_1.DOMRectReadOnly(0, 0, bufferInit.codedWidth, bufferInit.codedHeight);
458
+ }
459
+ }
460
+ /**
461
+ * Get the native frame handle (internal use only)
462
+ */
463
+ _getNative() {
464
+ this._assertNotClosed();
465
+ return this._native;
466
+ }
467
+ /**
468
+ * Calculate the size in bytes needed to hold the frame data
469
+ */
470
+ allocationSize(options) {
471
+ this._assertNotClosed();
472
+ const width = options?.rect?.width ?? this.codedWidth;
473
+ const height = options?.rect?.height ?? this.codedHeight;
474
+ const targetFormat = options?.format ?? this.format;
475
+ return this._calculateFormatSize(targetFormat, width, height);
476
+ }
477
+ _calculateFormatSize(format, width, height) {
478
+ switch (format) {
479
+ case "RGBA":
480
+ case "RGBX":
481
+ case "BGRA":
482
+ case "BGRX":
483
+ return width * height * 4;
484
+ case "I420":
485
+ return Math.floor(width * height * 1.5);
486
+ case "I420A":
487
+ return width * height * 2;
488
+ case "I422":
489
+ return width * height * 2;
490
+ case "I444":
491
+ return width * height * 3;
492
+ case "NV12":
493
+ return Math.floor(width * height * 1.5);
494
+ default:
495
+ return width * height * 4;
496
+ }
497
+ }
498
+ /**
499
+ * Copy the frame data to a destination buffer
500
+ */
501
+ async copyTo(destination, options) {
502
+ this._assertNotClosed();
503
+ let dest;
504
+ if (destination instanceof ArrayBuffer) {
505
+ dest = new Uint8Array(destination);
506
+ } else {
507
+ dest = new Uint8Array(destination.buffer, destination.byteOffset, destination.byteLength);
508
+ }
509
+ if (this._native) {
510
+ this._native.copyTo(Buffer.from(dest.buffer, dest.byteOffset, dest.byteLength), options);
511
+ } else if (this._buffer) {
512
+ const size = Math.min(dest.byteLength, this._buffer.byteLength);
513
+ dest.set(this._buffer.subarray(0, size));
514
+ }
515
+ return this._getPlaneLayouts(options);
516
+ }
517
+ /**
518
+ * Create a clone of this frame
519
+ */
520
+ clone() {
521
+ this._assertNotClosed();
522
+ return new _VideoFrame(this);
523
+ }
524
+ /**
525
+ * Close the frame and release resources
526
+ */
527
+ close() {
528
+ if (!this._closed) {
529
+ if (this._native) {
530
+ this._native.close();
531
+ this._native = null;
532
+ }
533
+ this._buffer = null;
534
+ this._closed = true;
535
+ }
536
+ }
537
+ _assertNotClosed() {
538
+ if (this._closed) {
539
+ throw new types_1.DOMException("VideoFrame is closed", "InvalidStateError");
540
+ }
541
+ }
542
+ _getPlaneLayouts(options) {
543
+ const width = options?.rect?.width ?? this.codedWidth;
544
+ const height = options?.rect?.height ?? this.codedHeight;
545
+ const targetFormat = options?.format ?? this.format;
546
+ switch (targetFormat) {
547
+ case "RGBA":
548
+ case "RGBX":
549
+ case "BGRA":
550
+ case "BGRX":
551
+ return [{ offset: 0, stride: width * 4 }];
552
+ case "I420": {
553
+ const ySize = width * height;
554
+ const uvSize = Math.floor(width / 2 * (height / 2));
555
+ return [
556
+ { offset: 0, stride: width },
557
+ { offset: ySize, stride: Math.floor(width / 2) },
558
+ { offset: ySize + uvSize, stride: Math.floor(width / 2) }
559
+ ];
560
+ }
561
+ case "I420A": {
562
+ const ySize = width * height;
563
+ const uvSize = Math.floor(width / 2 * (height / 2));
564
+ return [
565
+ { offset: 0, stride: width },
566
+ { offset: ySize, stride: Math.floor(width / 2) },
567
+ { offset: ySize + uvSize, stride: Math.floor(width / 2) },
568
+ { offset: ySize + 2 * uvSize, stride: width }
569
+ ];
570
+ }
571
+ case "I422": {
572
+ const ySize = width * height;
573
+ const uvSize = Math.floor(width / 2 * height);
574
+ return [
575
+ { offset: 0, stride: width },
576
+ { offset: ySize, stride: Math.floor(width / 2) },
577
+ { offset: ySize + uvSize, stride: Math.floor(width / 2) }
578
+ ];
579
+ }
580
+ case "I444": {
581
+ const planeSize = width * height;
582
+ return [
583
+ { offset: 0, stride: width },
584
+ { offset: planeSize, stride: width },
585
+ { offset: planeSize * 2, stride: width }
586
+ ];
587
+ }
588
+ case "NV12": {
589
+ const ySize = width * height;
590
+ return [
591
+ { offset: 0, stride: width },
592
+ { offset: ySize, stride: width }
593
+ ];
594
+ }
595
+ default:
596
+ return [{ offset: 0, stride: width * 4 }];
597
+ }
598
+ }
599
+ };
600
+ exports.VideoFrame = VideoFrame2;
601
+ }
602
+ });
603
+
604
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/AudioData.js
605
+ var require_AudioData = __commonJS({
606
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/AudioData.js"(exports) {
607
+ "use strict";
608
+ Object.defineProperty(exports, "__esModule", { value: true });
609
+ exports.AudioData = void 0;
610
+ var types_1 = require_types();
611
+ var native_1 = require_native();
612
+ function getBytesPerSample(format) {
613
+ switch (format) {
614
+ case "u8":
615
+ case "u8-planar":
616
+ return 1;
617
+ case "s16":
618
+ case "s16-planar":
619
+ return 2;
620
+ case "s32":
621
+ case "s32-planar":
622
+ case "f32":
623
+ case "f32-planar":
624
+ return 4;
625
+ default:
626
+ return 4;
627
+ }
628
+ }
629
+ function isPlanar(format) {
630
+ return format.endsWith("-planar");
631
+ }
632
+ var AudioData = class _AudioData {
633
+ // Per WebCodecs spec, after close() these should return null/0
634
+ get format() {
635
+ return this._closed ? null : this._format;
636
+ }
637
+ get sampleRate() {
638
+ return this._closed ? 0 : this._sampleRate;
639
+ }
640
+ get numberOfFrames() {
641
+ return this._closed ? 0 : this._numberOfFrames;
642
+ }
643
+ get numberOfChannels() {
644
+ return this._closed ? 0 : this._numberOfChannels;
645
+ }
646
+ get duration() {
647
+ return this._closed ? 0 : this._duration;
648
+ }
649
+ get timestamp() {
650
+ return this._closed ? 0 : this._timestamp;
651
+ }
652
+ constructor(init) {
653
+ this._closed = false;
654
+ this._buffer = null;
655
+ if (!init.format) {
656
+ throw new TypeError("format is required");
657
+ }
658
+ if (!init.sampleRate || init.sampleRate <= 0) {
659
+ throw new TypeError("sampleRate must be positive");
660
+ }
661
+ if (!init.numberOfFrames || init.numberOfFrames <= 0) {
662
+ throw new TypeError("numberOfFrames must be positive");
663
+ }
664
+ if (!init.numberOfChannels || init.numberOfChannels <= 0) {
665
+ throw new TypeError("numberOfChannels must be positive");
666
+ }
667
+ if (init.timestamp === void 0) {
668
+ throw new TypeError("timestamp is required");
669
+ }
670
+ if (!init.data) {
671
+ throw new TypeError("data is required");
672
+ }
673
+ let buffer;
674
+ if (init.data instanceof ArrayBuffer) {
675
+ buffer = new Uint8Array(init.data);
676
+ } else {
677
+ buffer = new Uint8Array(init.data.buffer, init.data.byteOffset, init.data.byteLength);
678
+ }
679
+ this._buffer = new Uint8Array(buffer);
680
+ if (native_1.native) {
681
+ try {
682
+ this._native = native_1.native.createAudioData(Buffer.from(buffer), init.format, init.sampleRate, init.numberOfFrames, init.numberOfChannels, init.timestamp);
683
+ } catch {
684
+ this._native = null;
685
+ }
686
+ }
687
+ this._format = init.format;
688
+ this._sampleRate = init.sampleRate;
689
+ this._numberOfFrames = init.numberOfFrames;
690
+ this._numberOfChannels = init.numberOfChannels;
691
+ this._timestamp = init.timestamp;
692
+ this._duration = Math.floor(init.numberOfFrames / init.sampleRate * 1e6);
693
+ }
694
+ /**
695
+ * Calculate the size in bytes needed to hold the audio data for a plane
696
+ */
697
+ allocationSize(options) {
698
+ this._assertNotClosed();
699
+ const frameOffset = options.frameOffset ?? 0;
700
+ const frameCount = options.frameCount ?? this.numberOfFrames - frameOffset;
701
+ const format = options.format ?? this.format;
702
+ if (!format) {
703
+ throw new types_1.DOMException("No format available", "InvalidStateError");
704
+ }
705
+ const bytesPerSample = getBytesPerSample(format);
706
+ if (isPlanar(format)) {
707
+ return frameCount * bytesPerSample;
708
+ } else {
709
+ return frameCount * this.numberOfChannels * bytesPerSample;
710
+ }
711
+ }
712
+ /**
713
+ * Copy audio data to a destination buffer
714
+ */
715
+ copyTo(destination, options) {
716
+ this._assertNotClosed();
717
+ if (options.planeIndex < 0) {
718
+ throw new RangeError("planeIndex must be non-negative");
719
+ }
720
+ const format = options.format ?? this.format;
721
+ if (!format) {
722
+ throw new types_1.DOMException("No format available", "InvalidStateError");
723
+ }
724
+ if (isPlanar(format)) {
725
+ if (options.planeIndex >= this.numberOfChannels) {
726
+ throw new RangeError(`planeIndex ${options.planeIndex} out of range for ${this.numberOfChannels} channels`);
727
+ }
728
+ } else {
729
+ if (options.planeIndex !== 0) {
730
+ throw new RangeError("planeIndex must be 0 for interleaved formats");
731
+ }
732
+ }
733
+ let dest;
734
+ if (destination instanceof ArrayBuffer) {
735
+ dest = new Uint8Array(destination);
736
+ } else {
737
+ dest = new Uint8Array(destination.buffer, destination.byteOffset, destination.byteLength);
738
+ }
739
+ if (this._native) {
740
+ this._native.copyTo(Buffer.from(dest.buffer, dest.byteOffset, dest.byteLength), options);
741
+ } else if (this._buffer) {
742
+ const frameOffset = options.frameOffset ?? 0;
743
+ const frameCount = options.frameCount ?? this.numberOfFrames - frameOffset;
744
+ const bytesPerSample = getBytesPerSample(format);
745
+ if (isPlanar(format)) {
746
+ const planeSize = this.numberOfFrames * bytesPerSample;
747
+ const srcOffset = options.planeIndex * planeSize + frameOffset * bytesPerSample;
748
+ const copySize = frameCount * bytesPerSample;
749
+ dest.set(this._buffer.subarray(srcOffset, srcOffset + copySize));
750
+ } else {
751
+ const srcOffset = frameOffset * this.numberOfChannels * bytesPerSample;
752
+ const copySize = frameCount * this.numberOfChannels * bytesPerSample;
753
+ dest.set(this._buffer.subarray(srcOffset, srcOffset + copySize));
754
+ }
755
+ }
756
+ }
757
+ /**
758
+ * Create a clone of this audio data
759
+ */
760
+ clone() {
761
+ this._assertNotClosed();
762
+ if (!this._buffer || !this.format) {
763
+ throw new types_1.DOMException("Cannot clone AudioData without data", "InvalidStateError");
764
+ }
765
+ return new _AudioData({
766
+ format: this.format,
767
+ sampleRate: this.sampleRate,
768
+ numberOfFrames: this.numberOfFrames,
769
+ numberOfChannels: this.numberOfChannels,
770
+ timestamp: this.timestamp,
771
+ data: new Uint8Array(this._buffer)
772
+ });
773
+ }
774
+ /**
775
+ * Close the audio data and release resources
776
+ */
777
+ close() {
778
+ if (!this._closed) {
779
+ if (this._native) {
780
+ this._native.close();
781
+ this._native = null;
782
+ }
783
+ this._buffer = null;
784
+ this._closed = true;
785
+ }
786
+ }
787
+ _assertNotClosed() {
788
+ if (this._closed) {
789
+ throw new types_1.DOMException("AudioData is closed", "InvalidStateError");
790
+ }
791
+ }
792
+ };
793
+ exports.AudioData = AudioData;
794
+ }
795
+ });
796
+
797
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/EncodedVideoChunk.js
798
+ var require_EncodedVideoChunk = __commonJS({
799
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/EncodedVideoChunk.js"(exports) {
800
+ "use strict";
801
+ Object.defineProperty(exports, "__esModule", { value: true });
802
+ exports.EncodedVideoChunk = void 0;
803
+ var EncodedVideoChunk2 = class {
804
+ constructor(init) {
805
+ if (!init.type) {
806
+ throw new TypeError("type is required");
807
+ }
808
+ if (init.type !== "key" && init.type !== "delta") {
809
+ throw new TypeError('type must be "key" or "delta"');
810
+ }
811
+ if (init.timestamp === void 0) {
812
+ throw new TypeError("timestamp is required");
813
+ }
814
+ if (!init.data) {
815
+ throw new TypeError("data is required");
816
+ }
817
+ this.type = init.type;
818
+ this.timestamp = init.timestamp;
819
+ this.duration = init.duration ?? null;
820
+ let source;
821
+ if (init.data instanceof ArrayBuffer) {
822
+ source = new Uint8Array(init.data);
823
+ } else {
824
+ source = new Uint8Array(init.data.buffer, init.data.byteOffset, init.data.byteLength);
825
+ }
826
+ this._data = new Uint8Array(source);
827
+ this.byteLength = this._data.byteLength;
828
+ }
829
+ /**
830
+ * Copy the encoded data to a destination buffer
831
+ */
832
+ copyTo(destination) {
833
+ let dest;
834
+ if (destination instanceof ArrayBuffer) {
835
+ dest = new Uint8Array(destination);
836
+ } else {
837
+ dest = new Uint8Array(destination.buffer, destination.byteOffset, destination.byteLength);
838
+ }
839
+ if (dest.byteLength < this._data.byteLength) {
840
+ throw new TypeError("Destination buffer is too small");
841
+ }
842
+ dest.set(this._data);
843
+ }
844
+ };
845
+ exports.EncodedVideoChunk = EncodedVideoChunk2;
846
+ }
847
+ });
848
+
849
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/EncodedAudioChunk.js
850
+ var require_EncodedAudioChunk = __commonJS({
851
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/EncodedAudioChunk.js"(exports) {
852
+ "use strict";
853
+ Object.defineProperty(exports, "__esModule", { value: true });
854
+ exports.EncodedAudioChunk = void 0;
855
+ var EncodedAudioChunk = class {
856
+ constructor(init) {
857
+ if (!init.type) {
858
+ throw new TypeError("type is required");
859
+ }
860
+ if (init.type !== "key" && init.type !== "delta") {
861
+ throw new TypeError('type must be "key" or "delta"');
862
+ }
863
+ if (init.timestamp === void 0) {
864
+ throw new TypeError("timestamp is required");
865
+ }
866
+ if (!init.data) {
867
+ throw new TypeError("data is required");
868
+ }
869
+ this.type = init.type;
870
+ this.timestamp = init.timestamp;
871
+ this.duration = init.duration ?? null;
872
+ let source;
873
+ if (init.data instanceof ArrayBuffer) {
874
+ source = new Uint8Array(init.data);
875
+ } else {
876
+ source = new Uint8Array(init.data.buffer, init.data.byteOffset, init.data.byteLength);
877
+ }
878
+ this._data = new Uint8Array(source);
879
+ this.byteLength = this._data.byteLength;
880
+ }
881
+ /**
882
+ * Copy the encoded data to a destination buffer
883
+ */
884
+ copyTo(destination) {
885
+ let dest;
886
+ if (destination instanceof ArrayBuffer) {
887
+ dest = new Uint8Array(destination);
888
+ } else {
889
+ dest = new Uint8Array(destination.buffer, destination.byteOffset, destination.byteLength);
890
+ }
891
+ if (dest.byteLength < this._data.byteLength) {
892
+ throw new TypeError("Destination buffer is too small");
893
+ }
894
+ dest.set(this._data);
895
+ }
896
+ };
897
+ exports.EncodedAudioChunk = EncodedAudioChunk;
898
+ }
899
+ });
900
+
901
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/ImageDecoder.js
902
+ var require_ImageDecoder = __commonJS({
903
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/ImageDecoder.js"(exports) {
904
+ "use strict";
905
+ Object.defineProperty(exports, "__esModule", { value: true });
906
+ exports.ImageDecoder = void 0;
907
+ var VideoFrame_1 = require_VideoFrame();
908
+ var types_1 = require_types();
909
+ var native_1 = require_native();
910
+ function isReadableStream(value) {
911
+ return typeof value === "object" && value !== null && typeof value.getReader === "function";
912
+ }
913
+ var ImageDecoder = class {
914
+ /**
915
+ * Check if a MIME type is supported for decoding
916
+ */
917
+ static isTypeSupported(type) {
918
+ if (!native_1.native || !native_1.native.ImageDecoderNative) {
919
+ return Promise.resolve(false);
920
+ }
921
+ return Promise.resolve(native_1.native.ImageDecoderNative.isTypeSupported(type));
922
+ }
923
+ constructor(init) {
924
+ this._complete = false;
925
+ this._closed = false;
926
+ if (!init.data) {
927
+ throw new TypeError("data is required");
928
+ }
929
+ if (!init.type) {
930
+ throw new TypeError("type is required");
931
+ }
932
+ if (!native_1.native || !native_1.native.ImageDecoderNative) {
933
+ throw new types_1.DOMException("Native addon not available", "NotSupportedError");
934
+ }
935
+ this._type = init.type;
936
+ this._completedPromise = new Promise((resolve, reject) => {
937
+ this._completedResolve = resolve;
938
+ this._completedReject = reject;
939
+ });
940
+ if (isReadableStream(init.data)) {
941
+ this._handleReadableStream(init.data);
942
+ return;
943
+ }
944
+ let dataBuffer;
945
+ if (init.data instanceof ArrayBuffer) {
946
+ dataBuffer = Buffer.from(init.data);
947
+ } else if (ArrayBuffer.isView(init.data)) {
948
+ dataBuffer = Buffer.from(init.data.buffer, init.data.byteOffset, init.data.byteLength);
949
+ } else {
950
+ throw new TypeError("Invalid data type: expected BufferSource or ReadableStream");
951
+ }
952
+ this._initNative(dataBuffer);
953
+ }
954
+ /**
955
+ * Handle ReadableStream input by reading all chunks and concatenating them
956
+ */
957
+ async _handleReadableStream(stream) {
958
+ this._streamReader = stream.getReader();
959
+ const chunks = [];
960
+ try {
961
+ while (true) {
962
+ const { done, value } = await this._streamReader.read();
963
+ if (done)
964
+ break;
965
+ let chunk;
966
+ if (value instanceof ArrayBuffer) {
967
+ chunk = new Uint8Array(value);
968
+ } else if (ArrayBuffer.isView(value)) {
969
+ chunk = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
970
+ } else {
971
+ throw new TypeError("ReadableStream yielded invalid chunk type");
972
+ }
973
+ chunks.push(chunk);
974
+ }
975
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
976
+ const fullData = new Uint8Array(totalLength);
977
+ let offset = 0;
978
+ for (const chunk of chunks) {
979
+ fullData.set(chunk, offset);
980
+ offset += chunk.length;
981
+ }
982
+ this._initNative(Buffer.from(fullData));
983
+ } catch (error) {
984
+ this._completedReject(error instanceof Error ? error : new Error(String(error)));
985
+ }
986
+ }
987
+ /**
988
+ * Initialize the native decoder with buffer data
989
+ */
990
+ _initNative(dataBuffer) {
991
+ try {
992
+ this._native = new native_1.native.ImageDecoderNative({
993
+ data: dataBuffer,
994
+ type: this._type
995
+ });
996
+ this._complete = this._native.complete;
997
+ if (this._complete) {
998
+ this._completedResolve();
999
+ }
1000
+ } catch (e) {
1001
+ const error = new types_1.DOMException(e.message || "Failed to create ImageDecoder", "NotSupportedError");
1002
+ this._completedReject(error);
1003
+ throw error;
1004
+ }
1005
+ }
1006
+ /**
1007
+ * Whether all image data has been received
1008
+ */
1009
+ get complete() {
1010
+ return this._complete;
1011
+ }
1012
+ /**
1013
+ * Promise that resolves when complete becomes true
1014
+ */
1015
+ get completed() {
1016
+ return this._completedPromise;
1017
+ }
1018
+ /**
1019
+ * The MIME type of the image
1020
+ */
1021
+ get type() {
1022
+ return this._type;
1023
+ }
1024
+ /**
1025
+ * Decode an image frame
1026
+ */
1027
+ async decode(options) {
1028
+ if (this._closed) {
1029
+ throw new types_1.DOMException("ImageDecoder is closed", "InvalidStateError");
1030
+ }
1031
+ if (!this._complete) {
1032
+ throw new types_1.DOMException("Image data is not complete", "InvalidStateError");
1033
+ }
1034
+ try {
1035
+ const result = this._native.decode(options?.frameIndex ?? 0);
1036
+ const videoFrame = new VideoFrame_1.VideoFrame(result.image);
1037
+ return {
1038
+ image: videoFrame,
1039
+ complete: result.complete
1040
+ };
1041
+ } catch (e) {
1042
+ throw new types_1.DOMException(e.message || "Failed to decode image", "EncodingError");
1043
+ }
1044
+ }
1045
+ /**
1046
+ * Reset the decoder state
1047
+ */
1048
+ reset() {
1049
+ if (!this._closed) {
1050
+ this._native.reset();
1051
+ }
1052
+ }
1053
+ /**
1054
+ * Close the decoder and release resources
1055
+ */
1056
+ close() {
1057
+ if (!this._closed) {
1058
+ this._closed = true;
1059
+ this._native.close();
1060
+ }
1061
+ }
1062
+ };
1063
+ exports.ImageDecoder = ImageDecoder;
1064
+ }
1065
+ });
1066
+
1067
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/codec-registry.js
1068
+ var require_codec_registry = __commonJS({
1069
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/codec-registry.js"(exports) {
1070
+ "use strict";
1071
+ Object.defineProperty(exports, "__esModule", { value: true });
1072
+ exports.AUDIO_CODECS = exports.VIDEO_CODECS = void 0;
1073
+ exports.parseAvcCodecString = parseAvcCodecString;
1074
+ exports.parseAacCodecString = parseAacCodecString;
1075
+ exports.parseVp9CodecString = parseVp9CodecString;
1076
+ exports.isVideoCodecSupported = isVideoCodecSupported;
1077
+ exports.isAudioCodecSupported = isAudioCodecSupported;
1078
+ exports.getFFmpegVideoCodec = getFFmpegVideoCodec;
1079
+ exports.getFFmpegVideoDecoder = getFFmpegVideoDecoder;
1080
+ exports.getFFmpegAudioCodec = getFFmpegAudioCodec;
1081
+ exports.getFFmpegAudioDecoder = getFFmpegAudioDecoder;
1082
+ function parseAvcCodecString(codec) {
1083
+ const match = codec.match(/^avc1\.([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);
1084
+ if (!match)
1085
+ return null;
1086
+ const profile = parseInt(match[1], 16);
1087
+ const level = parseInt(match[3], 16);
1088
+ return { profile, level };
1089
+ }
1090
+ function parseAacCodecString(codec) {
1091
+ const match = codec.match(/^mp4a\.40\.(\d+)$/);
1092
+ if (!match)
1093
+ return null;
1094
+ return { objectType: parseInt(match[1], 10) };
1095
+ }
1096
+ function parseVp9CodecString(codec) {
1097
+ if (codec === "vp9" || codec === "vp09") {
1098
+ return { profile: 0, level: 10, bitDepth: 8 };
1099
+ }
1100
+ const match = codec.match(/^vp09\.(\d{2})\.(\d{2})\.(\d{2})/);
1101
+ if (!match)
1102
+ return null;
1103
+ return {
1104
+ profile: parseInt(match[1], 10),
1105
+ level: parseInt(match[2], 10),
1106
+ bitDepth: parseInt(match[3], 10)
1107
+ };
1108
+ }
1109
+ exports.VIDEO_CODECS = {
1110
+ // H.264/AVC
1111
+ "avc1": {
1112
+ ffmpegCodec: "libx264",
1113
+ type: "video",
1114
+ profiles: {
1115
+ "42": 66,
1116
+ // Baseline
1117
+ "4d": 77,
1118
+ // Main
1119
+ "58": 88,
1120
+ // Extended
1121
+ "64": 100
1122
+ // High
1123
+ }
1124
+ },
1125
+ // VP8
1126
+ "vp8": {
1127
+ ffmpegCodec: "libvpx",
1128
+ type: "video"
1129
+ },
1130
+ // VP9
1131
+ "vp09": {
1132
+ ffmpegCodec: "libvpx-vp9",
1133
+ type: "video"
1134
+ },
1135
+ "vp9": {
1136
+ ffmpegCodec: "libvpx-vp9",
1137
+ type: "video"
1138
+ },
1139
+ // H.265/HEVC
1140
+ "hvc1": {
1141
+ ffmpegCodec: "libx265",
1142
+ type: "video"
1143
+ },
1144
+ "hev1": {
1145
+ ffmpegCodec: "libx265",
1146
+ type: "video"
1147
+ },
1148
+ // AV1
1149
+ "av01": {
1150
+ ffmpegCodec: "libaom-av1",
1151
+ type: "video"
1152
+ }
1153
+ };
1154
+ exports.AUDIO_CODECS = {
1155
+ // AAC
1156
+ "mp4a.40": {
1157
+ ffmpegCodec: "aac",
1158
+ type: "audio"
1159
+ },
1160
+ // Opus
1161
+ "opus": {
1162
+ ffmpegCodec: "libopus",
1163
+ type: "audio"
1164
+ },
1165
+ // MP3
1166
+ "mp3": {
1167
+ ffmpegCodec: "libmp3lame",
1168
+ type: "audio"
1169
+ },
1170
+ // FLAC
1171
+ "flac": {
1172
+ ffmpegCodec: "flac",
1173
+ type: "audio"
1174
+ },
1175
+ // Vorbis
1176
+ "vorbis": {
1177
+ ffmpegCodec: "libvorbis",
1178
+ type: "audio"
1179
+ },
1180
+ // PCM
1181
+ "pcm": {
1182
+ ffmpegCodec: "pcm_f32le",
1183
+ type: "audio"
1184
+ }
1185
+ };
1186
+ function isVideoCodecSupported(codec) {
1187
+ if (codec.startsWith("avc1.")) {
1188
+ return parseAvcCodecString(codec) !== null;
1189
+ }
1190
+ if (codec.startsWith("vp09.")) {
1191
+ return parseVp9CodecString(codec) !== null;
1192
+ }
1193
+ if (codec.startsWith("hvc1.") || codec.startsWith("hev1.")) {
1194
+ return true;
1195
+ }
1196
+ if (codec.startsWith("av01.")) {
1197
+ return true;
1198
+ }
1199
+ return codec in exports.VIDEO_CODECS;
1200
+ }
1201
+ function isAudioCodecSupported(codec) {
1202
+ if (codec.startsWith("mp4a.40.")) {
1203
+ return parseAacCodecString(codec) !== null;
1204
+ }
1205
+ return codec in exports.AUDIO_CODECS;
1206
+ }
1207
+ function getFFmpegVideoCodec(codec) {
1208
+ if (codec.startsWith("avc1.")) {
1209
+ return "libx264";
1210
+ }
1211
+ if (codec.startsWith("vp09.") || codec === "vp9") {
1212
+ return "libvpx-vp9";
1213
+ }
1214
+ if (codec === "vp8") {
1215
+ return "libvpx";
1216
+ }
1217
+ if (codec.startsWith("hvc1.") || codec.startsWith("hev1.")) {
1218
+ return "libx265";
1219
+ }
1220
+ if (codec.startsWith("av01.")) {
1221
+ return "libaom-av1";
1222
+ }
1223
+ const info = exports.VIDEO_CODECS[codec];
1224
+ return info?.ffmpegCodec ?? null;
1225
+ }
1226
+ function getFFmpegVideoDecoder(codec) {
1227
+ if (codec.startsWith("avc1.")) {
1228
+ return "h264";
1229
+ }
1230
+ if (codec.startsWith("vp09.") || codec === "vp9") {
1231
+ return "vp9";
1232
+ }
1233
+ if (codec === "vp8") {
1234
+ return "vp8";
1235
+ }
1236
+ if (codec.startsWith("hvc1.") || codec.startsWith("hev1.")) {
1237
+ return "hevc";
1238
+ }
1239
+ if (codec.startsWith("av01.")) {
1240
+ return "av1";
1241
+ }
1242
+ const encoderToDecoder = {
1243
+ "libx264": "h264",
1244
+ "libvpx": "vp8",
1245
+ "libvpx-vp9": "vp9",
1246
+ "libx265": "hevc",
1247
+ "libaom-av1": "av1"
1248
+ };
1249
+ const info = exports.VIDEO_CODECS[codec];
1250
+ if (info) {
1251
+ return encoderToDecoder[info.ffmpegCodec] ?? info.ffmpegCodec;
1252
+ }
1253
+ return null;
1254
+ }
1255
+ function getFFmpegAudioCodec(codec) {
1256
+ if (codec.startsWith("mp4a.40.")) {
1257
+ return "aac";
1258
+ }
1259
+ const info = exports.AUDIO_CODECS[codec];
1260
+ return info?.ffmpegCodec ?? null;
1261
+ }
1262
+ function getFFmpegAudioDecoder(codec) {
1263
+ if (codec.startsWith("mp4a.40.")) {
1264
+ return "aac";
1265
+ }
1266
+ const encoderToDecoder = {
1267
+ "libopus": "opus",
1268
+ "libmp3lame": "mp3",
1269
+ "libvorbis": "vorbis"
1270
+ };
1271
+ const info = exports.AUDIO_CODECS[codec];
1272
+ if (info) {
1273
+ return encoderToDecoder[info.ffmpegCodec] ?? info.ffmpegCodec;
1274
+ }
1275
+ return null;
1276
+ }
1277
+ }
1278
+ });
1279
+
1280
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoEncoder.js
1281
+ var require_VideoEncoder = __commonJS({
1282
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoEncoder.js"(exports) {
1283
+ "use strict";
1284
+ Object.defineProperty(exports, "__esModule", { value: true });
1285
+ exports.VideoEncoder = void 0;
1286
+ var EncodedVideoChunk_1 = require_EncodedVideoChunk();
1287
+ var codec_registry_1 = require_codec_registry();
1288
+ var types_1 = require_types();
1289
+ var native_1 = require_native();
1290
+ var VideoEncoder = class {
1291
+ /**
1292
+ * Check if a VideoEncoder configuration is supported
1293
+ *
1294
+ * Tests whether the specified codec and parameters can be encoded on this platform.
1295
+ * This method probes the native FFmpeg installation for codec availability.
1296
+ *
1297
+ * @param config - Configuration to test
1298
+ * @returns Promise resolving to support status and normalized config
1299
+ *
1300
+ * @example
1301
+ * ```ts
1302
+ * const result = await VideoEncoder.isConfigSupported({
1303
+ * codec: 'avc1.42E01E',
1304
+ * width: 1920,
1305
+ * height: 1080
1306
+ * });
1307
+ *
1308
+ * if (result.supported) {
1309
+ * console.log('H.264 encoding is supported');
1310
+ * } else {
1311
+ * console.log('H.264 encoding is NOT supported');
1312
+ * }
1313
+ * ```
1314
+ *
1315
+ * @example Check hardware encoder
1316
+ * ```ts
1317
+ * const hwSupport = await VideoEncoder.isConfigSupported({
1318
+ * codec: 'h264_videotoolbox',
1319
+ * width: 3840,
1320
+ * height: 2160,
1321
+ * hardwareAcceleration: 'prefer-hardware'
1322
+ * });
1323
+ *
1324
+ * if (!hwSupport.supported) {
1325
+ * // Fallback to software encoder
1326
+ * encoder.configure({ codec: 'avc1.42E01E', ... });
1327
+ * }
1328
+ * ```
1329
+ */
1330
+ static async isConfigSupported(config) {
1331
+ if (!config.codec || config.width <= 0 || config.height <= 0) {
1332
+ return { supported: false, config };
1333
+ }
1334
+ if (!(0, codec_registry_1.isVideoCodecSupported)(config.codec)) {
1335
+ return { supported: false, config };
1336
+ }
1337
+ if (native_1.native?.CapabilityProbe?.probeVideoEncoder) {
1338
+ try {
1339
+ const ffmpegCodec = (0, codec_registry_1.getFFmpegVideoCodec)(config.codec);
1340
+ const result = native_1.native.CapabilityProbe.probeVideoEncoder({
1341
+ codec: ffmpegCodec,
1342
+ width: config.width,
1343
+ height: config.height,
1344
+ hardwareAcceleration: config.hardwareAcceleration || "no-preference"
1345
+ });
1346
+ return {
1347
+ supported: result.supported,
1348
+ config
1349
+ };
1350
+ } catch {
1351
+ }
1352
+ }
1353
+ return { supported: true, config };
1354
+ }
1355
+ /**
1356
+ * Create a new VideoEncoder
1357
+ *
1358
+ * @param init - Initialization callbacks for output and errors
1359
+ * @throws TypeError if callbacks are not functions
1360
+ *
1361
+ * @example
1362
+ * ```ts
1363
+ * const encoder = new VideoEncoder({
1364
+ * output: (chunk, metadata) => {
1365
+ * // Handle encoded chunk
1366
+ * if (metadata?.decoderConfig) {
1367
+ * console.log('Received decoder config:', metadata.decoderConfig);
1368
+ * }
1369
+ * },
1370
+ * error: (err) => {
1371
+ * console.error('Encoding failed:', err.message);
1372
+ * }
1373
+ * });
1374
+ * ```
1375
+ */
1376
+ constructor(init) {
1377
+ this._state = "unconfigured";
1378
+ this._encodeQueueSize = 0;
1379
+ this._pendingCallbacks = 0;
1380
+ this._config = null;
1381
+ this._sentDecoderConfig = false;
1382
+ this._listeners = /* @__PURE__ */ new Map();
1383
+ this._useAsync = true;
1384
+ this._nativeCreated = false;
1385
+ this._ondequeue = null;
1386
+ if (!init.output || typeof init.output !== "function") {
1387
+ throw new TypeError("output callback is required");
1388
+ }
1389
+ if (!init.error || typeof init.error !== "function") {
1390
+ throw new TypeError("error callback is required");
1391
+ }
1392
+ this._outputCallback = init.output;
1393
+ this._errorCallback = init.error;
1394
+ }
1395
+ /**
1396
+ * Current encoder state
1397
+ * - `unconfigured`: Not configured yet, or reset() was called
1398
+ * - `configured`: Ready to encode frames
1399
+ * - `closed`: Encoder has been closed and cannot be used
1400
+ */
1401
+ get state() {
1402
+ return this._state;
1403
+ }
1404
+ /**
1405
+ * Number of pending encode operations
1406
+ * Useful for backpressure management in async mode
1407
+ *
1408
+ * @example Backpressure handling
1409
+ * ```ts
1410
+ * for (const frame of frames) {
1411
+ * encoder.encode(frame);
1412
+ *
1413
+ * // Wait if queue gets too large
1414
+ * if (encoder.encodeQueueSize > 10) {
1415
+ * await new Promise(resolve => {
1416
+ * encoder.addEventListener('dequeue', resolve, { once: true });
1417
+ * });
1418
+ * }
1419
+ * }
1420
+ * ```
1421
+ */
1422
+ get encodeQueueSize() {
1423
+ return this._encodeQueueSize;
1424
+ }
1425
+ /**
1426
+ * Event handler for dequeue events
1427
+ *
1428
+ * Called when an item is removed from the encode queue. Useful for backpressure
1429
+ * management. This is an alternative to using addEventListener('dequeue', ...).
1430
+ *
1431
+ * @example
1432
+ * ```ts
1433
+ * encoder.ondequeue = () => {
1434
+ * console.log('Queue size:', encoder.encodeQueueSize);
1435
+ * };
1436
+ * ```
1437
+ */
1438
+ get ondequeue() {
1439
+ return this._ondequeue;
1440
+ }
1441
+ set ondequeue(handler) {
1442
+ this._ondequeue = handler;
1443
+ }
1444
+ /**
1445
+ * Add an event listener
1446
+ * Currently supports 'dequeue' events fired when encode queue decreases
1447
+ *
1448
+ * @param type - Event type ('dequeue')
1449
+ * @param listener - Callback to invoke
1450
+ * @param options - Event listener options
1451
+ *
1452
+ * @example Wait for queue to drain
1453
+ * ```ts
1454
+ * encoder.addEventListener('dequeue', () => {
1455
+ * console.log('Queue size:', encoder.encodeQueueSize);
1456
+ * });
1457
+ * ```
1458
+ */
1459
+ addEventListener(type, listener, options) {
1460
+ if (typeof listener !== "function")
1461
+ return;
1462
+ const once = !!(options && options.once);
1463
+ const wrapper = once ? () => {
1464
+ this.removeEventListener(type, wrapper);
1465
+ listener();
1466
+ } : listener;
1467
+ let set = this._listeners.get(type);
1468
+ if (!set) {
1469
+ set = /* @__PURE__ */ new Set();
1470
+ this._listeners.set(type, set);
1471
+ }
1472
+ set.add(wrapper);
1473
+ }
1474
+ /**
1475
+ * Remove an event listener
1476
+ *
1477
+ * @param type - Event type ('dequeue')
1478
+ * @param listener - Callback to remove
1479
+ */
1480
+ removeEventListener(type, listener) {
1481
+ const set = this._listeners.get(type);
1482
+ if (!set)
1483
+ return;
1484
+ if (set.has(listener)) {
1485
+ set.delete(listener);
1486
+ }
1487
+ if (set.size === 0) {
1488
+ this._listeners.delete(type);
1489
+ }
1490
+ }
1491
+ _dispatchEvent(type) {
1492
+ if (type === "dequeue" && this._ondequeue) {
1493
+ try {
1494
+ this._ondequeue(new Event("dequeue"));
1495
+ } catch {
1496
+ }
1497
+ }
1498
+ const set = this._listeners.get(type);
1499
+ if (!set)
1500
+ return;
1501
+ for (const listener of Array.from(set)) {
1502
+ try {
1503
+ listener();
1504
+ } catch {
1505
+ }
1506
+ }
1507
+ }
1508
+ /**
1509
+ * Configure the encoder with codec parameters
1510
+ *
1511
+ * Must be called before encoding frames. Can be called multiple times to
1512
+ * reconfigure (e.g., to change bitrate or resolution).
1513
+ *
1514
+ * @param config - Encoder configuration
1515
+ * @throws DOMException if encoder is closed
1516
+ * @throws DOMException if codec is not supported
1517
+ * @throws DOMException if dimensions are invalid
1518
+ *
1519
+ * @example Basic H.264
1520
+ * ```ts
1521
+ * encoder.configure({
1522
+ * codec: 'avc1.42E01E',
1523
+ * width: 1920,
1524
+ * height: 1080,
1525
+ * bitrate: 5_000_000,
1526
+ * framerate: 30
1527
+ * });
1528
+ * ```
1529
+ *
1530
+ * @example Hardware acceleration
1531
+ * ```ts
1532
+ * encoder.configure({
1533
+ * codec: 'h264_videotoolbox', // macOS
1534
+ * width: 1920,
1535
+ * height: 1080,
1536
+ * hardwareAcceleration: 'prefer-hardware'
1537
+ * });
1538
+ * ```
1539
+ *
1540
+ * @example VP9 with HDR
1541
+ * ```ts
1542
+ * encoder.configure({
1543
+ * codec: 'vp09.00.10.08',
1544
+ * width: 3840,
1545
+ * height: 2160,
1546
+ * bitrate: 20_000_000,
1547
+ * colorSpace: {
1548
+ * primaries: 'bt2020',
1549
+ * transfer: 'pq',
1550
+ * matrix: 'bt2020-ncl'
1551
+ * }
1552
+ * });
1553
+ * ```
1554
+ */
1555
+ configure(config) {
1556
+ if (this._state === "closed") {
1557
+ throw new types_1.DOMException("Encoder is closed", "InvalidStateError");
1558
+ }
1559
+ if (!(0, codec_registry_1.isVideoCodecSupported)(config.codec)) {
1560
+ throw new types_1.DOMException(`Unsupported codec: ${config.codec}`, "NotSupportedError");
1561
+ }
1562
+ if (config.width <= 0 || config.height <= 0) {
1563
+ throw new types_1.DOMException("Invalid dimensions", "NotSupportedError");
1564
+ }
1565
+ if (config.latencyMode && !["quality", "realtime"].includes(config.latencyMode)) {
1566
+ throw new types_1.DOMException(`Invalid latencyMode: ${config.latencyMode}. Must be 'quality' or 'realtime'.`, "TypeError");
1567
+ }
1568
+ if (config.bitrateMode && !["constant", "variable", "quantizer"].includes(config.bitrateMode)) {
1569
+ throw new types_1.DOMException(`Invalid bitrateMode: ${config.bitrateMode}. Must be 'constant', 'variable', or 'quantizer'.`, "TypeError");
1570
+ }
1571
+ if (!native_1.native) {
1572
+ throw new types_1.DOMException("Native addon not available", "NotSupportedError");
1573
+ }
1574
+ this._useAsync = config.useWorkerThread !== false && !!native_1.native.VideoEncoderAsync;
1575
+ if (!this._nativeCreated) {
1576
+ if (this._useAsync) {
1577
+ this._native = new native_1.native.VideoEncoderAsync(this._onChunk.bind(this), this._onError.bind(this));
1578
+ } else {
1579
+ this._native = new native_1.native.VideoEncoderNative(this._onChunk.bind(this), this._onError.bind(this));
1580
+ }
1581
+ this._nativeCreated = true;
1582
+ }
1583
+ const ffmpegCodec = (0, codec_registry_1.getFFmpegVideoCodec)(config.codec);
1584
+ const codecParams = {
1585
+ codec: ffmpegCodec,
1586
+ width: config.width,
1587
+ height: config.height
1588
+ };
1589
+ if (config.codec.startsWith("avc1.")) {
1590
+ const avcInfo = (0, codec_registry_1.parseAvcCodecString)(config.codec);
1591
+ if (avcInfo) {
1592
+ codecParams.profile = avcInfo.profile;
1593
+ codecParams.level = avcInfo.level;
1594
+ }
1595
+ codecParams.avcFormat = config.avc?.format ?? "annexb";
1596
+ }
1597
+ if (config.bitrate)
1598
+ codecParams.bitrate = config.bitrate;
1599
+ if (config.framerate)
1600
+ codecParams.framerate = config.framerate;
1601
+ if (config.bitrateMode)
1602
+ codecParams.bitrateMode = config.bitrateMode;
1603
+ if (config.latencyMode)
1604
+ codecParams.latencyMode = config.latencyMode;
1605
+ if (config.colorSpace)
1606
+ codecParams.colorSpace = config.colorSpace;
1607
+ if (config.hardwareAcceleration)
1608
+ codecParams.hardwareAcceleration = config.hardwareAcceleration;
1609
+ if (config.alpha)
1610
+ codecParams.alpha = config.alpha;
1611
+ if (config.scalabilityMode)
1612
+ codecParams.scalabilityMode = config.scalabilityMode;
1613
+ this._native.configure(codecParams);
1614
+ this._config = config;
1615
+ this._state = "configured";
1616
+ this._sentDecoderConfig = false;
1617
+ }
1618
+ /**
1619
+ * Encode a video frame
1620
+ *
1621
+ * Queues a frame for encoding. In async mode (default), encoding happens in
1622
+ * a worker thread and the output callback is invoked when complete.
1623
+ *
1624
+ * **IMPORTANT**: Always call `frame.close()` after encoding to prevent memory leaks.
1625
+ *
1626
+ * @param frame - VideoFrame to encode
1627
+ * @param options - Encoding options (keyFrame)
1628
+ * @throws DOMException if encoder is not configured
1629
+ * @throws DOMException if frame is invalid
1630
+ *
1631
+ * @example Basic encoding
1632
+ * ```ts
1633
+ * const frame = new VideoFrame(buffer, {
1634
+ * format: 'RGBA',
1635
+ * codedWidth: 1920,
1636
+ * codedHeight: 1080,
1637
+ * timestamp: 0
1638
+ * });
1639
+ *
1640
+ * encoder.encode(frame);
1641
+ * frame.close(); // MUST close to prevent memory leak
1642
+ * ```
1643
+ *
1644
+ * @example Force keyframe
1645
+ * ```ts
1646
+ * // Force first frame to be keyframe
1647
+ * encoder.encode(frame, { keyFrame: true });
1648
+ * frame.close();
1649
+ *
1650
+ * // Keyframe every 2 seconds at 30fps
1651
+ * for (let i = 0; i < frames.length; i++) {
1652
+ * encoder.encode(frames[i], { keyFrame: i % 60 === 0 });
1653
+ * frames[i].close();
1654
+ * }
1655
+ * ```
1656
+ */
1657
+ encode(frame, options) {
1658
+ if (this._state !== "configured") {
1659
+ throw new types_1.DOMException("Encoder is not configured", "InvalidStateError");
1660
+ }
1661
+ const nativeFrame = frame._getNative();
1662
+ if (!nativeFrame) {
1663
+ throw new types_1.DOMException("VideoFrame has no native handle", "InvalidStateError");
1664
+ }
1665
+ const keyFrame = options?.keyFrame ?? false;
1666
+ this._encodeQueueSize++;
1667
+ this._pendingCallbacks++;
1668
+ this._native.encode(nativeFrame, frame.timestamp, keyFrame);
1669
+ setImmediate(() => {
1670
+ this._pendingCallbacks--;
1671
+ this._encodeQueueSize = Math.max(0, this._encodeQueueSize - 1);
1672
+ this._dispatchEvent("dequeue");
1673
+ });
1674
+ }
1675
+ /**
1676
+ * Wait for all pending encodes to complete
1677
+ *
1678
+ * Flushes the internal encode queue and returns a promise that resolves when
1679
+ * all frames have been encoded. Call this before closing the encoder to ensure
1680
+ * no frames are lost.
1681
+ *
1682
+ * @returns Promise that resolves when flush is complete
1683
+ * @throws DOMException if encoder is not configured
1684
+ * @throws DOMException if encoding fails
1685
+ *
1686
+ * @example
1687
+ * ```ts
1688
+ * // Encode all frames
1689
+ * for (const frame of frames) {
1690
+ * encoder.encode(frame);
1691
+ * frame.close();
1692
+ * }
1693
+ *
1694
+ * // Wait for encoding to finish
1695
+ * await encoder.flush();
1696
+ *
1697
+ * console.log('All frames encoded!');
1698
+ * encoder.close();
1699
+ * ```
1700
+ */
1701
+ async flush() {
1702
+ if (this._state !== "configured") {
1703
+ throw new types_1.DOMException("Encoder is not configured", "InvalidStateError");
1704
+ }
1705
+ return new Promise((resolve, reject) => {
1706
+ this._native.flush(async (err) => {
1707
+ if (err) {
1708
+ reject(new types_1.DOMException(err.message, "EncodingError"));
1709
+ } else {
1710
+ while (this._pendingCallbacks > 0) {
1711
+ await new Promise((r) => setImmediate(r));
1712
+ }
1713
+ resolve();
1714
+ }
1715
+ });
1716
+ });
1717
+ }
1718
+ /**
1719
+ * Reset the encoder to unconfigured state
1720
+ *
1721
+ * Aborts all pending encode operations and resets to unconfigured state.
1722
+ * You must call `configure()` again before encoding more frames.
1723
+ *
1724
+ * @throws DOMException if encoder is closed
1725
+ *
1726
+ * @example
1727
+ * ```ts
1728
+ * encoder.configure({ codec: 'avc1.42E01E', width: 1920, height: 1080 });
1729
+ * encoder.encode(frame1);
1730
+ *
1731
+ * // Abort and reconfigure with different settings
1732
+ * encoder.reset();
1733
+ * encoder.configure({ codec: 'vp09.00.10.08', width: 1280, height: 720 });
1734
+ * encoder.encode(frame2);
1735
+ * ```
1736
+ */
1737
+ reset() {
1738
+ if (this._state === "closed") {
1739
+ throw new types_1.DOMException("Encoder is closed", "InvalidStateError");
1740
+ }
1741
+ if (this._native) {
1742
+ this._native.reset();
1743
+ }
1744
+ this._encodeQueueSize = 0;
1745
+ this._state = "unconfigured";
1746
+ this._sentDecoderConfig = false;
1747
+ this._config = null;
1748
+ }
1749
+ /**
1750
+ * Close the encoder and release resources
1751
+ *
1752
+ * Closes the encoder and frees all native resources. The encoder cannot be
1753
+ * used after calling close(). Any pending encode operations are aborted.
1754
+ *
1755
+ * @example
1756
+ * ```ts
1757
+ * // Encode frames
1758
+ * for (const frame of frames) {
1759
+ * encoder.encode(frame);
1760
+ * frame.close();
1761
+ * }
1762
+ *
1763
+ * await encoder.flush();
1764
+ * encoder.close(); // Release resources
1765
+ *
1766
+ * // encoder.encode() will now throw
1767
+ * ```
1768
+ */
1769
+ close() {
1770
+ if (this._state === "closed")
1771
+ return;
1772
+ if (this._native) {
1773
+ this._native.close();
1774
+ }
1775
+ this._state = "closed";
1776
+ this._encodeQueueSize = 0;
1777
+ this._config = null;
1778
+ }
1779
+ _onChunk(data, isKeyframe, timestamp, duration, extradata) {
1780
+ const dataCopy = new Uint8Array(data);
1781
+ const extradataCopy = extradata ? new Uint8Array(extradata) : void 0;
1782
+ const chunk = new EncodedVideoChunk_1.EncodedVideoChunk({
1783
+ type: isKeyframe ? "key" : "delta",
1784
+ timestamp,
1785
+ duration: duration > 0 ? duration : void 0,
1786
+ data: dataCopy
1787
+ });
1788
+ let metadata;
1789
+ if (isKeyframe && !this._sentDecoderConfig && this._config) {
1790
+ const colorSpace = this._config.colorSpace ?? {
1791
+ primaries: "bt709",
1792
+ transfer: "iec61966-2-1",
1793
+ matrix: "rgb",
1794
+ fullRange: true
1795
+ };
1796
+ metadata = {
1797
+ decoderConfig: {
1798
+ codec: this._config.codec,
1799
+ codedWidth: this._config.width,
1800
+ codedHeight: this._config.height,
1801
+ description: extradataCopy ? extradataCopy.buffer : void 0,
1802
+ colorSpace
1803
+ }
1804
+ };
1805
+ this._sentDecoderConfig = true;
1806
+ }
1807
+ try {
1808
+ this._outputCallback(chunk, metadata);
1809
+ } catch (e) {
1810
+ }
1811
+ }
1812
+ _onError(message) {
1813
+ try {
1814
+ this._errorCallback(new types_1.DOMException(message, "EncodingError"));
1815
+ } catch (e) {
1816
+ }
1817
+ }
1818
+ };
1819
+ exports.VideoEncoder = VideoEncoder;
1820
+ }
1821
+ });
1822
+
1823
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoDecoder.js
1824
+ var require_VideoDecoder = __commonJS({
1825
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/VideoDecoder.js"(exports) {
1826
+ "use strict";
1827
+ Object.defineProperty(exports, "__esModule", { value: true });
1828
+ exports.VideoDecoder = void 0;
1829
+ var VideoFrame_1 = require_VideoFrame();
1830
+ var codec_registry_1 = require_codec_registry();
1831
+ var types_1 = require_types();
1832
+ var native_1 = require_native();
1833
+ var VideoDecoder2 = class {
1834
+ static async isConfigSupported(config) {
1835
+ if (!config.codec) {
1836
+ return { supported: false, config };
1837
+ }
1838
+ if (!(0, codec_registry_1.isVideoCodecSupported)(config.codec)) {
1839
+ return { supported: false, config };
1840
+ }
1841
+ if (native_1.native?.CapabilityProbe?.probeVideoDecoder) {
1842
+ try {
1843
+ const ffmpegCodec = (0, codec_registry_1.getFFmpegVideoDecoder)(config.codec);
1844
+ const result = native_1.native.CapabilityProbe.probeVideoDecoder({
1845
+ codec: ffmpegCodec,
1846
+ width: config.codedWidth || 1920,
1847
+ height: config.codedHeight || 1080,
1848
+ hardwareAcceleration: config.hardwareAcceleration || "no-preference"
1849
+ });
1850
+ return {
1851
+ supported: result.supported,
1852
+ config
1853
+ };
1854
+ } catch {
1855
+ }
1856
+ }
1857
+ return { supported: true, config };
1858
+ }
1859
+ constructor(init) {
1860
+ this._state = "unconfigured";
1861
+ this._decodeQueueSize = 0;
1862
+ this._pendingCallbacks = 0;
1863
+ this._config = null;
1864
+ this._listeners = /* @__PURE__ */ new Map();
1865
+ this._useAsync = true;
1866
+ this._nativeCreated = false;
1867
+ this._ondequeue = null;
1868
+ if (!init.output || typeof init.output !== "function") {
1869
+ throw new TypeError("output callback is required");
1870
+ }
1871
+ if (!init.error || typeof init.error !== "function") {
1872
+ throw new TypeError("error callback is required");
1873
+ }
1874
+ this._outputCallback = init.output;
1875
+ this._errorCallback = init.error;
1876
+ }
1877
+ get state() {
1878
+ return this._state;
1879
+ }
1880
+ get decodeQueueSize() {
1881
+ return this._decodeQueueSize;
1882
+ }
1883
+ /**
1884
+ * Event handler for dequeue events
1885
+ */
1886
+ get ondequeue() {
1887
+ return this._ondequeue;
1888
+ }
1889
+ set ondequeue(handler) {
1890
+ this._ondequeue = handler;
1891
+ }
1892
+ /**
1893
+ * Minimal EventTarget-style API for 'dequeue' events.
1894
+ * Enables compatibility with MediaBunny and browser WebCodecs code.
1895
+ */
1896
+ addEventListener(type, listener, options) {
1897
+ if (typeof listener !== "function")
1898
+ return;
1899
+ const once = !!(options && options.once);
1900
+ const wrapper = once ? () => {
1901
+ this.removeEventListener(type, wrapper);
1902
+ listener();
1903
+ } : listener;
1904
+ let set = this._listeners.get(type);
1905
+ if (!set) {
1906
+ set = /* @__PURE__ */ new Set();
1907
+ this._listeners.set(type, set);
1908
+ }
1909
+ set.add(wrapper);
1910
+ }
1911
+ removeEventListener(type, listener) {
1912
+ const set = this._listeners.get(type);
1913
+ if (!set)
1914
+ return;
1915
+ if (set.has(listener)) {
1916
+ set.delete(listener);
1917
+ }
1918
+ if (set.size === 0) {
1919
+ this._listeners.delete(type);
1920
+ }
1921
+ }
1922
+ _dispatchEvent(type) {
1923
+ if (type === "dequeue" && this._ondequeue) {
1924
+ try {
1925
+ this._ondequeue(new Event("dequeue"));
1926
+ } catch {
1927
+ }
1928
+ }
1929
+ const set = this._listeners.get(type);
1930
+ if (!set)
1931
+ return;
1932
+ for (const listener of Array.from(set)) {
1933
+ try {
1934
+ listener();
1935
+ } catch {
1936
+ }
1937
+ }
1938
+ }
1939
+ configure(config) {
1940
+ if (this._state === "closed") {
1941
+ throw new types_1.DOMException("Decoder is closed", "InvalidStateError");
1942
+ }
1943
+ if (!(0, codec_registry_1.isVideoCodecSupported)(config.codec)) {
1944
+ throw new types_1.DOMException(`Unsupported codec: ${config.codec}`, "NotSupportedError");
1945
+ }
1946
+ if (!native_1.native) {
1947
+ throw new types_1.DOMException("Native addon not available", "NotSupportedError");
1948
+ }
1949
+ this._useAsync = config.useWorkerThread !== false && !!native_1.native.VideoDecoderAsync;
1950
+ if (!this._nativeCreated) {
1951
+ if (this._useAsync) {
1952
+ this._native = new native_1.native.VideoDecoderAsync(this._onFrame.bind(this), this._onError.bind(this));
1953
+ } else {
1954
+ this._native = new native_1.native.VideoDecoderNative(this._onFrame.bind(this), this._onError.bind(this));
1955
+ }
1956
+ this._nativeCreated = true;
1957
+ }
1958
+ const ffmpegCodec = (0, codec_registry_1.getFFmpegVideoDecoder)(config.codec);
1959
+ const codecParams = { codec: ffmpegCodec };
1960
+ if (config.codec.startsWith("avc1.")) {
1961
+ const avcInfo = (0, codec_registry_1.parseAvcCodecString)(config.codec);
1962
+ if (avcInfo) {
1963
+ codecParams.profile = avcInfo.profile;
1964
+ codecParams.level = avcInfo.level;
1965
+ }
1966
+ }
1967
+ if (config.codedWidth)
1968
+ codecParams.width = config.codedWidth;
1969
+ if (config.codedHeight)
1970
+ codecParams.height = config.codedHeight;
1971
+ if (config.description) {
1972
+ let desc;
1973
+ if (config.description instanceof ArrayBuffer) {
1974
+ desc = new Uint8Array(config.description);
1975
+ } else {
1976
+ desc = new Uint8Array(config.description.buffer, config.description.byteOffset, config.description.byteLength);
1977
+ }
1978
+ codecParams.extradata = Buffer.from(desc);
1979
+ }
1980
+ this._native.configure(codecParams);
1981
+ this._config = config;
1982
+ this._state = "configured";
1983
+ }
1984
+ decode(chunk) {
1985
+ if (this._state !== "configured") {
1986
+ throw new types_1.DOMException("Decoder is not configured", "InvalidStateError");
1987
+ }
1988
+ const data = new Uint8Array(chunk.byteLength);
1989
+ chunk.copyTo(data);
1990
+ this._decodeQueueSize++;
1991
+ this._pendingCallbacks++;
1992
+ this._native.decode(Buffer.from(data), chunk.type === "key", chunk.timestamp, chunk.duration ?? 0);
1993
+ setImmediate(() => {
1994
+ this._pendingCallbacks--;
1995
+ this._decodeQueueSize = Math.max(0, this._decodeQueueSize - 1);
1996
+ this._dispatchEvent("dequeue");
1997
+ });
1998
+ }
1999
+ async flush() {
2000
+ if (this._state !== "configured") {
2001
+ throw new types_1.DOMException("Decoder is not configured", "InvalidStateError");
2002
+ }
2003
+ return new Promise((resolve, reject) => {
2004
+ this._native.flush(async (err) => {
2005
+ if (err) {
2006
+ reject(new types_1.DOMException(err.message, "EncodingError"));
2007
+ } else {
2008
+ while (this._pendingCallbacks > 0) {
2009
+ await new Promise((r) => setImmediate(r));
2010
+ }
2011
+ resolve();
2012
+ }
2013
+ });
2014
+ });
2015
+ }
2016
+ reset() {
2017
+ if (this._state === "closed") {
2018
+ throw new types_1.DOMException("Decoder is closed", "InvalidStateError");
2019
+ }
2020
+ if (this._native) {
2021
+ this._native.reset();
2022
+ }
2023
+ this._decodeQueueSize = 0;
2024
+ this._state = "unconfigured";
2025
+ this._config = null;
2026
+ }
2027
+ close() {
2028
+ if (this._state === "closed")
2029
+ return;
2030
+ if (this._native) {
2031
+ this._native.close();
2032
+ }
2033
+ this._state = "closed";
2034
+ this._decodeQueueSize = 0;
2035
+ this._config = null;
2036
+ }
2037
+ _onFrame(nativeFrame, timestamp, duration) {
2038
+ const width = nativeFrame.width;
2039
+ const height = nativeFrame.height;
2040
+ const format = nativeFrame.format || "I420";
2041
+ const size = nativeFrame.allocationSize();
2042
+ const buffer = Buffer.alloc(size);
2043
+ nativeFrame.copyTo(buffer);
2044
+ try {
2045
+ const frame = new VideoFrame_1.VideoFrame(buffer, {
2046
+ format,
2047
+ codedWidth: width,
2048
+ codedHeight: height,
2049
+ timestamp,
2050
+ duration: duration > 0 ? duration : void 0
2051
+ });
2052
+ this._outputCallback(frame);
2053
+ } catch (e) {
2054
+ console.error("VideoDecoder output callback error:", e);
2055
+ }
2056
+ }
2057
+ _onError(message) {
2058
+ try {
2059
+ this._errorCallback(new types_1.DOMException(message, "EncodingError"));
2060
+ } catch (e) {
2061
+ }
2062
+ }
2063
+ };
2064
+ exports.VideoDecoder = VideoDecoder2;
2065
+ }
2066
+ });
2067
+
2068
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/AudioEncoder.js
2069
+ var require_AudioEncoder = __commonJS({
2070
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/AudioEncoder.js"(exports) {
2071
+ "use strict";
2072
+ Object.defineProperty(exports, "__esModule", { value: true });
2073
+ exports.AudioEncoder = void 0;
2074
+ var EncodedAudioChunk_1 = require_EncodedAudioChunk();
2075
+ var codec_registry_1 = require_codec_registry();
2076
+ var types_1 = require_types();
2077
+ var native_1 = require_native();
2078
+ var AudioEncoder = class {
2079
+ static async isConfigSupported(config) {
2080
+ const supported = (0, codec_registry_1.isAudioCodecSupported)(config.codec) && config.sampleRate > 0 && config.numberOfChannels > 0;
2081
+ return { supported, config };
2082
+ }
2083
+ constructor(init) {
2084
+ this._state = "unconfigured";
2085
+ this._encodeQueueSize = 0;
2086
+ this._pendingCallbacks = 0;
2087
+ this._config = null;
2088
+ this._sentDecoderConfig = false;
2089
+ this._listeners = /* @__PURE__ */ new Map();
2090
+ this._ondequeue = null;
2091
+ if (!init.output || typeof init.output !== "function") {
2092
+ throw new TypeError("output callback is required");
2093
+ }
2094
+ if (!init.error || typeof init.error !== "function") {
2095
+ throw new TypeError("error callback is required");
2096
+ }
2097
+ this._outputCallback = init.output;
2098
+ this._errorCallback = init.error;
2099
+ if (native_1.native) {
2100
+ this._native = new native_1.native.AudioEncoderNative(this._onChunk.bind(this), this._onError.bind(this));
2101
+ }
2102
+ }
2103
+ get state() {
2104
+ return this._state;
2105
+ }
2106
+ get encodeQueueSize() {
2107
+ return this._encodeQueueSize;
2108
+ }
2109
+ /**
2110
+ * Event handler for dequeue events
2111
+ */
2112
+ get ondequeue() {
2113
+ return this._ondequeue;
2114
+ }
2115
+ set ondequeue(handler) {
2116
+ this._ondequeue = handler;
2117
+ }
2118
+ /**
2119
+ * Minimal EventTarget-style API for 'dequeue' events, mirroring VideoEncoder.
2120
+ */
2121
+ addEventListener(type, listener, options) {
2122
+ if (typeof listener !== "function")
2123
+ return;
2124
+ const once = !!(options && options.once);
2125
+ const wrapper = once ? () => {
2126
+ this.removeEventListener(type, wrapper);
2127
+ listener();
2128
+ } : listener;
2129
+ let set = this._listeners.get(type);
2130
+ if (!set) {
2131
+ set = /* @__PURE__ */ new Set();
2132
+ this._listeners.set(type, set);
2133
+ }
2134
+ set.add(wrapper);
2135
+ }
2136
+ removeEventListener(type, listener) {
2137
+ const set = this._listeners.get(type);
2138
+ if (!set)
2139
+ return;
2140
+ if (set.has(listener)) {
2141
+ set.delete(listener);
2142
+ }
2143
+ if (set.size === 0) {
2144
+ this._listeners.delete(type);
2145
+ }
2146
+ }
2147
+ _dispatchEvent(type) {
2148
+ if (type === "dequeue" && this._ondequeue) {
2149
+ try {
2150
+ this._ondequeue(new Event("dequeue"));
2151
+ } catch {
2152
+ }
2153
+ }
2154
+ const set = this._listeners.get(type);
2155
+ if (!set)
2156
+ return;
2157
+ for (const listener of Array.from(set)) {
2158
+ try {
2159
+ listener();
2160
+ } catch {
2161
+ }
2162
+ }
2163
+ }
2164
+ configure(config) {
2165
+ if (this._state === "closed") {
2166
+ throw new types_1.DOMException("Encoder is closed", "InvalidStateError");
2167
+ }
2168
+ if (!(0, codec_registry_1.isAudioCodecSupported)(config.codec)) {
2169
+ throw new types_1.DOMException(`Unsupported codec: ${config.codec}`, "NotSupportedError");
2170
+ }
2171
+ if (!native_1.native) {
2172
+ throw new types_1.DOMException("Native addon not available", "NotSupportedError");
2173
+ }
2174
+ if (config.sampleRate <= 0 || config.numberOfChannels <= 0) {
2175
+ throw new types_1.DOMException("Invalid audio parameters", "NotSupportedError");
2176
+ }
2177
+ const ffmpegCodec = (0, codec_registry_1.getFFmpegAudioCodec)(config.codec);
2178
+ const codecParams = {
2179
+ codec: ffmpegCodec,
2180
+ sampleRate: config.sampleRate,
2181
+ channels: config.numberOfChannels
2182
+ };
2183
+ if (config.bitrate)
2184
+ codecParams.bitrate = config.bitrate;
2185
+ this._native.configure(codecParams);
2186
+ this._config = config;
2187
+ this._state = "configured";
2188
+ this._sentDecoderConfig = false;
2189
+ }
2190
+ encode(data) {
2191
+ if (this._state !== "configured") {
2192
+ throw new types_1.DOMException("Encoder is not configured", "InvalidStateError");
2193
+ }
2194
+ const bufferSize = data.allocationSize({ planeIndex: 0 });
2195
+ const buffer = new ArrayBuffer(bufferSize);
2196
+ data.copyTo(buffer, { planeIndex: 0 });
2197
+ this._encodeQueueSize++;
2198
+ this._pendingCallbacks++;
2199
+ this._native.encode(new Float32Array(buffer), data.format, data.sampleRate, data.numberOfFrames, data.numberOfChannels, data.timestamp);
2200
+ setImmediate(() => {
2201
+ this._pendingCallbacks--;
2202
+ this._encodeQueueSize = Math.max(0, this._encodeQueueSize - 1);
2203
+ this._dispatchEvent("dequeue");
2204
+ });
2205
+ }
2206
+ async flush() {
2207
+ if (this._state !== "configured") {
2208
+ throw new types_1.DOMException("Encoder is not configured", "InvalidStateError");
2209
+ }
2210
+ return new Promise((resolve, reject) => {
2211
+ this._native.flush(async (err) => {
2212
+ if (err) {
2213
+ reject(new types_1.DOMException(err.message, "EncodingError"));
2214
+ } else {
2215
+ while (this._pendingCallbacks > 0) {
2216
+ await new Promise((r) => setImmediate(r));
2217
+ }
2218
+ resolve();
2219
+ }
2220
+ });
2221
+ });
2222
+ }
2223
+ reset() {
2224
+ if (this._state === "closed") {
2225
+ throw new types_1.DOMException("Encoder is closed", "InvalidStateError");
2226
+ }
2227
+ if (this._native) {
2228
+ this._native.reset();
2229
+ }
2230
+ this._encodeQueueSize = 0;
2231
+ this._state = "unconfigured";
2232
+ this._sentDecoderConfig = false;
2233
+ this._config = null;
2234
+ }
2235
+ close() {
2236
+ if (this._state === "closed")
2237
+ return;
2238
+ if (this._native) {
2239
+ this._native.close();
2240
+ }
2241
+ this._state = "closed";
2242
+ this._encodeQueueSize = 0;
2243
+ this._config = null;
2244
+ }
2245
+ _onChunk(data, timestamp, duration, extradata) {
2246
+ const chunk = new EncodedAudioChunk_1.EncodedAudioChunk({
2247
+ type: "key",
2248
+ // Audio frames are typically all keyframes
2249
+ timestamp,
2250
+ duration: duration > 0 ? duration : void 0,
2251
+ data
2252
+ });
2253
+ let metadata;
2254
+ if (!this._sentDecoderConfig && this._config) {
2255
+ metadata = {
2256
+ decoderConfig: {
2257
+ codec: this._config.codec,
2258
+ sampleRate: this._config.sampleRate,
2259
+ numberOfChannels: this._config.numberOfChannels,
2260
+ description: extradata ? new Uint8Array(extradata).buffer : void 0
2261
+ }
2262
+ };
2263
+ this._sentDecoderConfig = true;
2264
+ }
2265
+ try {
2266
+ this._outputCallback(chunk, metadata);
2267
+ } catch (e) {
2268
+ }
2269
+ }
2270
+ _onError(message) {
2271
+ try {
2272
+ this._errorCallback(new types_1.DOMException(message, "EncodingError"));
2273
+ } catch (e) {
2274
+ }
2275
+ }
2276
+ };
2277
+ exports.AudioEncoder = AudioEncoder;
2278
+ }
2279
+ });
2280
+
2281
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/AudioDecoder.js
2282
+ var require_AudioDecoder = __commonJS({
2283
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/AudioDecoder.js"(exports) {
2284
+ "use strict";
2285
+ Object.defineProperty(exports, "__esModule", { value: true });
2286
+ exports.AudioDecoder = void 0;
2287
+ var AudioData_1 = require_AudioData();
2288
+ var codec_registry_1 = require_codec_registry();
2289
+ var types_1 = require_types();
2290
+ var native_1 = require_native();
2291
+ var AudioDecoder = class {
2292
+ static async isConfigSupported(config) {
2293
+ const supported = (0, codec_registry_1.isAudioCodecSupported)(config.codec);
2294
+ return { supported, config };
2295
+ }
2296
+ constructor(init) {
2297
+ this._state = "unconfigured";
2298
+ this._decodeQueueSize = 0;
2299
+ this._config = null;
2300
+ this._ondequeue = null;
2301
+ this._listeners = /* @__PURE__ */ new Map();
2302
+ if (!init.output || typeof init.output !== "function") {
2303
+ throw new TypeError("output callback is required");
2304
+ }
2305
+ if (!init.error || typeof init.error !== "function") {
2306
+ throw new TypeError("error callback is required");
2307
+ }
2308
+ this._outputCallback = init.output;
2309
+ this._errorCallback = init.error;
2310
+ if (native_1.native) {
2311
+ this._native = new native_1.native.AudioDecoderNative(this._onData.bind(this), this._onError.bind(this));
2312
+ }
2313
+ }
2314
+ get state() {
2315
+ return this._state;
2316
+ }
2317
+ get decodeQueueSize() {
2318
+ return this._decodeQueueSize;
2319
+ }
2320
+ /**
2321
+ * Event handler for dequeue events
2322
+ */
2323
+ get ondequeue() {
2324
+ return this._ondequeue;
2325
+ }
2326
+ set ondequeue(handler) {
2327
+ this._ondequeue = handler;
2328
+ }
2329
+ /**
2330
+ * Minimal EventTarget-style API for 'dequeue' events.
2331
+ * Enables compatibility with MediaBunny and browser WebCodecs code.
2332
+ */
2333
+ addEventListener(type, listener, options) {
2334
+ if (typeof listener !== "function")
2335
+ return;
2336
+ const once = !!(options && options.once);
2337
+ const wrapper = once ? () => {
2338
+ this.removeEventListener(type, wrapper);
2339
+ listener();
2340
+ } : listener;
2341
+ let set = this._listeners.get(type);
2342
+ if (!set) {
2343
+ set = /* @__PURE__ */ new Set();
2344
+ this._listeners.set(type, set);
2345
+ }
2346
+ set.add(wrapper);
2347
+ }
2348
+ removeEventListener(type, listener) {
2349
+ const set = this._listeners.get(type);
2350
+ if (!set)
2351
+ return;
2352
+ if (set.has(listener)) {
2353
+ set.delete(listener);
2354
+ }
2355
+ if (set.size === 0) {
2356
+ this._listeners.delete(type);
2357
+ }
2358
+ }
2359
+ _dispatchEvent(type) {
2360
+ if (type === "dequeue" && this._ondequeue) {
2361
+ try {
2362
+ this._ondequeue(new Event("dequeue"));
2363
+ } catch {
2364
+ }
2365
+ }
2366
+ const set = this._listeners.get(type);
2367
+ if (set) {
2368
+ for (const listener of set) {
2369
+ try {
2370
+ listener();
2371
+ } catch {
2372
+ }
2373
+ }
2374
+ }
2375
+ }
2376
+ configure(config) {
2377
+ if (this._state === "closed") {
2378
+ throw new types_1.DOMException("Decoder is closed", "InvalidStateError");
2379
+ }
2380
+ if (!(0, codec_registry_1.isAudioCodecSupported)(config.codec)) {
2381
+ throw new types_1.DOMException(`Unsupported codec: ${config.codec}`, "NotSupportedError");
2382
+ }
2383
+ if (!native_1.native) {
2384
+ throw new types_1.DOMException("Native addon not available", "NotSupportedError");
2385
+ }
2386
+ const ffmpegCodec = (0, codec_registry_1.getFFmpegAudioDecoder)(config.codec);
2387
+ const codecParams = {
2388
+ codec: ffmpegCodec,
2389
+ sampleRate: config.sampleRate,
2390
+ channels: config.numberOfChannels
2391
+ };
2392
+ if (config.description) {
2393
+ let desc;
2394
+ if (config.description instanceof ArrayBuffer) {
2395
+ desc = new Uint8Array(config.description);
2396
+ } else {
2397
+ desc = new Uint8Array(config.description.buffer, config.description.byteOffset, config.description.byteLength);
2398
+ }
2399
+ codecParams.extradata = Buffer.from(desc);
2400
+ }
2401
+ this._native.configure(codecParams);
2402
+ this._config = config;
2403
+ this._state = "configured";
2404
+ }
2405
+ decode(chunk) {
2406
+ if (this._state !== "configured") {
2407
+ throw new types_1.DOMException("Decoder is not configured", "InvalidStateError");
2408
+ }
2409
+ const data = new Uint8Array(chunk.byteLength);
2410
+ chunk.copyTo(data);
2411
+ this._decodeQueueSize++;
2412
+ this._native.decode(Buffer.from(data), chunk.type === "key", chunk.timestamp, chunk.duration ?? 0);
2413
+ }
2414
+ async flush() {
2415
+ if (this._state !== "configured") {
2416
+ throw new types_1.DOMException("Decoder is not configured", "InvalidStateError");
2417
+ }
2418
+ return new Promise((resolve, reject) => {
2419
+ this._native.flush((err) => {
2420
+ if (err) {
2421
+ reject(new types_1.DOMException(err.message, "EncodingError"));
2422
+ } else {
2423
+ resolve();
2424
+ }
2425
+ });
2426
+ });
2427
+ }
2428
+ reset() {
2429
+ if (this._state === "closed") {
2430
+ throw new types_1.DOMException("Decoder is closed", "InvalidStateError");
2431
+ }
2432
+ if (this._native) {
2433
+ this._native.reset();
2434
+ }
2435
+ this._decodeQueueSize = 0;
2436
+ this._state = "unconfigured";
2437
+ this._config = null;
2438
+ }
2439
+ close() {
2440
+ if (this._state === "closed")
2441
+ return;
2442
+ if (this._native) {
2443
+ this._native.close();
2444
+ }
2445
+ this._state = "closed";
2446
+ this._decodeQueueSize = 0;
2447
+ this._config = null;
2448
+ }
2449
+ _onData(buffer, format, sampleRate, numberOfFrames, numberOfChannels, timestamp) {
2450
+ const bufferCopy = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength).slice();
2451
+ setImmediate(() => {
2452
+ this._decodeQueueSize = Math.max(0, this._decodeQueueSize - 1);
2453
+ this._dispatchEvent("dequeue");
2454
+ try {
2455
+ const audioData = new AudioData_1.AudioData({
2456
+ format,
2457
+ sampleRate,
2458
+ numberOfFrames,
2459
+ numberOfChannels,
2460
+ timestamp,
2461
+ data: bufferCopy.buffer
2462
+ });
2463
+ this._outputCallback(audioData);
2464
+ } catch (e) {
2465
+ console.error("AudioDecoder output callback error:", e);
2466
+ }
2467
+ });
2468
+ }
2469
+ _onError(message) {
2470
+ try {
2471
+ this._errorCallback(new types_1.DOMException(message, "EncodingError"));
2472
+ } catch (e) {
2473
+ }
2474
+ }
2475
+ };
2476
+ exports.AudioDecoder = AudioDecoder;
2477
+ }
2478
+ });
2479
+
2480
+ // ../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/index.js
2481
+ var require_dist = __commonJS({
2482
+ "../../node_modules/.pnpm/node-webcodecs@1.0.0/node_modules/node-webcodecs/dist/index.js"(exports) {
2483
+ "use strict";
2484
+ Object.defineProperty(exports, "__esModule", { value: true });
2485
+ exports.DOMRectReadOnly = exports.parseVp9CodecString = exports.parseAacCodecString = exports.parseAvcCodecString = exports.getFFmpegAudioCodec = exports.getFFmpegVideoCodec = exports.isAudioCodecSupported = exports.isVideoCodecSupported = exports.AudioDecoder = exports.AudioEncoder = exports.VideoDecoder = exports.VideoEncoder = exports.ImageDecoder = exports.VideoColorSpace = exports.EncodedAudioChunk = exports.EncodedVideoChunk = exports.AudioData = exports.VideoFrame = void 0;
2486
+ exports.getFFmpegVersion = getFFmpegVersion;
2487
+ exports.listCodecs = listCodecs;
2488
+ exports.hasCodec = hasCodec;
2489
+ exports.isNativeAvailable = isNativeAvailable;
2490
+ var VideoFrame_1 = require_VideoFrame();
2491
+ Object.defineProperty(exports, "VideoFrame", { enumerable: true, get: function() {
2492
+ return VideoFrame_1.VideoFrame;
2493
+ } });
2494
+ var AudioData_1 = require_AudioData();
2495
+ Object.defineProperty(exports, "AudioData", { enumerable: true, get: function() {
2496
+ return AudioData_1.AudioData;
2497
+ } });
2498
+ var EncodedVideoChunk_1 = require_EncodedVideoChunk();
2499
+ Object.defineProperty(exports, "EncodedVideoChunk", { enumerable: true, get: function() {
2500
+ return EncodedVideoChunk_1.EncodedVideoChunk;
2501
+ } });
2502
+ var EncodedAudioChunk_1 = require_EncodedAudioChunk();
2503
+ Object.defineProperty(exports, "EncodedAudioChunk", { enumerable: true, get: function() {
2504
+ return EncodedAudioChunk_1.EncodedAudioChunk;
2505
+ } });
2506
+ var VideoColorSpace_1 = require_VideoColorSpace();
2507
+ Object.defineProperty(exports, "VideoColorSpace", { enumerable: true, get: function() {
2508
+ return VideoColorSpace_1.VideoColorSpace;
2509
+ } });
2510
+ var ImageDecoder_1 = require_ImageDecoder();
2511
+ Object.defineProperty(exports, "ImageDecoder", { enumerable: true, get: function() {
2512
+ return ImageDecoder_1.ImageDecoder;
2513
+ } });
2514
+ var VideoEncoder_1 = require_VideoEncoder();
2515
+ Object.defineProperty(exports, "VideoEncoder", { enumerable: true, get: function() {
2516
+ return VideoEncoder_1.VideoEncoder;
2517
+ } });
2518
+ var VideoDecoder_1 = require_VideoDecoder();
2519
+ Object.defineProperty(exports, "VideoDecoder", { enumerable: true, get: function() {
2520
+ return VideoDecoder_1.VideoDecoder;
2521
+ } });
2522
+ var AudioEncoder_1 = require_AudioEncoder();
2523
+ Object.defineProperty(exports, "AudioEncoder", { enumerable: true, get: function() {
2524
+ return AudioEncoder_1.AudioEncoder;
2525
+ } });
2526
+ var AudioDecoder_1 = require_AudioDecoder();
2527
+ Object.defineProperty(exports, "AudioDecoder", { enumerable: true, get: function() {
2528
+ return AudioDecoder_1.AudioDecoder;
2529
+ } });
2530
+ var codec_registry_1 = require_codec_registry();
2531
+ Object.defineProperty(exports, "isVideoCodecSupported", { enumerable: true, get: function() {
2532
+ return codec_registry_1.isVideoCodecSupported;
2533
+ } });
2534
+ Object.defineProperty(exports, "isAudioCodecSupported", { enumerable: true, get: function() {
2535
+ return codec_registry_1.isAudioCodecSupported;
2536
+ } });
2537
+ Object.defineProperty(exports, "getFFmpegVideoCodec", { enumerable: true, get: function() {
2538
+ return codec_registry_1.getFFmpegVideoCodec;
2539
+ } });
2540
+ Object.defineProperty(exports, "getFFmpegAudioCodec", { enumerable: true, get: function() {
2541
+ return codec_registry_1.getFFmpegAudioCodec;
2542
+ } });
2543
+ Object.defineProperty(exports, "parseAvcCodecString", { enumerable: true, get: function() {
2544
+ return codec_registry_1.parseAvcCodecString;
2545
+ } });
2546
+ Object.defineProperty(exports, "parseAacCodecString", { enumerable: true, get: function() {
2547
+ return codec_registry_1.parseAacCodecString;
2548
+ } });
2549
+ Object.defineProperty(exports, "parseVp9CodecString", { enumerable: true, get: function() {
2550
+ return codec_registry_1.parseVp9CodecString;
2551
+ } });
2552
+ var types_1 = require_types();
2553
+ Object.defineProperty(exports, "DOMRectReadOnly", { enumerable: true, get: function() {
2554
+ return types_1.DOMRectReadOnly;
2555
+ } });
2556
+ var native_1 = require_native();
2557
+ function getFFmpegVersion() {
2558
+ if (native_1.native && native_1.native.getFFmpegVersion) {
2559
+ return native_1.native.getFFmpegVersion();
2560
+ }
2561
+ return null;
2562
+ }
2563
+ function listCodecs() {
2564
+ if (native_1.native && native_1.native.listCodecs) {
2565
+ return native_1.native.listCodecs();
2566
+ }
2567
+ return null;
2568
+ }
2569
+ function hasCodec(codecName, type) {
2570
+ if (native_1.native && native_1.native.hasCodec) {
2571
+ return native_1.native.hasCodec(codecName, type);
2572
+ }
2573
+ return false;
2574
+ }
2575
+ function isNativeAvailable() {
2576
+ return native_1.native !== null;
2577
+ }
2578
+ }
2579
+ });
2
2580
 
3
2581
  // src/VoiceManager.ts
4
2582
  import { EventEmitter as EventEmitter3 } from "events";
@@ -13,6 +2591,9 @@ var thumbnail = MINIMAL_PNG_BASE64;
13
2591
  import { EventEmitter } from "events";
14
2592
  import * as nacl from "tweetnacl";
15
2593
  import * as dgram from "dgram";
2594
+ import * as ws from "ws";
2595
+ import { Readable } from "stream";
2596
+ import { opus } from "prism-media";
16
2597
  var VOICE_WS_OPCODES = {
17
2598
  Identify: 0,
18
2599
  SelectProtocol: 1,
@@ -156,11 +2737,11 @@ var VoiceConnection = class extends EventEmitter {
156
2737
  this.voiceWs.removeAllListeners();
157
2738
  }
158
2739
  };
159
- const ws = this.voiceWs;
160
- ws.on("open", onOpen);
161
- ws.on("error", onError);
162
- ws.on("message", (data) => onMessage(data));
163
- ws.once("close", () => {
2740
+ const ws2 = this.voiceWs;
2741
+ ws2.on("open", onOpen);
2742
+ ws2.on("error", onError);
2743
+ ws2.on("message", (data) => onMessage(data));
2744
+ ws2.once("close", () => {
164
2745
  cleanup();
165
2746
  if (!this._destroyed) reject(new Error("Voice WebSocket closed"));
166
2747
  });
@@ -168,7 +2749,6 @@ var VoiceConnection = class extends EventEmitter {
168
2749
  }
169
2750
  async getWebSocketConstructor() {
170
2751
  try {
171
- const ws = await import("ws");
172
2752
  return ws.default;
173
2753
  } catch {
174
2754
  throw new Error('Install "ws" for voice support: pnpm add ws');
@@ -254,8 +2834,6 @@ var VoiceConnection = class extends EventEmitter {
254
2834
  */
255
2835
  async play(urlOrStream) {
256
2836
  this.stop();
257
- const { opus: prismOpus } = await import("prism-media");
258
- const { Readable } = await import("stream");
259
2837
  let inputStream;
260
2838
  if (typeof urlOrStream === "string") {
261
2839
  try {
@@ -271,7 +2849,7 @@ var VoiceConnection = class extends EventEmitter {
271
2849
  } else {
272
2850
  inputStream = urlOrStream;
273
2851
  }
274
- const demuxer = new prismOpus.WebmDemuxer();
2852
+ const demuxer = new opus.WebmDemuxer();
275
2853
  inputStream.pipe(demuxer);
276
2854
  this._playing = true;
277
2855
  this.currentStream = demuxer;
@@ -364,7 +2942,7 @@ var VoiceConnection = class extends EventEmitter {
364
2942
  };
365
2943
 
366
2944
  // src/LiveKitRtcConnection.ts
367
- import { spawn } from "child_process";
2945
+ import { execFile, spawn } from "child_process";
368
2946
  import { EventEmitter as EventEmitter2 } from "events";
369
2947
  import {
370
2948
  Room,
@@ -466,6 +3044,12 @@ function concatUint8Arrays(a, b) {
466
3044
  }
467
3045
 
468
3046
  // src/LiveKitRtcConnection.ts
3047
+ var WebCodecs = __toESM(require_dist());
3048
+ import { Readable as Readable2 } from "stream";
3049
+ import { OpusDecoder } from "opus-decoder";
3050
+ import { opus as opus2 } from "prism-media";
3051
+ import { promisify } from "util";
3052
+ import { createFile } from "mp4box";
469
3053
  var SAMPLE_RATE = 48e3;
470
3054
  var CHANNELS2 = 1;
471
3055
  function getNaluByteLength(nalu) {
@@ -710,13 +3294,11 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
710
3294
  this.emit("error", new Error("useFFmpeg requires a URL; buffer/ArrayBuffer not supported"));
711
3295
  return;
712
3296
  }
713
- const { createFile } = await import("mp4box");
714
- let VideoDecoder;
715
- let EncodedVideoChunk;
3297
+ let VideoDecoder2;
3298
+ let EncodedVideoChunk2;
716
3299
  try {
717
- const webcodecs = await import("./dist-N4IEBIZ4.mjs");
718
- VideoDecoder = webcodecs.VideoDecoder;
719
- EncodedVideoChunk = webcodecs.EncodedVideoChunk;
3300
+ VideoDecoder2 = WebCodecs.VideoDecoder;
3301
+ EncodedVideoChunk2 = WebCodecs.EncodedVideoChunk;
720
3302
  } catch {
721
3303
  this.emit(
722
3304
  "error",
@@ -800,7 +3382,7 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
800
3382
  const FRAME_INTERVAL_MS = Math.round(1e3 / maxFps);
801
3383
  const MAX_QUEUED_FRAMES = 30;
802
3384
  let pacingInterval = null;
803
- const decoder = new VideoDecoder({
3385
+ const decoder = new VideoDecoder2({
804
3386
  output: async (frame) => {
805
3387
  if (!this._playingVideo || !source) return;
806
3388
  const { codedWidth, codedHeight } = frame;
@@ -944,7 +3526,7 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
944
3526
  try {
945
3527
  for (const sample of samp) {
946
3528
  const isKeyFrame = sample.is_sync ?? sample.is_rap ?? sample.dts === 0;
947
- const chunk = new EncodedVideoChunk({
3529
+ const chunk = new EncodedVideoChunk2({
948
3530
  type: isKeyFrame ? "key" : "delta",
949
3531
  timestamp: Math.round(sample.dts / sample.timescale * 1e6),
950
3532
  duration: Math.round(sample.duration / sample.timescale * 1e6),
@@ -983,7 +3565,7 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
983
3565
  try {
984
3566
  for (const sample of samples) {
985
3567
  const isKeyFrame = sample.is_sync ?? sample.is_rap ?? sample.dts === 0;
986
- const chunk = new EncodedVideoChunk({
3568
+ const chunk = new EncodedVideoChunk2({
987
3569
  type: isKeyFrame ? "key" : "delta",
988
3570
  timestamp: Math.round(sample.dts / sample.timescale * 1e6),
989
3571
  duration: Math.round(sample.duration / sample.timescale * 1e6),
@@ -1056,8 +3638,6 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
1056
3638
  file.start();
1057
3639
  });
1058
3640
  if (videoUrl && audioSource && audioTrack) {
1059
- const { opus: prismOpus } = await import("prism-media");
1060
- const { OpusDecoder } = await import("opus-decoder");
1061
3641
  const runAudioFfmpeg = async () => {
1062
3642
  if (!this._playingVideo || cleanupCalled || !audioSource) return;
1063
3643
  const audioProc = spawn(
@@ -1079,7 +3659,7 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
1079
3659
  { stdio: ["ignore", "pipe", "pipe"] }
1080
3660
  );
1081
3661
  audioFfmpegProc = audioProc;
1082
- const demuxer = new prismOpus.WebmDemuxer();
3662
+ const demuxer = new opus2.WebmDemuxer();
1083
3663
  if (audioProc.stdout) audioProc.stdout.pipe(demuxer);
1084
3664
  const decoder2 = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
1085
3665
  await decoder2.ready;
@@ -1169,8 +3749,6 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
1169
3749
  let height = 480;
1170
3750
  let hasAudio = false;
1171
3751
  try {
1172
- const { execFile } = await import("child_process");
1173
- const { promisify } = await import("util");
1174
3752
  const exec = promisify(execFile);
1175
3753
  const { stdout } = await exec(
1176
3754
  "ffprobe",
@@ -1433,9 +4011,7 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
1433
4011
  }
1434
4012
  if (hasAudio && audioReady && audioSource && proc.stdio[3]) {
1435
4013
  const audioPipe = proc.stdio[3];
1436
- const { opus: prismOpus } = await import("prism-media");
1437
- const { OpusDecoder } = await import("opus-decoder");
1438
- const demuxer = new prismOpus.WebmDemuxer();
4014
+ const demuxer = new opus2.WebmDemuxer();
1439
4015
  audioPipe.pipe(demuxer);
1440
4016
  const decoder = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
1441
4017
  await decoder.ready;
@@ -1517,16 +4093,13 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
1517
4093
  this.emit("error", new Error("LiveKit: not connected"));
1518
4094
  return;
1519
4095
  }
1520
- const { opus: prismOpus } = await import("prism-media");
1521
- const { Readable } = await import("stream");
1522
- const { OpusDecoder } = await import("opus-decoder");
1523
4096
  let inputStream;
1524
4097
  if (typeof urlOrStream === "string") {
1525
4098
  try {
1526
4099
  const response = await fetch(urlOrStream);
1527
4100
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
1528
4101
  if (!response.body) throw new Error("No response body");
1529
- inputStream = Readable.fromWeb(response.body);
4102
+ inputStream = Readable2.fromWeb(response.body);
1530
4103
  } catch (e) {
1531
4104
  this.emit("error", e instanceof Error ? e : new Error(String(e)));
1532
4105
  return;
@@ -1541,7 +4114,7 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
1541
4114
  const options = new TrackPublishOptions();
1542
4115
  options.source = TrackSource.SOURCE_MICROPHONE;
1543
4116
  await this.room.localParticipant.publishTrack(track, options);
1544
- const demuxer = new prismOpus.WebmDemuxer();
4117
+ const demuxer = new opus2.WebmDemuxer();
1545
4118
  inputStream.pipe(demuxer);
1546
4119
  this.currentStream = demuxer;
1547
4120
  const decoder = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });