@fluxerjs/voice 1.2.0 → 1.2.2
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.js +26 -2582
- package/dist/index.mjs +20 -27
- package/package.json +5 -5
- package/dist/chunk-EBO3CZXG.mjs +0 -15
- package/dist/dist-N4IEBIZ4.mjs +0 -2552
package/dist/index.js
CHANGED
|
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
-
};
|
|
11
8
|
var __export = (target, all) => {
|
|
12
9
|
for (var name in all)
|
|
13
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -30,2554 +27,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
27
|
));
|
|
31
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
29
|
|
|
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"(exports2) {
|
|
36
|
-
"use strict";
|
|
37
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
38
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
62
|
-
"use strict";
|
|
63
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
64
|
-
exports2.DOMException = exports2.WebCodecsDOMException = exports2.DOMRectReadOnly = void 0;
|
|
65
|
-
exports2.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
|
-
exports2.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
|
-
exports2.WebCodecsDOMException = WebCodecsDOMException;
|
|
91
|
-
exports2.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"(exports2, module2) {
|
|
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
|
-
module2.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"(exports2, module2) {
|
|
329
|
-
"use strict";
|
|
330
|
-
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
|
|
331
|
-
if (typeof runtimeRequire.addon === "function") {
|
|
332
|
-
module2.exports = runtimeRequire.addon.bind(runtimeRequire);
|
|
333
|
-
} else {
|
|
334
|
-
module2.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"(exports2) {
|
|
342
|
-
"use strict";
|
|
343
|
-
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
344
|
-
return mod && mod.__esModule ? mod : { "default": mod };
|
|
345
|
-
};
|
|
346
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
347
|
-
exports2.native = void 0;
|
|
348
|
-
var path_1 = __importDefault(require("path"));
|
|
349
|
-
var nodeGypBuild = require_node_gyp_build2();
|
|
350
|
-
var native;
|
|
351
|
-
try {
|
|
352
|
-
exports2.native = native = nodeGypBuild(path_1.default.join(__dirname, ".."));
|
|
353
|
-
} catch (error) {
|
|
354
|
-
exports2.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"(exports2) {
|
|
366
|
-
"use strict";
|
|
367
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
368
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
607
|
-
"use strict";
|
|
608
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
609
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
800
|
-
"use strict";
|
|
801
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
802
|
-
exports2.EncodedVideoChunk = void 0;
|
|
803
|
-
var EncodedVideoChunk = 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
|
-
exports2.EncodedVideoChunk = EncodedVideoChunk;
|
|
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"(exports2) {
|
|
852
|
-
"use strict";
|
|
853
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
854
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
904
|
-
"use strict";
|
|
905
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
906
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
1070
|
-
"use strict";
|
|
1071
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1072
|
-
exports2.AUDIO_CODECS = exports2.VIDEO_CODECS = void 0;
|
|
1073
|
-
exports2.parseAvcCodecString = parseAvcCodecString;
|
|
1074
|
-
exports2.parseAacCodecString = parseAacCodecString;
|
|
1075
|
-
exports2.parseVp9CodecString = parseVp9CodecString;
|
|
1076
|
-
exports2.isVideoCodecSupported = isVideoCodecSupported;
|
|
1077
|
-
exports2.isAudioCodecSupported = isAudioCodecSupported;
|
|
1078
|
-
exports2.getFFmpegVideoCodec = getFFmpegVideoCodec;
|
|
1079
|
-
exports2.getFFmpegVideoDecoder = getFFmpegVideoDecoder;
|
|
1080
|
-
exports2.getFFmpegAudioCodec = getFFmpegAudioCodec;
|
|
1081
|
-
exports2.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
|
-
exports2.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
|
-
exports2.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 exports2.VIDEO_CODECS;
|
|
1200
|
-
}
|
|
1201
|
-
function isAudioCodecSupported(codec) {
|
|
1202
|
-
if (codec.startsWith("mp4a.40.")) {
|
|
1203
|
-
return parseAacCodecString(codec) !== null;
|
|
1204
|
-
}
|
|
1205
|
-
return codec in exports2.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 = exports2.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 = exports2.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 = exports2.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 = exports2.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"(exports2) {
|
|
1283
|
-
"use strict";
|
|
1284
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1285
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
1826
|
-
"use strict";
|
|
1827
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1828
|
-
exports2.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 VideoDecoder = 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
|
-
exports2.VideoDecoder = VideoDecoder;
|
|
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"(exports2) {
|
|
2071
|
-
"use strict";
|
|
2072
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2073
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
2284
|
-
"use strict";
|
|
2285
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2286
|
-
exports2.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
|
-
exports2.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"(exports2) {
|
|
2483
|
-
"use strict";
|
|
2484
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2485
|
-
exports2.DOMRectReadOnly = exports2.parseVp9CodecString = exports2.parseAacCodecString = exports2.parseAvcCodecString = exports2.getFFmpegAudioCodec = exports2.getFFmpegVideoCodec = exports2.isAudioCodecSupported = exports2.isVideoCodecSupported = exports2.AudioDecoder = exports2.AudioEncoder = exports2.VideoDecoder = exports2.VideoEncoder = exports2.ImageDecoder = exports2.VideoColorSpace = exports2.EncodedAudioChunk = exports2.EncodedVideoChunk = exports2.AudioData = exports2.VideoFrame = void 0;
|
|
2486
|
-
exports2.getFFmpegVersion = getFFmpegVersion;
|
|
2487
|
-
exports2.listCodecs = listCodecs;
|
|
2488
|
-
exports2.hasCodec = hasCodec;
|
|
2489
|
-
exports2.isNativeAvailable = isNativeAvailable;
|
|
2490
|
-
var VideoFrame_1 = require_VideoFrame();
|
|
2491
|
-
Object.defineProperty(exports2, "VideoFrame", { enumerable: true, get: function() {
|
|
2492
|
-
return VideoFrame_1.VideoFrame;
|
|
2493
|
-
} });
|
|
2494
|
-
var AudioData_1 = require_AudioData();
|
|
2495
|
-
Object.defineProperty(exports2, "AudioData", { enumerable: true, get: function() {
|
|
2496
|
-
return AudioData_1.AudioData;
|
|
2497
|
-
} });
|
|
2498
|
-
var EncodedVideoChunk_1 = require_EncodedVideoChunk();
|
|
2499
|
-
Object.defineProperty(exports2, "EncodedVideoChunk", { enumerable: true, get: function() {
|
|
2500
|
-
return EncodedVideoChunk_1.EncodedVideoChunk;
|
|
2501
|
-
} });
|
|
2502
|
-
var EncodedAudioChunk_1 = require_EncodedAudioChunk();
|
|
2503
|
-
Object.defineProperty(exports2, "EncodedAudioChunk", { enumerable: true, get: function() {
|
|
2504
|
-
return EncodedAudioChunk_1.EncodedAudioChunk;
|
|
2505
|
-
} });
|
|
2506
|
-
var VideoColorSpace_1 = require_VideoColorSpace();
|
|
2507
|
-
Object.defineProperty(exports2, "VideoColorSpace", { enumerable: true, get: function() {
|
|
2508
|
-
return VideoColorSpace_1.VideoColorSpace;
|
|
2509
|
-
} });
|
|
2510
|
-
var ImageDecoder_1 = require_ImageDecoder();
|
|
2511
|
-
Object.defineProperty(exports2, "ImageDecoder", { enumerable: true, get: function() {
|
|
2512
|
-
return ImageDecoder_1.ImageDecoder;
|
|
2513
|
-
} });
|
|
2514
|
-
var VideoEncoder_1 = require_VideoEncoder();
|
|
2515
|
-
Object.defineProperty(exports2, "VideoEncoder", { enumerable: true, get: function() {
|
|
2516
|
-
return VideoEncoder_1.VideoEncoder;
|
|
2517
|
-
} });
|
|
2518
|
-
var VideoDecoder_1 = require_VideoDecoder();
|
|
2519
|
-
Object.defineProperty(exports2, "VideoDecoder", { enumerable: true, get: function() {
|
|
2520
|
-
return VideoDecoder_1.VideoDecoder;
|
|
2521
|
-
} });
|
|
2522
|
-
var AudioEncoder_1 = require_AudioEncoder();
|
|
2523
|
-
Object.defineProperty(exports2, "AudioEncoder", { enumerable: true, get: function() {
|
|
2524
|
-
return AudioEncoder_1.AudioEncoder;
|
|
2525
|
-
} });
|
|
2526
|
-
var AudioDecoder_1 = require_AudioDecoder();
|
|
2527
|
-
Object.defineProperty(exports2, "AudioDecoder", { enumerable: true, get: function() {
|
|
2528
|
-
return AudioDecoder_1.AudioDecoder;
|
|
2529
|
-
} });
|
|
2530
|
-
var codec_registry_1 = require_codec_registry();
|
|
2531
|
-
Object.defineProperty(exports2, "isVideoCodecSupported", { enumerable: true, get: function() {
|
|
2532
|
-
return codec_registry_1.isVideoCodecSupported;
|
|
2533
|
-
} });
|
|
2534
|
-
Object.defineProperty(exports2, "isAudioCodecSupported", { enumerable: true, get: function() {
|
|
2535
|
-
return codec_registry_1.isAudioCodecSupported;
|
|
2536
|
-
} });
|
|
2537
|
-
Object.defineProperty(exports2, "getFFmpegVideoCodec", { enumerable: true, get: function() {
|
|
2538
|
-
return codec_registry_1.getFFmpegVideoCodec;
|
|
2539
|
-
} });
|
|
2540
|
-
Object.defineProperty(exports2, "getFFmpegAudioCodec", { enumerable: true, get: function() {
|
|
2541
|
-
return codec_registry_1.getFFmpegAudioCodec;
|
|
2542
|
-
} });
|
|
2543
|
-
Object.defineProperty(exports2, "parseAvcCodecString", { enumerable: true, get: function() {
|
|
2544
|
-
return codec_registry_1.parseAvcCodecString;
|
|
2545
|
-
} });
|
|
2546
|
-
Object.defineProperty(exports2, "parseAacCodecString", { enumerable: true, get: function() {
|
|
2547
|
-
return codec_registry_1.parseAacCodecString;
|
|
2548
|
-
} });
|
|
2549
|
-
Object.defineProperty(exports2, "parseVp9CodecString", { enumerable: true, get: function() {
|
|
2550
|
-
return codec_registry_1.parseVp9CodecString;
|
|
2551
|
-
} });
|
|
2552
|
-
var types_1 = require_types();
|
|
2553
|
-
Object.defineProperty(exports2, "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
|
-
});
|
|
2580
|
-
|
|
2581
30
|
// src/index.ts
|
|
2582
31
|
var index_exports = {};
|
|
2583
32
|
__export(index_exports, {
|
|
@@ -2602,6 +51,9 @@ var thumbnail = MINIMAL_PNG_BASE64;
|
|
|
2602
51
|
var import_events = require("events");
|
|
2603
52
|
var nacl = __toESM(require("tweetnacl"));
|
|
2604
53
|
var dgram = __toESM(require("dgram"));
|
|
54
|
+
var ws = __toESM(require("ws"));
|
|
55
|
+
var import_node_stream = require("stream");
|
|
56
|
+
var import_prism_media = require("prism-media");
|
|
2605
57
|
var VOICE_WS_OPCODES = {
|
|
2606
58
|
Identify: 0,
|
|
2607
59
|
SelectProtocol: 1,
|
|
@@ -2745,11 +197,11 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2745
197
|
this.voiceWs.removeAllListeners();
|
|
2746
198
|
}
|
|
2747
199
|
};
|
|
2748
|
-
const
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
200
|
+
const ws2 = this.voiceWs;
|
|
201
|
+
ws2.on("open", onOpen);
|
|
202
|
+
ws2.on("error", onError);
|
|
203
|
+
ws2.on("message", (data) => onMessage(data));
|
|
204
|
+
ws2.once("close", () => {
|
|
2753
205
|
cleanup();
|
|
2754
206
|
if (!this._destroyed) reject(new Error("Voice WebSocket closed"));
|
|
2755
207
|
});
|
|
@@ -2757,7 +209,6 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2757
209
|
}
|
|
2758
210
|
async getWebSocketConstructor() {
|
|
2759
211
|
try {
|
|
2760
|
-
const ws = await import("ws");
|
|
2761
212
|
return ws.default;
|
|
2762
213
|
} catch {
|
|
2763
214
|
throw new Error('Install "ws" for voice support: pnpm add ws');
|
|
@@ -2843,15 +294,13 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2843
294
|
*/
|
|
2844
295
|
async play(urlOrStream) {
|
|
2845
296
|
this.stop();
|
|
2846
|
-
const { opus: prismOpus } = await import("prism-media");
|
|
2847
|
-
const { Readable } = await import("stream");
|
|
2848
297
|
let inputStream;
|
|
2849
298
|
if (typeof urlOrStream === "string") {
|
|
2850
299
|
try {
|
|
2851
300
|
const response = await fetch(urlOrStream);
|
|
2852
301
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
2853
302
|
if (!response.body) throw new Error("No response body");
|
|
2854
|
-
inputStream = Readable.fromWeb(response.body);
|
|
303
|
+
inputStream = import_node_stream.Readable.fromWeb(response.body);
|
|
2855
304
|
} catch (e) {
|
|
2856
305
|
const err = e instanceof Error ? e : new Error(String(e));
|
|
2857
306
|
this.emit("error", err);
|
|
@@ -2860,7 +309,7 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2860
309
|
} else {
|
|
2861
310
|
inputStream = urlOrStream;
|
|
2862
311
|
}
|
|
2863
|
-
const demuxer = new
|
|
312
|
+
const demuxer = new import_prism_media.opus.WebmDemuxer();
|
|
2864
313
|
inputStream.pipe(demuxer);
|
|
2865
314
|
this._playing = true;
|
|
2866
315
|
this.currentStream = demuxer;
|
|
@@ -3043,6 +492,11 @@ function concatUint8Arrays(a, b) {
|
|
|
3043
492
|
}
|
|
3044
493
|
|
|
3045
494
|
// src/LiveKitRtcConnection.ts
|
|
495
|
+
var import_node_stream2 = require("stream");
|
|
496
|
+
var import_opus_decoder = require("opus-decoder");
|
|
497
|
+
var import_prism_media2 = require("prism-media");
|
|
498
|
+
var import_node_util = require("util");
|
|
499
|
+
var import_mp4box = require("mp4box");
|
|
3046
500
|
var SAMPLE_RATE = 48e3;
|
|
3047
501
|
var CHANNELS2 = 1;
|
|
3048
502
|
function getNaluByteLength(nalu) {
|
|
@@ -3287,11 +741,10 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3287
741
|
this.emit("error", new Error("useFFmpeg requires a URL; buffer/ArrayBuffer not supported"));
|
|
3288
742
|
return;
|
|
3289
743
|
}
|
|
3290
|
-
const { createFile } = await import("mp4box");
|
|
3291
744
|
let VideoDecoder;
|
|
3292
745
|
let EncodedVideoChunk;
|
|
3293
746
|
try {
|
|
3294
|
-
const webcodecs = await
|
|
747
|
+
const webcodecs = await import("node-webcodecs");
|
|
3295
748
|
VideoDecoder = webcodecs.VideoDecoder;
|
|
3296
749
|
EncodedVideoChunk = webcodecs.EncodedVideoChunk;
|
|
3297
750
|
} catch {
|
|
@@ -3323,7 +776,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3323
776
|
} else {
|
|
3324
777
|
arrayBuffer = urlOrBuffer;
|
|
3325
778
|
}
|
|
3326
|
-
const file = createFile();
|
|
779
|
+
const file = (0, import_mp4box.createFile)();
|
|
3327
780
|
const sourceOption = options?.source ?? "camera";
|
|
3328
781
|
const loop = options?.loop ?? true;
|
|
3329
782
|
file.onError = (e) => {
|
|
@@ -3503,7 +956,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3503
956
|
playbackStartMs = null;
|
|
3504
957
|
frameQueue.length = 0;
|
|
3505
958
|
samplesReceived = 0;
|
|
3506
|
-
const loopFile = createFile();
|
|
959
|
+
const loopFile = (0, import_mp4box.createFile)();
|
|
3507
960
|
loopFile.onError = (e) => {
|
|
3508
961
|
this._playingVideo = false;
|
|
3509
962
|
this.emit("error", e);
|
|
@@ -3633,8 +1086,6 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3633
1086
|
file.start();
|
|
3634
1087
|
});
|
|
3635
1088
|
if (videoUrl && audioSource && audioTrack) {
|
|
3636
|
-
const { opus: prismOpus } = await import("prism-media");
|
|
3637
|
-
const { OpusDecoder } = await import("opus-decoder");
|
|
3638
1089
|
const runAudioFfmpeg = async () => {
|
|
3639
1090
|
if (!this._playingVideo || cleanupCalled || !audioSource) return;
|
|
3640
1091
|
const audioProc = (0, import_node_child_process.spawn)(
|
|
@@ -3656,9 +1107,9 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3656
1107
|
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
3657
1108
|
);
|
|
3658
1109
|
audioFfmpegProc = audioProc;
|
|
3659
|
-
const demuxer = new
|
|
1110
|
+
const demuxer = new import_prism_media2.opus.WebmDemuxer();
|
|
3660
1111
|
if (audioProc.stdout) audioProc.stdout.pipe(demuxer);
|
|
3661
|
-
const decoder2 = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
1112
|
+
const decoder2 = new import_opus_decoder.OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
3662
1113
|
await decoder2.ready;
|
|
3663
1114
|
let sampleBuffer = new Int16Array(0);
|
|
3664
1115
|
let opusBuffer = new Uint8Array(0);
|
|
@@ -3746,9 +1197,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3746
1197
|
let height = 480;
|
|
3747
1198
|
let hasAudio = false;
|
|
3748
1199
|
try {
|
|
3749
|
-
const
|
|
3750
|
-
const { promisify } = await import("util");
|
|
3751
|
-
const exec = promisify(execFile);
|
|
1200
|
+
const exec = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
3752
1201
|
const { stdout } = await exec(
|
|
3753
1202
|
"ffprobe",
|
|
3754
1203
|
[
|
|
@@ -4010,11 +1459,9 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
4010
1459
|
}
|
|
4011
1460
|
if (hasAudio && audioReady && audioSource && proc.stdio[3]) {
|
|
4012
1461
|
const audioPipe = proc.stdio[3];
|
|
4013
|
-
const
|
|
4014
|
-
const { OpusDecoder } = await import("opus-decoder");
|
|
4015
|
-
const demuxer = new prismOpus.WebmDemuxer();
|
|
1462
|
+
const demuxer = new import_prism_media2.opus.WebmDemuxer();
|
|
4016
1463
|
audioPipe.pipe(demuxer);
|
|
4017
|
-
const decoder = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
1464
|
+
const decoder = new import_opus_decoder.OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
4018
1465
|
await decoder.ready;
|
|
4019
1466
|
let sampleBuffer = new Int16Array(0);
|
|
4020
1467
|
let opusBuffer = new Uint8Array(0);
|
|
@@ -4094,16 +1541,13 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
4094
1541
|
this.emit("error", new Error("LiveKit: not connected"));
|
|
4095
1542
|
return;
|
|
4096
1543
|
}
|
|
4097
|
-
const { opus: prismOpus } = await import("prism-media");
|
|
4098
|
-
const { Readable } = await import("stream");
|
|
4099
|
-
const { OpusDecoder } = await import("opus-decoder");
|
|
4100
1544
|
let inputStream;
|
|
4101
1545
|
if (typeof urlOrStream === "string") {
|
|
4102
1546
|
try {
|
|
4103
1547
|
const response = await fetch(urlOrStream);
|
|
4104
1548
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
4105
1549
|
if (!response.body) throw new Error("No response body");
|
|
4106
|
-
inputStream = Readable.fromWeb(response.body);
|
|
1550
|
+
inputStream = import_node_stream2.Readable.fromWeb(response.body);
|
|
4107
1551
|
} catch (e) {
|
|
4108
1552
|
this.emit("error", e instanceof Error ? e : new Error(String(e)));
|
|
4109
1553
|
return;
|
|
@@ -4118,10 +1562,10 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
4118
1562
|
const options = new import_rtc_node.TrackPublishOptions();
|
|
4119
1563
|
options.source = import_rtc_node.TrackSource.SOURCE_MICROPHONE;
|
|
4120
1564
|
await this.room.localParticipant.publishTrack(track, options);
|
|
4121
|
-
const demuxer = new
|
|
1565
|
+
const demuxer = new import_prism_media2.opus.WebmDemuxer();
|
|
4122
1566
|
inputStream.pipe(demuxer);
|
|
4123
1567
|
this.currentStream = demuxer;
|
|
4124
|
-
const decoder = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
1568
|
+
const decoder = new import_opus_decoder.OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
4125
1569
|
await decoder.ready;
|
|
4126
1570
|
this._playing = true;
|
|
4127
1571
|
let sampleBuffer = new Int16Array(0);
|