krono-flow 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/decoder.js +15882 -0
- package/dist/decoder.js.map +1 -0
- package/dist/decoder.min.js +217 -0
- package/dist/decoder.min.js.map +1 -0
- package/dist/encoder.js +7002 -0
- package/dist/encoder.js.map +1 -0
- package/dist/encoder.min.js +121 -0
- package/dist/encoder.min.js.map +1 -0
- package/dist/index.js +38331 -0
- package/dist/index.js.map +1 -0
- package/dist/index.min.js +274 -0
- package/dist/index.min.js.map +1 -0
- package/dist/style.css +217 -0
- package/dist/style.css.map +1 -0
- package/dist/style.min.css +1 -0
- package/dist/style.min.css.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoder.min.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/misc.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/metadata.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/codec.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/muxer.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/codec-data.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/packet.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/matroska/ebml.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/subtitles.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/isobmff/isobmff-boxes.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/writer.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/target.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/isobmff/isobmff-muxer.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/isobmff/isobmff-misc.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/isobmff/isobmff-reader.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/matroska/matroska-muxer.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/matroska/matroska-misc.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/output-format.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/media-source.js","../node_modules/_mediabunny@1.25.1@mediabunny/dist/modules/src/output.js","../src/encoder.ts"],"sourcesContent":["/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\r\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n ownKeys = Object.getOwnPropertyNames || function (o) {\r\n var ar = [];\r\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n return ar;\r\n };\r\n return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose, inner;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n if (async) inner = dispose;\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n var r, s = 0;\r\n function next() {\r\n while (r = env.stack.pop()) {\r\n try {\r\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n if (r.dispose) {\r\n var result = r.dispose.call(r.value);\r\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n else s |= 1;\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n });\r\n }\r\n return path;\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __esDecorate: __esDecorate,\r\n __runInitializers: __runInitializers,\r\n __propKey: __propKey,\r\n __setFunctionName: __setFunctionName,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nexport function assert(x) {\n if (!x) {\n throw new Error('Assertion failed.');\n }\n}\nexport const normalizeRotation = (rotation) => {\n const mappedRotation = (rotation % 360 + 360) % 360;\n if (mappedRotation === 0 || mappedRotation === 90 || mappedRotation === 180 || mappedRotation === 270) {\n return mappedRotation;\n }\n else {\n throw new Error(`Invalid rotation ${rotation}.`);\n }\n};\nexport const last = (arr) => {\n return arr && arr[arr.length - 1];\n};\nexport const isU32 = (value) => {\n return value >= 0 && value < 2 ** 32;\n};\nexport class Bitstream {\n constructor(bytes) {\n this.bytes = bytes;\n /** Current offset in bits. */\n this.pos = 0;\n }\n seekToByte(byteOffset) {\n this.pos = 8 * byteOffset;\n }\n readBit() {\n const byteIndex = Math.floor(this.pos / 8);\n const byte = this.bytes[byteIndex] ?? 0;\n const bitIndex = 0b111 - (this.pos & 0b111);\n const bit = (byte & (1 << bitIndex)) >> bitIndex;\n this.pos++;\n return bit;\n }\n readBits(n) {\n if (n === 1) {\n return this.readBit();\n }\n let result = 0;\n for (let i = 0; i < n; i++) {\n result <<= 1;\n result |= this.readBit();\n }\n return result;\n }\n writeBits(n, value) {\n const end = this.pos + n;\n for (let i = this.pos; i < end; i++) {\n const byteIndex = Math.floor(i / 8);\n let byte = this.bytes[byteIndex];\n const bitIndex = 0b111 - (i & 0b111);\n byte &= ~(1 << bitIndex);\n byte |= ((value & (1 << (end - i - 1))) >> (end - i - 1)) << bitIndex;\n this.bytes[byteIndex] = byte;\n }\n this.pos = end;\n }\n ;\n readAlignedByte() {\n // Ensure we're byte-aligned\n if (this.pos % 8 !== 0) {\n throw new Error('Bitstream is not byte-aligned.');\n }\n const byteIndex = this.pos / 8;\n const byte = this.bytes[byteIndex] ?? 0;\n this.pos += 8;\n return byte;\n }\n skipBits(n) {\n this.pos += n;\n }\n getBitsLeft() {\n return this.bytes.length * 8 - this.pos;\n }\n clone() {\n const clone = new Bitstream(this.bytes);\n clone.pos = this.pos;\n return clone;\n }\n}\n/** Reads an exponential-Golomb universal code from a Bitstream. */\nexport const readExpGolomb = (bitstream) => {\n let leadingZeroBits = 0;\n while (bitstream.readBits(1) === 0 && leadingZeroBits < 32) {\n leadingZeroBits++;\n }\n if (leadingZeroBits >= 32) {\n throw new Error('Invalid exponential-Golomb code.');\n }\n const result = (1 << leadingZeroBits) - 1 + bitstream.readBits(leadingZeroBits);\n return result;\n};\n/** Reads a signed exponential-Golomb universal code from a Bitstream. */\nexport const readSignedExpGolomb = (bitstream) => {\n const codeNum = readExpGolomb(bitstream);\n return ((codeNum & 1) === 0)\n ? -(codeNum >> 1)\n : ((codeNum + 1) >> 1);\n};\nexport const writeBits = (bytes, start, end, value) => {\n for (let i = start; i < end; i++) {\n const byteIndex = Math.floor(i / 8);\n let byte = bytes[byteIndex];\n const bitIndex = 0b111 - (i & 0b111);\n byte &= ~(1 << bitIndex);\n byte |= ((value & (1 << (end - i - 1))) >> (end - i - 1)) << bitIndex;\n bytes[byteIndex] = byte;\n }\n};\nexport const toUint8Array = (source) => {\n if (source.constructor === Uint8Array) { // We want a true Uint8Array, not something that extends it like Buffer\n return source;\n }\n else if (source instanceof ArrayBuffer) {\n return new Uint8Array(source);\n }\n else {\n return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);\n }\n};\nexport const toDataView = (source) => {\n if (source.constructor === DataView) {\n return source;\n }\n else if (source instanceof ArrayBuffer) {\n return new DataView(source);\n }\n else {\n return new DataView(source.buffer, source.byteOffset, source.byteLength);\n }\n};\nexport const textDecoder = /* #__PURE__ */ new TextDecoder();\nexport const textEncoder = /* #__PURE__ */ new TextEncoder();\nexport const isIso88591Compatible = (text) => {\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n if (code > 255) {\n return false;\n }\n }\n return true;\n};\nconst invertObject = (object) => {\n return Object.fromEntries(Object.entries(object).map(([key, value]) => [value, key]));\n};\n// For the color space mappings, see Rec. ITU-T H.273.\nexport const COLOR_PRIMARIES_MAP = {\n bt709: 1, // ITU-R BT.709\n bt470bg: 5, // ITU-R BT.470BG\n smpte170m: 6, // ITU-R BT.601 525 - SMPTE 170M\n bt2020: 9, // ITU-R BT.202\n smpte432: 12, // SMPTE EG 432-1\n};\nexport const COLOR_PRIMARIES_MAP_INVERSE = /* #__PURE__ */ invertObject(COLOR_PRIMARIES_MAP);\nexport const TRANSFER_CHARACTERISTICS_MAP = {\n 'bt709': 1, // ITU-R BT.709\n 'smpte170m': 6, // SMPTE 170M\n 'linear': 8, // Linear transfer characteristics\n 'iec61966-2-1': 13, // IEC 61966-2-1\n 'pq': 16, // Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system\n 'hlg': 18, // Rec. ITU-R BT.2100-2 hybrid loggamma (HLG) system\n};\nexport const TRANSFER_CHARACTERISTICS_MAP_INVERSE = /* #__PURE__ */ invertObject(TRANSFER_CHARACTERISTICS_MAP);\nexport const MATRIX_COEFFICIENTS_MAP = {\n 'rgb': 0, // Identity\n 'bt709': 1, // ITU-R BT.709\n 'bt470bg': 5, // ITU-R BT.470BG\n 'smpte170m': 6, // SMPTE 170M\n 'bt2020-ncl': 9, // ITU-R BT.2020-2 (non-constant luminance)\n};\nexport const MATRIX_COEFFICIENTS_MAP_INVERSE = /* #__PURE__ */ invertObject(MATRIX_COEFFICIENTS_MAP);\nexport const colorSpaceIsComplete = (colorSpace) => {\n return (!!colorSpace\n && !!colorSpace.primaries\n && !!colorSpace.transfer\n && !!colorSpace.matrix\n && colorSpace.fullRange !== undefined);\n};\nexport const isAllowSharedBufferSource = (x) => {\n return (x instanceof ArrayBuffer\n || (typeof SharedArrayBuffer !== 'undefined' && x instanceof SharedArrayBuffer)\n || ArrayBuffer.isView(x));\n};\nexport class AsyncMutex {\n constructor() {\n this.currentPromise = Promise.resolve();\n }\n async acquire() {\n let resolver;\n const nextPromise = new Promise((resolve) => {\n resolver = resolve;\n });\n const currentPromiseAlias = this.currentPromise;\n this.currentPromise = nextPromise;\n await currentPromiseAlias;\n return resolver;\n }\n}\nexport const bytesToHexString = (bytes) => {\n return [...bytes].map(x => x.toString(16).padStart(2, '0')).join('');\n};\nexport const reverseBitsU32 = (x) => {\n x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);\n x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);\n x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);\n x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);\n x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);\n return x >>> 0; // Ensure it's treated as an unsigned 32-bit integer\n};\n/** Returns the smallest index i such that val[i] === key, or -1 if no such index exists. */\nexport const binarySearchExact = (arr, key, valueGetter) => {\n let low = 0;\n let high = arr.length - 1;\n let ans = -1;\n while (low <= high) {\n const mid = (low + high) >> 1;\n const midVal = valueGetter(arr[mid]);\n if (midVal === key) {\n ans = mid;\n high = mid - 1; // Continue searching left to find the lowest index\n }\n else if (midVal < key) {\n low = mid + 1;\n }\n else {\n high = mid - 1;\n }\n }\n return ans;\n};\n/** Returns the largest index i such that val[i] <= key, or -1 if no such index exists. */\nexport const binarySearchLessOrEqual = (arr, key, valueGetter) => {\n let low = 0;\n let high = arr.length - 1;\n let ans = -1;\n while (low <= high) {\n const mid = (low + (high - low + 1) / 2) | 0;\n const midVal = valueGetter(arr[mid]);\n if (midVal <= key) {\n ans = mid;\n low = mid + 1;\n }\n else {\n high = mid - 1;\n }\n }\n return ans;\n};\n/** Assumes the array is already sorted. */\nexport const insertSorted = (arr, item, valueGetter) => {\n const insertionIndex = binarySearchLessOrEqual(arr, valueGetter(item), valueGetter);\n arr.splice(insertionIndex + 1, 0, item); // This even behaves correctly for the -1 case\n};\nexport const promiseWithResolvers = () => {\n let resolve;\n let reject;\n const promise = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve: resolve, reject: reject };\n};\nexport const removeItem = (arr, item) => {\n const index = arr.indexOf(item);\n if (index !== -1) {\n arr.splice(index, 1);\n }\n};\nexport const findLast = (arr, predicate) => {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (predicate(arr[i])) {\n return arr[i];\n }\n }\n return undefined;\n};\nexport const findLastIndex = (arr, predicate) => {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (predicate(arr[i])) {\n return i;\n }\n }\n return -1;\n};\nexport const toAsyncIterator = async function* (source) {\n if (Symbol.iterator in source) {\n // @ts-expect-error Trust me\n yield* source[Symbol.iterator]();\n }\n else {\n // @ts-expect-error Trust me\n yield* source[Symbol.asyncIterator]();\n }\n};\nexport const validateAnyIterable = (iterable) => {\n if (!(Symbol.iterator in iterable) && !(Symbol.asyncIterator in iterable)) {\n throw new TypeError('Argument must be an iterable or async iterable.');\n }\n};\nexport const assertNever = (x) => {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new Error(`Unexpected value: ${x}`);\n};\nexport const getUint24 = (view, byteOffset, littleEndian) => {\n const byte1 = view.getUint8(byteOffset);\n const byte2 = view.getUint8(byteOffset + 1);\n const byte3 = view.getUint8(byteOffset + 2);\n if (littleEndian) {\n return byte1 | (byte2 << 8) | (byte3 << 16);\n }\n else {\n return (byte1 << 16) | (byte2 << 8) | byte3;\n }\n};\nexport const getInt24 = (view, byteOffset, littleEndian) => {\n // The left shift pushes the most significant bit into the sign bit region, and the subsequent right shift\n // then correctly interprets the sign bit.\n return getUint24(view, byteOffset, littleEndian) << 8 >> 8;\n};\nexport const setUint24 = (view, byteOffset, value, littleEndian) => {\n // Ensure the value is within 24-bit unsigned range (0 to 16777215)\n value = value >>> 0; // Convert to unsigned 32-bit\n value = value & 0xFFFFFF; // Mask to 24 bits\n if (littleEndian) {\n view.setUint8(byteOffset, value & 0xFF);\n view.setUint8(byteOffset + 1, (value >>> 8) & 0xFF);\n view.setUint8(byteOffset + 2, (value >>> 16) & 0xFF);\n }\n else {\n view.setUint8(byteOffset, (value >>> 16) & 0xFF);\n view.setUint8(byteOffset + 1, (value >>> 8) & 0xFF);\n view.setUint8(byteOffset + 2, value & 0xFF);\n }\n};\nexport const setInt24 = (view, byteOffset, value, littleEndian) => {\n // Ensure the value is within 24-bit signed range (-8388608 to 8388607)\n value = clamp(value, -8388608, 8388607);\n // Convert negative values to their 24-bit representation\n if (value < 0) {\n value = (value + 0x1000000) & 0xFFFFFF;\n }\n setUint24(view, byteOffset, value, littleEndian);\n};\nexport const setInt64 = (view, byteOffset, value, littleEndian) => {\n if (littleEndian) {\n view.setUint32(byteOffset + 0, value, true);\n view.setInt32(byteOffset + 4, Math.floor(value / 2 ** 32), true);\n }\n else {\n view.setInt32(byteOffset + 0, Math.floor(value / 2 ** 32), true);\n view.setUint32(byteOffset + 4, value, true);\n }\n};\n/**\n * Calls a function on each value spat out by an async generator. The reason for writing this manually instead of\n * using a generator function is that the generator function queues return() calls - here, we forward them immediately.\n */\nexport const mapAsyncGenerator = (generator, map) => {\n return {\n async next() {\n const result = await generator.next();\n if (result.done) {\n return { value: undefined, done: true };\n }\n else {\n return { value: map(result.value), done: false };\n }\n },\n return() {\n return generator.return();\n },\n throw(error) {\n return generator.throw(error);\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n};\nexport const clamp = (value, min, max) => {\n return Math.max(min, Math.min(max, value));\n};\nexport const UNDETERMINED_LANGUAGE = 'und';\nexport const roundIfAlmostInteger = (value) => {\n const rounded = Math.round(value);\n if (Math.abs(value / rounded - 1) < 10 * Number.EPSILON) {\n return rounded;\n }\n else {\n return value;\n }\n};\nexport const roundToMultiple = (value, multiple) => {\n return Math.round(value / multiple) * multiple;\n};\nexport const ilog = (x) => {\n let ret = 0;\n while (x) {\n ret++;\n x >>= 1;\n }\n return ret;\n};\nconst ISO_639_2_REGEX = /^[a-z]{3}$/;\nexport const isIso639Dash2LanguageCode = (x) => {\n return ISO_639_2_REGEX.test(x);\n};\n// Since the result will be truncated, add a bit of eps to compensate for floating point errors\nexport const SECOND_TO_MICROSECOND_FACTOR = 1e6 * (1 + Number.EPSILON);\n/**\n * Merges two RequestInit objects with special handling for headers.\n * Headers are merged case-insensitively, but original casing is preserved.\n * init2 headers take precedence and will override case-insensitive matches from init1.\n */\nexport const mergeRequestInit = (init1, init2) => {\n const merged = { ...init1, ...init2 };\n // Special handling for headers\n if (init1.headers || init2.headers) {\n const headers1 = init1.headers ? normalizeHeaders(init1.headers) : {};\n const headers2 = init2.headers ? normalizeHeaders(init2.headers) : {};\n const mergedHeaders = { ...headers1 };\n // For each header in headers2, check if a case-insensitive match exists in mergedHeaders\n Object.entries(headers2).forEach(([key2, value2]) => {\n const existingKey = Object.keys(mergedHeaders).find(key1 => key1.toLowerCase() === key2.toLowerCase());\n if (existingKey) {\n delete mergedHeaders[existingKey];\n }\n mergedHeaders[key2] = value2;\n });\n merged.headers = mergedHeaders;\n }\n return merged;\n};\n/** Normalizes HeadersInit to a Record<string, string> format. */\nconst normalizeHeaders = (headers) => {\n if (headers instanceof Headers) {\n const result = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n }\n if (Array.isArray(headers)) {\n const result = {};\n headers.forEach(([key, value]) => {\n result[key] = value;\n });\n return result;\n }\n return headers;\n};\nexport const retriedFetch = async (fetchFn, url, requestInit, getRetryDelay) => {\n let attempts = 0;\n while (true) {\n try {\n return await fetchFn(url, requestInit);\n }\n catch (error) {\n attempts++;\n const retryDelayInSeconds = getRetryDelay(attempts, error, url);\n if (retryDelayInSeconds === null) {\n throw error;\n }\n console.error('Retrying failed fetch. Error:', error);\n if (!Number.isFinite(retryDelayInSeconds) || retryDelayInSeconds < 0) {\n throw new TypeError('Retry delay must be a non-negative finite number.');\n }\n if (retryDelayInSeconds > 0) {\n await new Promise(resolve => setTimeout(resolve, 1000 * retryDelayInSeconds));\n }\n }\n }\n};\nexport const computeRationalApproximation = (x, maxDenominator) => {\n // Handle negative numbers\n const sign = x < 0 ? -1 : 1;\n x = Math.abs(x);\n let prevNumerator = 0, prevDenominator = 1;\n let currNumerator = 1, currDenominator = 0;\n // Continued fraction algorithm\n let remainder = x;\n while (true) {\n const integer = Math.floor(remainder);\n // Calculate next convergent\n const nextNumerator = integer * currNumerator + prevNumerator;\n const nextDenominator = integer * currDenominator + prevDenominator;\n if (nextDenominator > maxDenominator) {\n return {\n numerator: sign * currNumerator,\n denominator: currDenominator,\n };\n }\n prevNumerator = currNumerator;\n prevDenominator = currDenominator;\n currNumerator = nextNumerator;\n currDenominator = nextDenominator;\n remainder = 1 / (remainder - integer);\n // Guard against precision issues\n if (!isFinite(remainder)) {\n break;\n }\n }\n return {\n numerator: sign * currNumerator,\n denominator: currDenominator,\n };\n};\nexport class CallSerializer {\n constructor() {\n this.currentPromise = Promise.resolve();\n }\n call(fn) {\n return this.currentPromise = this.currentPromise.then(fn);\n }\n}\nlet isWebKitCache = null;\nexport const isWebKit = () => {\n if (isWebKitCache !== null) {\n return isWebKitCache;\n }\n // This even returns true for WebKit-wrapping browsers such as Chrome on iOS\n return isWebKitCache = !!(typeof navigator !== 'undefined' && navigator.vendor?.match(/apple/i));\n};\nlet isFirefoxCache = null;\nexport const isFirefox = () => {\n if (isFirefoxCache !== null) {\n return isFirefoxCache;\n }\n return isFirefoxCache = typeof navigator !== 'undefined' && navigator.userAgent?.includes('Firefox');\n};\nlet isChromiumCache = null;\nexport const isChromium = () => {\n if (isChromiumCache !== null) {\n return isChromiumCache;\n }\n return isChromiumCache = !!(typeof navigator !== 'undefined' && navigator.vendor?.includes('Google Inc'));\n};\n/** Acts like `??` except the condition is -1 and not null/undefined. */\nexport const coalesceIndex = (a, b) => {\n return a !== -1 ? a : b;\n};\nexport const closedIntervalsOverlap = (startA, endA, startB, endB) => {\n return startA <= endB && startB <= endA;\n};\nexport const keyValueIterator = function* (object) {\n for (const key in object) {\n const value = object[key];\n if (value === undefined) {\n continue;\n }\n yield { key, value };\n }\n};\nexport const imageMimeTypeToExtension = (mimeType) => {\n switch (mimeType.toLowerCase()) {\n case 'image/jpeg':\n case 'image/jpg':\n return '.jpg';\n case 'image/png':\n return '.png';\n case 'image/gif':\n return '.gif';\n case 'image/webp':\n return '.webp';\n case 'image/bmp':\n return '.bmp';\n case 'image/svg+xml':\n return '.svg';\n case 'image/tiff':\n return '.tiff';\n case 'image/avif':\n return '.avif';\n case 'image/x-icon':\n case 'image/vnd.microsoft.icon':\n return '.ico';\n default:\n return null;\n }\n};\nexport const base64ToBytes = (base64) => {\n const decoded = atob(base64);\n const bytes = new Uint8Array(decoded.length);\n for (let i = 0; i < decoded.length; i++) {\n bytes[i] = decoded.charCodeAt(i);\n }\n return bytes;\n};\nexport const bytesToBase64 = (bytes) => {\n let string = '';\n for (let i = 0; i < bytes.length; i++) {\n string += String.fromCharCode(bytes[i]);\n }\n return btoa(string);\n};\nexport const uint8ArraysAreEqual = (a, b) => {\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n};\nexport const polyfillSymbolDispose = () => {\n // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html\n // @ts-expect-error Readonly\n Symbol.dispose ??= Symbol('Symbol.dispose');\n};\nexport const isNumber = (x) => {\n return typeof x === 'number' && !Number.isNaN(x);\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n/**\n * Image data with additional metadata.\n *\n * @group Metadata tags\n * @public\n */\nexport class RichImageData {\n /** Creates a new {@link RichImageData}. */\n constructor(\n /** The raw image data. */\n data, \n /** An RFC 6838 MIME type (e.g. image/jpeg, image/png, etc.) */\n mimeType) {\n this.data = data;\n this.mimeType = mimeType;\n if (!(data instanceof Uint8Array)) {\n throw new TypeError('data must be a Uint8Array.');\n }\n if (typeof mimeType !== 'string') {\n throw new TypeError('mimeType must be a string.');\n }\n }\n}\n/**\n * A file attached to a media file.\n *\n * @group Metadata tags\n * @public\n */\nexport class AttachedFile {\n /** Creates a new {@link AttachedFile}. */\n constructor(\n /** The raw file data. */\n data, \n /** An RFC 6838 MIME type (e.g. image/jpeg, image/png, font/ttf, etc.) */\n mimeType, \n /** The name of the file. */\n name, \n /** A description of the file. */\n description) {\n this.data = data;\n this.mimeType = mimeType;\n this.name = name;\n this.description = description;\n if (!(data instanceof Uint8Array)) {\n throw new TypeError('data must be a Uint8Array.');\n }\n if (mimeType !== undefined && typeof mimeType !== 'string') {\n throw new TypeError('mimeType, when provided, must be a string.');\n }\n if (name !== undefined && typeof name !== 'string') {\n throw new TypeError('name, when provided, must be a string.');\n }\n if (description !== undefined && typeof description !== 'string') {\n throw new TypeError('description, when provided, must be a string.');\n }\n }\n}\n;\nexport const validateMetadataTags = (tags) => {\n if (!tags || typeof tags !== 'object') {\n throw new TypeError('tags must be an object.');\n }\n if (tags.title !== undefined && typeof tags.title !== 'string') {\n throw new TypeError('tags.title, when provided, must be a string.');\n }\n if (tags.description !== undefined && typeof tags.description !== 'string') {\n throw new TypeError('tags.description, when provided, must be a string.');\n }\n if (tags.artist !== undefined && typeof tags.artist !== 'string') {\n throw new TypeError('tags.artist, when provided, must be a string.');\n }\n if (tags.album !== undefined && typeof tags.album !== 'string') {\n throw new TypeError('tags.album, when provided, must be a string.');\n }\n if (tags.albumArtist !== undefined && typeof tags.albumArtist !== 'string') {\n throw new TypeError('tags.albumArtist, when provided, must be a string.');\n }\n if (tags.trackNumber !== undefined && (!Number.isInteger(tags.trackNumber) || tags.trackNumber <= 0)) {\n throw new TypeError('tags.trackNumber, when provided, must be a positive integer.');\n }\n if (tags.tracksTotal !== undefined\n && (!Number.isInteger(tags.tracksTotal) || tags.tracksTotal <= 0)) {\n throw new TypeError('tags.tracksTotal, when provided, must be a positive integer.');\n }\n if (tags.discNumber !== undefined && (!Number.isInteger(tags.discNumber) || tags.discNumber <= 0)) {\n throw new TypeError('tags.discNumber, when provided, must be a positive integer.');\n }\n if (tags.discsTotal !== undefined\n && (!Number.isInteger(tags.discsTotal) || tags.discsTotal <= 0)) {\n throw new TypeError('tags.discsTotal, when provided, must be a positive integer.');\n }\n if (tags.genre !== undefined && typeof tags.genre !== 'string') {\n throw new TypeError('tags.genre, when provided, must be a string.');\n }\n if (tags.date !== undefined && (!(tags.date instanceof Date) || Number.isNaN(tags.date.getTime()))) {\n throw new TypeError('tags.date, when provided, must be a valid Date.');\n }\n if (tags.lyrics !== undefined && typeof tags.lyrics !== 'string') {\n throw new TypeError('tags.lyrics, when provided, must be a string.');\n }\n if (tags.images !== undefined) {\n if (!Array.isArray(tags.images)) {\n throw new TypeError('tags.images, when provided, must be an array.');\n }\n for (const image of tags.images) {\n if (!image || typeof image !== 'object') {\n throw new TypeError('Each image in tags.images must be an object.');\n }\n if (!(image.data instanceof Uint8Array)) {\n throw new TypeError('Each image.data must be a Uint8Array.');\n }\n if (typeof image.mimeType !== 'string') {\n throw new TypeError('Each image.mimeType must be a string.');\n }\n if (!['coverFront', 'coverBack', 'unknown'].includes(image.kind)) {\n throw new TypeError('Each image.kind must be \\'coverFront\\', \\'coverBack\\', or \\'unknown\\'.');\n }\n }\n }\n if (tags.comment !== undefined && typeof tags.comment !== 'string') {\n throw new TypeError('tags.comment, when provided, must be a string.');\n }\n if (tags.raw !== undefined) {\n if (!tags.raw || typeof tags.raw !== 'object') {\n throw new TypeError('tags.raw, when provided, must be an object.');\n }\n for (const value of Object.values(tags.raw)) {\n if (value !== null\n && typeof value !== 'string'\n && !(value instanceof Uint8Array)\n && !(value instanceof RichImageData)\n && !(value instanceof AttachedFile)) {\n throw new TypeError('Each value in tags.raw must be a string, Uint8Array, RichImageData, AttachedFile, or null.');\n }\n }\n }\n};\nexport const metadataTagsAreEmpty = (tags) => {\n return tags.title === undefined\n && tags.description === undefined\n && tags.artist === undefined\n && tags.album === undefined\n && tags.albumArtist === undefined\n && tags.trackNumber === undefined\n && tags.tracksTotal === undefined\n && tags.discNumber === undefined\n && tags.discsTotal === undefined\n && tags.genre === undefined\n && tags.date === undefined\n && tags.lyrics === undefined\n && (!tags.images || tags.images.length === 0)\n && tags.comment === undefined\n && (tags.raw === undefined || Object.keys(tags.raw).length === 0);\n};\nexport const DEFAULT_TRACK_DISPOSITION = {\n default: true,\n forced: false,\n original: false,\n commentary: false,\n hearingImpaired: false,\n visuallyImpaired: false,\n};\nexport const validateTrackDisposition = (disposition) => {\n if (!disposition || typeof disposition !== 'object') {\n throw new TypeError('disposition must be an object.');\n }\n if (disposition.default !== undefined && typeof disposition.default !== 'boolean') {\n throw new TypeError('disposition.default must be a boolean.');\n }\n if (disposition.forced !== undefined && typeof disposition.forced !== 'boolean') {\n throw new TypeError('disposition.forced must be a boolean.');\n }\n if (disposition.original !== undefined && typeof disposition.original !== 'boolean') {\n throw new TypeError('disposition.original must be a boolean.');\n }\n if (disposition.commentary !== undefined && typeof disposition.commentary !== 'boolean') {\n throw new TypeError('disposition.commentary must be a boolean.');\n }\n if (disposition.hearingImpaired !== undefined && typeof disposition.hearingImpaired !== 'boolean') {\n throw new TypeError('disposition.hearingImpaired must be a boolean.');\n }\n if (disposition.visuallyImpaired !== undefined && typeof disposition.visuallyImpaired !== 'boolean') {\n throw new TypeError('disposition.visuallyImpaired must be a boolean.');\n }\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { Bitstream, COLOR_PRIMARIES_MAP, MATRIX_COEFFICIENTS_MAP, TRANSFER_CHARACTERISTICS_MAP, assert, bytesToHexString, isAllowSharedBufferSource, last, reverseBitsU32, toDataView, } from './misc.js';\n/**\n * List of known video codecs, ordered by encoding preference.\n * @group Codecs\n * @public\n */\nexport const VIDEO_CODECS = [\n 'avc',\n 'hevc',\n 'vp9',\n 'av1',\n 'vp8',\n];\n/**\n * List of known PCM (uncompressed) audio codecs, ordered by encoding preference.\n * @group Codecs\n * @public\n */\nexport const PCM_AUDIO_CODECS = [\n 'pcm-s16', // We don't prefix 'le' so we're compatible with the WebCodecs-registered PCM codec strings\n 'pcm-s16be',\n 'pcm-s24',\n 'pcm-s24be',\n 'pcm-s32',\n 'pcm-s32be',\n 'pcm-f32',\n 'pcm-f32be',\n 'pcm-f64',\n 'pcm-f64be',\n 'pcm-u8',\n 'pcm-s8',\n 'ulaw',\n 'alaw',\n];\n/**\n * List of known compressed audio codecs, ordered by encoding preference.\n * @group Codecs\n * @public\n */\nexport const NON_PCM_AUDIO_CODECS = [\n 'aac',\n 'opus',\n 'mp3',\n 'vorbis',\n 'flac',\n];\n/**\n * List of known audio codecs, ordered by encoding preference.\n * @group Codecs\n * @public\n */\nexport const AUDIO_CODECS = [\n ...NON_PCM_AUDIO_CODECS,\n ...PCM_AUDIO_CODECS,\n];\n/**\n * List of known subtitle codecs, ordered by encoding preference.\n * @group Codecs\n * @public\n */\nexport const SUBTITLE_CODECS = [\n 'webvtt',\n]; // TODO add the rest\n// https://en.wikipedia.org/wiki/Advanced_Video_Coding\nconst AVC_LEVEL_TABLE = [\n { maxMacroblocks: 99, maxBitrate: 64000, level: 0x0A }, // Level 1\n { maxMacroblocks: 396, maxBitrate: 192000, level: 0x0B }, // Level 1.1\n { maxMacroblocks: 396, maxBitrate: 384000, level: 0x0C }, // Level 1.2\n { maxMacroblocks: 396, maxBitrate: 768000, level: 0x0D }, // Level 1.3\n { maxMacroblocks: 396, maxBitrate: 2000000, level: 0x14 }, // Level 2\n { maxMacroblocks: 792, maxBitrate: 4000000, level: 0x15 }, // Level 2.1\n { maxMacroblocks: 1620, maxBitrate: 4000000, level: 0x16 }, // Level 2.2\n { maxMacroblocks: 1620, maxBitrate: 10000000, level: 0x1E }, // Level 3\n { maxMacroblocks: 3600, maxBitrate: 14000000, level: 0x1F }, // Level 3.1\n { maxMacroblocks: 5120, maxBitrate: 20000000, level: 0x20 }, // Level 3.2\n { maxMacroblocks: 8192, maxBitrate: 20000000, level: 0x28 }, // Level 4\n { maxMacroblocks: 8192, maxBitrate: 50000000, level: 0x29 }, // Level 4.1\n { maxMacroblocks: 8704, maxBitrate: 50000000, level: 0x2A }, // Level 4.2\n { maxMacroblocks: 22080, maxBitrate: 135000000, level: 0x32 }, // Level 5\n { maxMacroblocks: 36864, maxBitrate: 240000000, level: 0x33 }, // Level 5.1\n { maxMacroblocks: 36864, maxBitrate: 240000000, level: 0x34 }, // Level 5.2\n { maxMacroblocks: 139264, maxBitrate: 240000000, level: 0x3C }, // Level 6\n { maxMacroblocks: 139264, maxBitrate: 480000000, level: 0x3D }, // Level 6.1\n { maxMacroblocks: 139264, maxBitrate: 800000000, level: 0x3E }, // Level 6.2\n];\n// https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding\nconst HEVC_LEVEL_TABLE = [\n { maxPictureSize: 36864, maxBitrate: 128000, tier: 'L', level: 30 }, // Level 1 (Low Tier)\n { maxPictureSize: 122880, maxBitrate: 1500000, tier: 'L', level: 60 }, // Level 2 (Low Tier)\n { maxPictureSize: 245760, maxBitrate: 3000000, tier: 'L', level: 63 }, // Level 2.1 (Low Tier)\n { maxPictureSize: 552960, maxBitrate: 6000000, tier: 'L', level: 90 }, // Level 3 (Low Tier)\n { maxPictureSize: 983040, maxBitrate: 10000000, tier: 'L', level: 93 }, // Level 3.1 (Low Tier)\n { maxPictureSize: 2228224, maxBitrate: 12000000, tier: 'L', level: 120 }, // Level 4 (Low Tier)\n { maxPictureSize: 2228224, maxBitrate: 30000000, tier: 'H', level: 120 }, // Level 4 (High Tier)\n { maxPictureSize: 2228224, maxBitrate: 20000000, tier: 'L', level: 123 }, // Level 4.1 (Low Tier)\n { maxPictureSize: 2228224, maxBitrate: 50000000, tier: 'H', level: 123 }, // Level 4.1 (High Tier)\n { maxPictureSize: 8912896, maxBitrate: 25000000, tier: 'L', level: 150 }, // Level 5 (Low Tier)\n { maxPictureSize: 8912896, maxBitrate: 100000000, tier: 'H', level: 150 }, // Level 5 (High Tier)\n { maxPictureSize: 8912896, maxBitrate: 40000000, tier: 'L', level: 153 }, // Level 5.1 (Low Tier)\n { maxPictureSize: 8912896, maxBitrate: 160000000, tier: 'H', level: 153 }, // Level 5.1 (High Tier)\n { maxPictureSize: 8912896, maxBitrate: 60000000, tier: 'L', level: 156 }, // Level 5.2 (Low Tier)\n { maxPictureSize: 8912896, maxBitrate: 240000000, tier: 'H', level: 156 }, // Level 5.2 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 60000000, tier: 'L', level: 180 }, // Level 6 (Low Tier)\n { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'H', level: 180 }, // Level 6 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 120000000, tier: 'L', level: 183 }, // Level 6.1 (Low Tier)\n { maxPictureSize: 35651584, maxBitrate: 480000000, tier: 'H', level: 183 }, // Level 6.1 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'L', level: 186 }, // Level 6.2 (Low Tier)\n { maxPictureSize: 35651584, maxBitrate: 800000000, tier: 'H', level: 186 }, // Level 6.2 (High Tier)\n];\n// https://en.wikipedia.org/wiki/VP9\nexport const VP9_LEVEL_TABLE = [\n { maxPictureSize: 36864, maxBitrate: 200000, level: 10 }, // Level 1\n { maxPictureSize: 73728, maxBitrate: 800000, level: 11 }, // Level 1.1\n { maxPictureSize: 122880, maxBitrate: 1800000, level: 20 }, // Level 2\n { maxPictureSize: 245760, maxBitrate: 3600000, level: 21 }, // Level 2.1\n { maxPictureSize: 552960, maxBitrate: 7200000, level: 30 }, // Level 3\n { maxPictureSize: 983040, maxBitrate: 12000000, level: 31 }, // Level 3.1\n { maxPictureSize: 2228224, maxBitrate: 18000000, level: 40 }, // Level 4\n { maxPictureSize: 2228224, maxBitrate: 30000000, level: 41 }, // Level 4.1\n { maxPictureSize: 8912896, maxBitrate: 60000000, level: 50 }, // Level 5\n { maxPictureSize: 8912896, maxBitrate: 120000000, level: 51 }, // Level 5.1\n { maxPictureSize: 8912896, maxBitrate: 180000000, level: 52 }, // Level 5.2\n { maxPictureSize: 35651584, maxBitrate: 180000000, level: 60 }, // Level 6\n { maxPictureSize: 35651584, maxBitrate: 240000000, level: 61 }, // Level 6.1\n { maxPictureSize: 35651584, maxBitrate: 480000000, level: 62 }, // Level 6.2\n];\n// https://en.wikipedia.org/wiki/AV1\nconst AV1_LEVEL_TABLE = [\n { maxPictureSize: 147456, maxBitrate: 1500000, tier: 'M', level: 0 }, // Level 2.0 (Main Tier)\n { maxPictureSize: 278784, maxBitrate: 3000000, tier: 'M', level: 1 }, // Level 2.1 (Main Tier)\n { maxPictureSize: 665856, maxBitrate: 6000000, tier: 'M', level: 4 }, // Level 3.0 (Main Tier)\n { maxPictureSize: 1065024, maxBitrate: 10000000, tier: 'M', level: 5 }, // Level 3.1 (Main Tier)\n { maxPictureSize: 2359296, maxBitrate: 12000000, tier: 'M', level: 8 }, // Level 4.0 (Main Tier)\n { maxPictureSize: 2359296, maxBitrate: 30000000, tier: 'H', level: 8 }, // Level 4.0 (High Tier)\n { maxPictureSize: 2359296, maxBitrate: 20000000, tier: 'M', level: 9 }, // Level 4.1 (Main Tier)\n { maxPictureSize: 2359296, maxBitrate: 50000000, tier: 'H', level: 9 }, // Level 4.1 (High Tier)\n { maxPictureSize: 8912896, maxBitrate: 30000000, tier: 'M', level: 12 }, // Level 5.0 (Main Tier)\n { maxPictureSize: 8912896, maxBitrate: 100000000, tier: 'H', level: 12 }, // Level 5.0 (High Tier)\n { maxPictureSize: 8912896, maxBitrate: 40000000, tier: 'M', level: 13 }, // Level 5.1 (Main Tier)\n { maxPictureSize: 8912896, maxBitrate: 160000000, tier: 'H', level: 13 }, // Level 5.1 (High Tier)\n { maxPictureSize: 8912896, maxBitrate: 60000000, tier: 'M', level: 14 }, // Level 5.2 (Main Tier)\n { maxPictureSize: 8912896, maxBitrate: 240000000, tier: 'H', level: 14 }, // Level 5.2 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 60000000, tier: 'M', level: 15 }, // Level 5.3 (Main Tier)\n { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'H', level: 15 }, // Level 5.3 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 60000000, tier: 'M', level: 16 }, // Level 6.0 (Main Tier)\n { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'H', level: 16 }, // Level 6.0 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 100000000, tier: 'M', level: 17 }, // Level 6.1 (Main Tier)\n { maxPictureSize: 35651584, maxBitrate: 480000000, tier: 'H', level: 17 }, // Level 6.1 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 160000000, tier: 'M', level: 18 }, // Level 6.2 (Main Tier)\n { maxPictureSize: 35651584, maxBitrate: 800000000, tier: 'H', level: 18 }, // Level 6.2 (High Tier)\n { maxPictureSize: 35651584, maxBitrate: 160000000, tier: 'M', level: 19 }, // Level 6.3 (Main Tier)\n { maxPictureSize: 35651584, maxBitrate: 800000000, tier: 'H', level: 19 }, // Level 6.3 (High Tier)\n];\nconst VP9_DEFAULT_SUFFIX = '.01.01.01.01.00';\nconst AV1_DEFAULT_SUFFIX = '.0.110.01.01.01.0';\nexport const buildVideoCodecString = (codec, width, height, bitrate) => {\n if (codec === 'avc') {\n const profileIndication = 0x64; // High Profile\n const totalMacroblocks = Math.ceil(width / 16) * Math.ceil(height / 16);\n // Determine the level based on the table\n const levelInfo = AVC_LEVEL_TABLE.find(level => totalMacroblocks <= level.maxMacroblocks && bitrate <= level.maxBitrate) ?? last(AVC_LEVEL_TABLE);\n const levelIndication = levelInfo ? levelInfo.level : 0;\n const hexProfileIndication = profileIndication.toString(16).padStart(2, '0');\n const hexProfileCompatibility = '00';\n const hexLevelIndication = levelIndication.toString(16).padStart(2, '0');\n return `avc1.${hexProfileIndication}${hexProfileCompatibility}${hexLevelIndication}`;\n }\n else if (codec === 'hevc') {\n const profilePrefix = ''; // Profile space 0\n const profileIdc = 1; // Main Profile\n const compatibilityFlags = '6'; // Taken from the example in ISO 14496-15\n const pictureSize = width * height;\n const levelInfo = HEVC_LEVEL_TABLE.find(level => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate) ?? last(HEVC_LEVEL_TABLE);\n const constraintFlags = 'B0'; // Progressive source flag\n return 'hev1.'\n + `${profilePrefix}${profileIdc}.`\n + `${compatibilityFlags}.`\n + `${levelInfo.tier}${levelInfo.level}.`\n + `${constraintFlags}`;\n }\n else if (codec === 'vp8') {\n return 'vp8'; // Easy, this one\n }\n else if (codec === 'vp9') {\n const profile = '00'; // Profile 0\n const pictureSize = width * height;\n const levelInfo = VP9_LEVEL_TABLE.find(level => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate) ?? last(VP9_LEVEL_TABLE);\n const bitDepth = '08'; // 8-bit\n return `vp09.${profile}.${levelInfo.level.toString().padStart(2, '0')}.${bitDepth}`;\n }\n else if (codec === 'av1') {\n const profile = 0; // Main Profile, single digit\n const pictureSize = width * height;\n const levelInfo = AV1_LEVEL_TABLE.find(level => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate) ?? last(AV1_LEVEL_TABLE);\n const level = levelInfo.level.toString().padStart(2, '0');\n const bitDepth = '08'; // 8-bit\n return `av01.${profile}.${level}${levelInfo.tier}.${bitDepth}`;\n }\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new TypeError(`Unhandled codec '${codec}'.`);\n};\nexport const generateVp9CodecConfigurationFromCodecString = (codecString) => {\n // Reference: https://www.webmproject.org/docs/container/#vp9-codec-feature-metadata-codecprivate\n const parts = codecString.split('.'); // We can derive the required values from the codec string\n const profile = Number(parts[1]);\n const level = Number(parts[2]);\n const bitDepth = Number(parts[3]);\n const chromaSubsampling = parts[4] ? Number(parts[4]) : 1;\n return [\n 1, 1, profile,\n 2, 1, level,\n 3, 1, bitDepth,\n 4, 1, chromaSubsampling,\n ];\n};\nexport const generateAv1CodecConfigurationFromCodecString = (codecString) => {\n // Reference: https://aomediacodec.github.io/av1-isobmff/\n const parts = codecString.split('.'); // We can derive the required values from the codec string\n const marker = 1;\n const version = 1;\n const firstByte = (marker << 7) + version;\n const profile = Number(parts[1]);\n const levelAndTier = parts[2];\n const level = Number(levelAndTier.slice(0, -1));\n const secondByte = (profile << 5) + level;\n const tier = levelAndTier.slice(-1) === 'H' ? 1 : 0;\n const bitDepth = Number(parts[3]);\n const highBitDepth = bitDepth === 8 ? 0 : 1;\n const twelveBit = 0;\n const monochrome = parts[4] ? Number(parts[4]) : 0;\n const chromaSubsamplingX = parts[5] ? Number(parts[5][0]) : 1;\n const chromaSubsamplingY = parts[5] ? Number(parts[5][1]) : 1;\n const chromaSamplePosition = parts[5] ? Number(parts[5][2]) : 0; // CSP_UNKNOWN\n const thirdByte = (tier << 7)\n + (highBitDepth << 6)\n + (twelveBit << 5)\n + (monochrome << 4)\n + (chromaSubsamplingX << 3)\n + (chromaSubsamplingY << 2)\n + chromaSamplePosition;\n const initialPresentationDelayPresent = 0; // Should be fine\n const fourthByte = initialPresentationDelayPresent;\n return [firstByte, secondByte, thirdByte, fourthByte];\n};\nexport const extractVideoCodecString = (trackInfo) => {\n const { codec, codecDescription, colorSpace, avcCodecInfo, hevcCodecInfo, vp9CodecInfo, av1CodecInfo } = trackInfo;\n if (codec === 'avc') {\n assert(trackInfo.avcType !== null);\n if (avcCodecInfo) {\n const bytes = new Uint8Array([\n avcCodecInfo.avcProfileIndication,\n avcCodecInfo.profileCompatibility,\n avcCodecInfo.avcLevelIndication,\n ]);\n return `avc${trackInfo.avcType}.${bytesToHexString(bytes)}`;\n }\n if (!codecDescription || codecDescription.byteLength < 4) {\n throw new TypeError('AVC decoder description is not provided or is not at least 4 bytes long.');\n }\n return `avc${trackInfo.avcType}.${bytesToHexString(codecDescription.subarray(1, 4))}`;\n }\n else if (codec === 'hevc') {\n let generalProfileSpace;\n let generalProfileIdc;\n let compatibilityFlags;\n let generalTierFlag;\n let generalLevelIdc;\n let constraintFlags;\n if (hevcCodecInfo) {\n generalProfileSpace = hevcCodecInfo.generalProfileSpace;\n generalProfileIdc = hevcCodecInfo.generalProfileIdc;\n compatibilityFlags = reverseBitsU32(hevcCodecInfo.generalProfileCompatibilityFlags);\n generalTierFlag = hevcCodecInfo.generalTierFlag;\n generalLevelIdc = hevcCodecInfo.generalLevelIdc;\n constraintFlags = [...hevcCodecInfo.generalConstraintIndicatorFlags];\n }\n else {\n if (!codecDescription || codecDescription.byteLength < 23) {\n throw new TypeError('HEVC decoder description is not provided or is not at least 23 bytes long.');\n }\n const view = toDataView(codecDescription);\n const profileByte = view.getUint8(1);\n generalProfileSpace = (profileByte >> 6) & 0x03;\n generalProfileIdc = profileByte & 0x1F;\n compatibilityFlags = reverseBitsU32(view.getUint32(2));\n generalTierFlag = (profileByte >> 5) & 0x01;\n generalLevelIdc = view.getUint8(12);\n constraintFlags = [];\n for (let i = 0; i < 6; i++) {\n constraintFlags.push(view.getUint8(6 + i));\n }\n }\n let codecString = 'hev1.';\n codecString += ['', 'A', 'B', 'C'][generalProfileSpace] + generalProfileIdc;\n codecString += '.';\n codecString += compatibilityFlags.toString(16).toUpperCase();\n codecString += '.';\n codecString += generalTierFlag === 0 ? 'L' : 'H';\n codecString += generalLevelIdc;\n while (constraintFlags.length > 0 && constraintFlags[constraintFlags.length - 1] === 0) {\n constraintFlags.pop();\n }\n if (constraintFlags.length > 0) {\n codecString += '.';\n codecString += constraintFlags.map(x => x.toString(16).toUpperCase()).join('.');\n }\n return codecString;\n }\n else if (codec === 'vp8') {\n return 'vp8'; // Easy, this one\n }\n else if (codec === 'vp9') {\n if (!vp9CodecInfo) {\n // Calculate level based on dimensions\n const pictureSize = trackInfo.width * trackInfo.height;\n let level = last(VP9_LEVEL_TABLE).level; // Default to highest level\n for (const entry of VP9_LEVEL_TABLE) {\n if (pictureSize <= entry.maxPictureSize) {\n level = entry.level;\n break;\n }\n }\n // We don't really know better, so let's return a general-purpose, common codec string and hope for the best\n return `vp09.00.${level.toString().padStart(2, '0')}.08`;\n }\n const profile = vp9CodecInfo.profile.toString().padStart(2, '0');\n const level = vp9CodecInfo.level.toString().padStart(2, '0');\n const bitDepth = vp9CodecInfo.bitDepth.toString().padStart(2, '0');\n const chromaSubsampling = vp9CodecInfo.chromaSubsampling.toString().padStart(2, '0');\n const colourPrimaries = vp9CodecInfo.colourPrimaries.toString().padStart(2, '0');\n const transferCharacteristics = vp9CodecInfo.transferCharacteristics.toString().padStart(2, '0');\n const matrixCoefficients = vp9CodecInfo.matrixCoefficients.toString().padStart(2, '0');\n const videoFullRangeFlag = vp9CodecInfo.videoFullRangeFlag.toString().padStart(2, '0');\n let string = `vp09.${profile}.${level}.${bitDepth}.${chromaSubsampling}`;\n string += `.${colourPrimaries}.${transferCharacteristics}.${matrixCoefficients}.${videoFullRangeFlag}`;\n if (string.endsWith(VP9_DEFAULT_SUFFIX)) {\n string = string.slice(0, -VP9_DEFAULT_SUFFIX.length);\n }\n return string;\n }\n else if (codec === 'av1') {\n if (!av1CodecInfo) {\n // Calculate level based on dimensions\n const pictureSize = trackInfo.width * trackInfo.height;\n let level = last(VP9_LEVEL_TABLE).level; // Default to highest level\n for (const entry of VP9_LEVEL_TABLE) {\n if (pictureSize <= entry.maxPictureSize) {\n level = entry.level;\n break;\n }\n }\n // We don't really know better, so let's return a general-purpose, common codec string and hope for the best\n return `av01.0.${level.toString().padStart(2, '0')}M.08`;\n }\n // https://aomediacodec.github.io/av1-isobmff/#codecsparam\n const profile = av1CodecInfo.profile; // Single digit\n const level = av1CodecInfo.level.toString().padStart(2, '0');\n const tier = av1CodecInfo.tier ? 'H' : 'M';\n const bitDepth = av1CodecInfo.bitDepth.toString().padStart(2, '0');\n const monochrome = av1CodecInfo.monochrome ? '1' : '0';\n const chromaSubsampling = 100 * av1CodecInfo.chromaSubsamplingX\n + 10 * av1CodecInfo.chromaSubsamplingY\n + 1 * (av1CodecInfo.chromaSubsamplingX && av1CodecInfo.chromaSubsamplingY\n ? av1CodecInfo.chromaSamplePosition\n : 0);\n // The defaults are 1 (ITU-R BT.709)\n const colorPrimaries = colorSpace?.primaries ? COLOR_PRIMARIES_MAP[colorSpace.primaries] : 1;\n const transferCharacteristics = colorSpace?.transfer ? TRANSFER_CHARACTERISTICS_MAP[colorSpace.transfer] : 1;\n const matrixCoefficients = colorSpace?.matrix ? MATRIX_COEFFICIENTS_MAP[colorSpace.matrix] : 1;\n const videoFullRangeFlag = colorSpace?.fullRange ? 1 : 0;\n let string = `av01.${profile}.${level}${tier}.${bitDepth}`;\n string += `.${monochrome}.${chromaSubsampling.toString().padStart(3, '0')}`;\n string += `.${colorPrimaries.toString().padStart(2, '0')}`;\n string += `.${transferCharacteristics.toString().padStart(2, '0')}`;\n string += `.${matrixCoefficients.toString().padStart(2, '0')}`;\n string += `.${videoFullRangeFlag}`;\n if (string.endsWith(AV1_DEFAULT_SUFFIX)) {\n string = string.slice(0, -AV1_DEFAULT_SUFFIX.length);\n }\n return string;\n }\n throw new TypeError(`Unhandled codec '${codec}'.`);\n};\nexport const buildAudioCodecString = (codec, numberOfChannels, sampleRate) => {\n if (codec === 'aac') {\n // If stereo or higher channels and lower sample rate, likely using HE-AAC v2 with PS\n if (numberOfChannels >= 2 && sampleRate <= 24000) {\n return 'mp4a.40.29'; // HE-AAC v2 (AAC LC + SBR + PS)\n }\n // If sample rate is low, likely using HE-AAC v1 with SBR\n if (sampleRate <= 24000) {\n return 'mp4a.40.5'; // HE-AAC v1 (AAC LC + SBR)\n }\n // Default to standard AAC-LC for higher sample rates\n return 'mp4a.40.2'; // AAC-LC\n }\n else if (codec === 'mp3') {\n return 'mp3';\n }\n else if (codec === 'opus') {\n return 'opus';\n }\n else if (codec === 'vorbis') {\n return 'vorbis';\n }\n else if (codec === 'flac') {\n return 'flac';\n }\n else if (PCM_AUDIO_CODECS.includes(codec)) {\n return codec;\n }\n throw new TypeError(`Unhandled codec '${codec}'.`);\n};\nexport const extractAudioCodecString = (trackInfo) => {\n const { codec, codecDescription, aacCodecInfo } = trackInfo;\n if (codec === 'aac') {\n if (!aacCodecInfo) {\n throw new TypeError('AAC codec info must be provided.');\n }\n if (aacCodecInfo.isMpeg2) {\n return 'mp4a.67';\n }\n else {\n const audioSpecificConfig = parseAacAudioSpecificConfig(codecDescription);\n return `mp4a.40.${audioSpecificConfig.objectType}`;\n }\n }\n else if (codec === 'mp3') {\n return 'mp3';\n }\n else if (codec === 'opus') {\n return 'opus';\n }\n else if (codec === 'vorbis') {\n return 'vorbis';\n }\n else if (codec === 'flac') {\n return 'flac';\n }\n else if (codec && PCM_AUDIO_CODECS.includes(codec)) {\n return codec;\n }\n throw new TypeError(`Unhandled codec '${codec}'.`);\n};\nexport const aacFrequencyTable = [\n 96000, 88200, 64000, 48000, 44100, 32000,\n 24000, 22050, 16000, 12000, 11025, 8000, 7350,\n];\nexport const aacChannelMap = [-1, 1, 2, 3, 4, 5, 6, 8];\nexport const parseAacAudioSpecificConfig = (bytes) => {\n if (!bytes || bytes.byteLength < 2) {\n throw new TypeError('AAC description must be at least 2 bytes long.');\n }\n const bitstream = new Bitstream(bytes);\n let objectType = bitstream.readBits(5);\n if (objectType === 31) {\n objectType = 32 + bitstream.readBits(6);\n }\n const frequencyIndex = bitstream.readBits(4);\n let sampleRate = null;\n if (frequencyIndex === 15) {\n sampleRate = bitstream.readBits(24);\n }\n else {\n if (frequencyIndex < aacFrequencyTable.length) {\n sampleRate = aacFrequencyTable[frequencyIndex];\n }\n }\n const channelConfiguration = bitstream.readBits(4);\n let numberOfChannels = null;\n if (channelConfiguration >= 1 && channelConfiguration <= 7) {\n numberOfChannels = aacChannelMap[channelConfiguration];\n }\n return {\n objectType,\n frequencyIndex,\n sampleRate,\n channelConfiguration,\n numberOfChannels,\n };\n};\nexport const buildAacAudioSpecificConfig = (config) => {\n let frequencyIndex = aacFrequencyTable.indexOf(config.sampleRate);\n let customSampleRate = null;\n if (frequencyIndex === -1) {\n frequencyIndex = 15;\n customSampleRate = config.sampleRate;\n }\n const channelConfiguration = aacChannelMap.indexOf(config.numberOfChannels);\n if (channelConfiguration === -1) {\n throw new TypeError(`Unsupported number of channels: ${config.numberOfChannels}`);\n }\n let bitCount = 5 + 4 + 4;\n if (config.objectType >= 32) {\n bitCount += 6;\n }\n if (frequencyIndex === 15) {\n bitCount += 24;\n }\n const byteCount = Math.ceil(bitCount / 8);\n const bytes = new Uint8Array(byteCount);\n const bitstream = new Bitstream(bytes);\n if (config.objectType < 32) {\n bitstream.writeBits(5, config.objectType);\n }\n else {\n bitstream.writeBits(5, 31);\n bitstream.writeBits(6, config.objectType - 32);\n }\n bitstream.writeBits(4, frequencyIndex);\n if (frequencyIndex === 15) {\n bitstream.writeBits(24, customSampleRate);\n }\n bitstream.writeBits(4, channelConfiguration);\n return bytes;\n};\nexport const OPUS_SAMPLE_RATE = 48_000;\nconst PCM_CODEC_REGEX = /^pcm-([usf])(\\d+)+(be)?$/;\nexport const parsePcmCodec = (codec) => {\n assert(PCM_AUDIO_CODECS.includes(codec));\n if (codec === 'ulaw') {\n return { dataType: 'ulaw', sampleSize: 1, littleEndian: true, silentValue: 255 };\n }\n else if (codec === 'alaw') {\n return { dataType: 'alaw', sampleSize: 1, littleEndian: true, silentValue: 213 };\n }\n const match = PCM_CODEC_REGEX.exec(codec);\n assert(match);\n let dataType;\n if (match[1] === 'u') {\n dataType = 'unsigned';\n }\n else if (match[1] === 's') {\n dataType = 'signed';\n }\n else {\n dataType = 'float';\n }\n const sampleSize = (Number(match[2]) / 8);\n const littleEndian = match[3] !== 'be';\n const silentValue = codec === 'pcm-u8' ? 2 ** 7 : 0;\n return { dataType, sampleSize, littleEndian, silentValue };\n};\nexport const inferCodecFromCodecString = (codecString) => {\n // Video codecs\n if (codecString.startsWith('avc1') || codecString.startsWith('avc3')) {\n return 'avc';\n }\n else if (codecString.startsWith('hev1') || codecString.startsWith('hvc1')) {\n return 'hevc';\n }\n else if (codecString === 'vp8') {\n return 'vp8';\n }\n else if (codecString.startsWith('vp09')) {\n return 'vp9';\n }\n else if (codecString.startsWith('av01')) {\n return 'av1';\n }\n // Audio codecs\n if (codecString.startsWith('mp4a.40') || codecString === 'mp4a.67') {\n return 'aac';\n }\n else if (codecString === 'mp3'\n || codecString === 'mp4a.69'\n || codecString === 'mp4a.6B'\n || codecString === 'mp4a.6b') {\n return 'mp3';\n }\n else if (codecString === 'opus') {\n return 'opus';\n }\n else if (codecString === 'vorbis') {\n return 'vorbis';\n }\n else if (codecString === 'flac') {\n return 'flac';\n }\n else if (codecString === 'ulaw') {\n return 'ulaw';\n }\n else if (codecString === 'alaw') {\n return 'alaw';\n }\n else if (PCM_CODEC_REGEX.test(codecString)) {\n return codecString;\n }\n // Subtitle codecs\n if (codecString === 'webvtt') {\n return 'webvtt';\n }\n return null;\n};\nexport const getVideoEncoderConfigExtension = (codec) => {\n if (codec === 'avc') {\n return {\n avc: {\n format: 'avc', // Ensure the format is not Annex B\n },\n };\n }\n else if (codec === 'hevc') {\n return {\n hevc: {\n format: 'hevc', // Ensure the format is not Annex B\n },\n };\n }\n return {};\n};\nexport const getAudioEncoderConfigExtension = (codec) => {\n if (codec === 'aac') {\n return {\n aac: {\n format: 'aac', // Ensure the format is not ADTS\n },\n };\n }\n else if (codec === 'opus') {\n return {\n opus: {\n format: 'opus',\n },\n };\n }\n return {};\n};\nconst VALID_VIDEO_CODEC_STRING_PREFIXES = ['avc1', 'avc3', 'hev1', 'hvc1', 'vp8', 'vp09', 'av01'];\nconst AVC_CODEC_STRING_REGEX = /^(avc1|avc3)\\.[0-9a-fA-F]{6}$/;\nconst HEVC_CODEC_STRING_REGEX = /^(hev1|hvc1)\\.(?:[ABC]?\\d+)\\.[0-9a-fA-F]{1,8}\\.[LH]\\d+(?:\\.[0-9a-fA-F]{1,2}){0,6}$/;\nconst VP9_CODEC_STRING_REGEX = /^vp09(?:\\.\\d{2}){3}(?:(?:\\.\\d{2}){5})?$/;\nconst AV1_CODEC_STRING_REGEX = /^av01\\.\\d\\.\\d{2}[MH]\\.\\d{2}(?:\\.\\d\\.\\d{3}\\.\\d{2}\\.\\d{2}\\.\\d{2}\\.\\d)?$/;\nexport const validateVideoChunkMetadata = (metadata) => {\n if (!metadata) {\n throw new TypeError('Video chunk metadata must be provided.');\n }\n if (typeof metadata !== 'object') {\n throw new TypeError('Video chunk metadata must be an object.');\n }\n if (!metadata.decoderConfig) {\n throw new TypeError('Video chunk metadata must include a decoder configuration.');\n }\n if (typeof metadata.decoderConfig !== 'object') {\n throw new TypeError('Video chunk metadata decoder configuration must be an object.');\n }\n if (typeof metadata.decoderConfig.codec !== 'string') {\n throw new TypeError('Video chunk metadata decoder configuration must specify a codec string.');\n }\n if (!VALID_VIDEO_CODEC_STRING_PREFIXES.some(prefix => metadata.decoderConfig.codec.startsWith(prefix))) {\n throw new TypeError('Video chunk metadata decoder configuration codec string must be a valid video codec string as specified in'\n + ' the WebCodecs Codec Registry.');\n }\n if (!Number.isInteger(metadata.decoderConfig.codedWidth) || metadata.decoderConfig.codedWidth <= 0) {\n throw new TypeError('Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).');\n }\n if (!Number.isInteger(metadata.decoderConfig.codedHeight) || metadata.decoderConfig.codedHeight <= 0) {\n throw new TypeError('Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).');\n }\n if (metadata.decoderConfig.description !== undefined) {\n if (!isAllowSharedBufferSource(metadata.decoderConfig.description)) {\n throw new TypeError('Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an'\n + ' ArrayBuffer view.');\n }\n }\n if (metadata.decoderConfig.colorSpace !== undefined) {\n const { colorSpace } = metadata.decoderConfig;\n if (typeof colorSpace !== 'object') {\n throw new TypeError('Video chunk metadata decoder configuration colorSpace, when provided, must be an object.');\n }\n const primariesValues = Object.keys(COLOR_PRIMARIES_MAP);\n if (colorSpace.primaries != null && !primariesValues.includes(colorSpace.primaries)) {\n throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of`\n + ` ${primariesValues.join(', ')}.`);\n }\n const transferValues = Object.keys(TRANSFER_CHARACTERISTICS_MAP);\n if (colorSpace.transfer != null && !transferValues.includes(colorSpace.transfer)) {\n throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of`\n + ` ${transferValues.join(', ')}.`);\n }\n const matrixValues = Object.keys(MATRIX_COEFFICIENTS_MAP);\n if (colorSpace.matrix != null && !matrixValues.includes(colorSpace.matrix)) {\n throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of`\n + ` ${matrixValues.join(', ')}.`);\n }\n if (colorSpace.fullRange != null && typeof colorSpace.fullRange !== 'boolean') {\n throw new TypeError('Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.');\n }\n }\n if (metadata.decoderConfig.codec.startsWith('avc1') || metadata.decoderConfig.codec.startsWith('avc3')) {\n // AVC-specific validation\n if (!AVC_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {\n throw new TypeError('Video chunk metadata decoder configuration codec string for AVC must be a valid AVC codec string as'\n + ' specified in Section 3.4 of RFC 6381.');\n }\n // `description` may or may not be set, depending on if the format is AVCC or Annex B, so don't perform any\n // validation for it.\n // https://www.w3.org/TR/webcodecs-avc-codec-registration\n }\n else if (metadata.decoderConfig.codec.startsWith('hev1') || metadata.decoderConfig.codec.startsWith('hvc1')) {\n // HEVC-specific validation\n if (!HEVC_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {\n throw new TypeError('Video chunk metadata decoder configuration codec string for HEVC must be a valid HEVC codec string as'\n + ' specified in Section E.3 of ISO 14496-15.');\n }\n // `description` may or may not be set, depending on if the format is HEVC or Annex B, so don't perform any\n // validation for it.\n // https://www.w3.org/TR/webcodecs-hevc-codec-registration\n }\n else if (metadata.decoderConfig.codec.startsWith('vp8')) {\n // VP8-specific validation\n if (metadata.decoderConfig.codec !== 'vp8') {\n throw new TypeError('Video chunk metadata decoder configuration codec string for VP8 must be \"vp8\".');\n }\n }\n else if (metadata.decoderConfig.codec.startsWith('vp09')) {\n // VP9-specific validation\n if (!VP9_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {\n throw new TypeError('Video chunk metadata decoder configuration codec string for VP9 must be a valid VP9 codec string as'\n + ' specified in Section \"Codecs Parameter String\" of https://www.webmproject.org/vp9/mp4/.');\n }\n }\n else if (metadata.decoderConfig.codec.startsWith('av01')) {\n // AV1-specific validation\n if (!AV1_CODEC_STRING_REGEX.test(metadata.decoderConfig.codec)) {\n throw new TypeError('Video chunk metadata decoder configuration codec string for AV1 must be a valid AV1 codec string as'\n + ' specified in Section \"Codecs Parameter String\" of https://aomediacodec.github.io/av1-isobmff/.');\n }\n }\n};\nconst VALID_AUDIO_CODEC_STRING_PREFIXES = ['mp4a', 'mp3', 'opus', 'vorbis', 'flac', 'ulaw', 'alaw', 'pcm'];\nexport const validateAudioChunkMetadata = (metadata) => {\n if (!metadata) {\n throw new TypeError('Audio chunk metadata must be provided.');\n }\n if (typeof metadata !== 'object') {\n throw new TypeError('Audio chunk metadata must be an object.');\n }\n if (!metadata.decoderConfig) {\n throw new TypeError('Audio chunk metadata must include a decoder configuration.');\n }\n if (typeof metadata.decoderConfig !== 'object') {\n throw new TypeError('Audio chunk metadata decoder configuration must be an object.');\n }\n if (typeof metadata.decoderConfig.codec !== 'string') {\n throw new TypeError('Audio chunk metadata decoder configuration must specify a codec string.');\n }\n if (!VALID_AUDIO_CODEC_STRING_PREFIXES.some(prefix => metadata.decoderConfig.codec.startsWith(prefix))) {\n throw new TypeError('Audio chunk metadata decoder configuration codec string must be a valid audio codec string as specified in'\n + ' the WebCodecs Codec Registry.');\n }\n if (!Number.isInteger(metadata.decoderConfig.sampleRate) || metadata.decoderConfig.sampleRate <= 0) {\n throw new TypeError('Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).');\n }\n if (!Number.isInteger(metadata.decoderConfig.numberOfChannels) || metadata.decoderConfig.numberOfChannels <= 0) {\n throw new TypeError('Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).');\n }\n if (metadata.decoderConfig.description !== undefined) {\n if (!isAllowSharedBufferSource(metadata.decoderConfig.description)) {\n throw new TypeError('Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an'\n + ' ArrayBuffer view.');\n }\n }\n if (metadata.decoderConfig.codec.startsWith('mp4a')\n // These three refer to MP3:\n && metadata.decoderConfig.codec !== 'mp4a.69'\n && metadata.decoderConfig.codec !== 'mp4a.6B'\n && metadata.decoderConfig.codec !== 'mp4a.6b') {\n // AAC-specific validation\n const validStrings = ['mp4a.40.2', 'mp4a.40.02', 'mp4a.40.5', 'mp4a.40.05', 'mp4a.40.29', 'mp4a.67'];\n if (!validStrings.includes(metadata.decoderConfig.codec)) {\n throw new TypeError('Audio chunk metadata decoder configuration codec string for AAC must be a valid AAC codec string as'\n + ' specified in https://www.w3.org/TR/webcodecs-aac-codec-registration/.');\n }\n if (!metadata.decoderConfig.description) {\n throw new TypeError('Audio chunk metadata decoder configuration for AAC must include a description, which is expected to be'\n + ' an AudioSpecificConfig as specified in ISO 14496-3.');\n }\n }\n else if (metadata.decoderConfig.codec.startsWith('mp3') || metadata.decoderConfig.codec.startsWith('mp4a')) {\n // MP3-specific validation\n if (metadata.decoderConfig.codec !== 'mp3'\n && metadata.decoderConfig.codec !== 'mp4a.69'\n && metadata.decoderConfig.codec !== 'mp4a.6B'\n && metadata.decoderConfig.codec !== 'mp4a.6b') {\n throw new TypeError('Audio chunk metadata decoder configuration codec string for MP3 must be \"mp3\", \"mp4a.69\" or'\n + ' \"mp4a.6B\".');\n }\n }\n else if (metadata.decoderConfig.codec.startsWith('opus')) {\n // Opus-specific validation\n if (metadata.decoderConfig.codec !== 'opus') {\n throw new TypeError('Audio chunk metadata decoder configuration codec string for Opus must be \"opus\".');\n }\n if (metadata.decoderConfig.description && metadata.decoderConfig.description.byteLength < 18) {\n // Description is optional for Opus per-spec, so we shouldn't enforce it\n throw new TypeError('Audio chunk metadata decoder configuration description, when specified, is expected to be an'\n + ' Identification Header as specified in Section 5.1 of RFC 7845.');\n }\n }\n else if (metadata.decoderConfig.codec.startsWith('vorbis')) {\n // Vorbis-specific validation\n if (metadata.decoderConfig.codec !== 'vorbis') {\n throw new TypeError('Audio chunk metadata decoder configuration codec string for Vorbis must be \"vorbis\".');\n }\n if (!metadata.decoderConfig.description) {\n throw new TypeError('Audio chunk metadata decoder configuration for Vorbis must include a description, which is expected to'\n + ' adhere to the format described in https://www.w3.org/TR/webcodecs-vorbis-codec-registration/.');\n }\n }\n else if (metadata.decoderConfig.codec.startsWith('flac')) {\n // FLAC-specific validation\n if (metadata.decoderConfig.codec !== 'flac') {\n throw new TypeError('Audio chunk metadata decoder configuration codec string for FLAC must be \"flac\".');\n }\n const minDescriptionSize = 4 + 4 + 34; // 'fLaC' + metadata block header + STREAMINFO block\n if (!metadata.decoderConfig.description || metadata.decoderConfig.description.byteLength < minDescriptionSize) {\n throw new TypeError('Audio chunk metadata decoder configuration for FLAC must include a description, which is expected to'\n + ' adhere to the format described in https://www.w3.org/TR/webcodecs-flac-codec-registration/.');\n }\n }\n else if (metadata.decoderConfig.codec.startsWith('pcm')\n || metadata.decoderConfig.codec.startsWith('ulaw')\n || metadata.decoderConfig.codec.startsWith('alaw')) {\n // PCM-specific validation\n if (!PCM_AUDIO_CODECS.includes(metadata.decoderConfig.codec)) {\n throw new TypeError('Audio chunk metadata decoder configuration codec string for PCM must be one of the supported PCM'\n + ` codecs (${PCM_AUDIO_CODECS.join(', ')}).`);\n }\n }\n};\nexport const validateSubtitleMetadata = (metadata) => {\n if (!metadata) {\n throw new TypeError('Subtitle metadata must be provided.');\n }\n if (typeof metadata !== 'object') {\n throw new TypeError('Subtitle metadata must be an object.');\n }\n if (!metadata.config) {\n throw new TypeError('Subtitle metadata must include a config object.');\n }\n if (typeof metadata.config !== 'object') {\n throw new TypeError('Subtitle metadata config must be an object.');\n }\n if (typeof metadata.config.description !== 'string') {\n throw new TypeError('Subtitle metadata config description must be a string.');\n }\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { AsyncMutex } from './misc.js';\nexport class Muxer {\n constructor(output) {\n this.mutex = new AsyncMutex();\n /**\n * This field is used to synchronize multiple MediaStreamTracks. They use the same time coordinate system across\n * tracks, and to ensure correct audio-video sync, we must use the same offset for all of them. The reason an offset\n * is needed at all is because the timestamps typically don't start at zero.\n */\n this.firstMediaStreamTimestamp = null;\n this.trackTimestampInfo = new WeakMap();\n this.output = output;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onTrackClose(track) { }\n validateAndNormalizeTimestamp(track, timestampInSeconds, isKeyPacket) {\n timestampInSeconds += track.source._timestampOffset;\n let timestampInfo = this.trackTimestampInfo.get(track);\n if (!timestampInfo) {\n if (!isKeyPacket) {\n throw new Error('First packet must be a key packet.');\n }\n timestampInfo = {\n maxTimestamp: timestampInSeconds,\n maxTimestampBeforeLastKeyPacket: timestampInSeconds,\n };\n this.trackTimestampInfo.set(track, timestampInfo);\n }\n if (timestampInSeconds < 0) {\n throw new Error(`Timestamps must be non-negative (got ${timestampInSeconds}s).`);\n }\n if (isKeyPacket) {\n timestampInfo.maxTimestampBeforeLastKeyPacket = timestampInfo.maxTimestamp;\n }\n if (timestampInSeconds < timestampInfo.maxTimestampBeforeLastKeyPacket) {\n throw new Error(`Timestamps cannot be smaller than the largest timestamp of the previous GOP (a GOP begins with a key`\n + ` packet and ends right before the next key packet). Got ${timestampInSeconds}s, but largest`\n + ` timestamp is ${timestampInfo.maxTimestampBeforeLastKeyPacket}s.`);\n }\n timestampInfo.maxTimestamp = Math.max(timestampInfo.maxTimestamp, timestampInSeconds);\n return timestampInSeconds;\n }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { VP9_LEVEL_TABLE } from './codec.js';\nimport { assert, assertNever, base64ToBytes, Bitstream, bytesToBase64, keyValueIterator, getUint24, last, readExpGolomb, readSignedExpGolomb, textDecoder, textEncoder, toDataView, toUint8Array, } from './misc.js';\n// References for AVC/HEVC code:\n// ISO 14496-15\n// Rec. ITU-T H.264\n// Rec. ITU-T H.265\n// https://stackoverflow.com/questions/24884827\nexport var AvcNalUnitType;\n(function (AvcNalUnitType) {\n AvcNalUnitType[AvcNalUnitType[\"IDR\"] = 5] = \"IDR\";\n AvcNalUnitType[AvcNalUnitType[\"SPS\"] = 7] = \"SPS\";\n AvcNalUnitType[AvcNalUnitType[\"PPS\"] = 8] = \"PPS\";\n AvcNalUnitType[AvcNalUnitType[\"SPS_EXT\"] = 13] = \"SPS_EXT\";\n})(AvcNalUnitType || (AvcNalUnitType = {}));\nexport var HevcNalUnitType;\n(function (HevcNalUnitType) {\n HevcNalUnitType[HevcNalUnitType[\"RASL_N\"] = 8] = \"RASL_N\";\n HevcNalUnitType[HevcNalUnitType[\"RASL_R\"] = 9] = \"RASL_R\";\n HevcNalUnitType[HevcNalUnitType[\"BLA_W_LP\"] = 16] = \"BLA_W_LP\";\n HevcNalUnitType[HevcNalUnitType[\"RSV_IRAP_VCL23\"] = 23] = \"RSV_IRAP_VCL23\";\n HevcNalUnitType[HevcNalUnitType[\"VPS_NUT\"] = 32] = \"VPS_NUT\";\n HevcNalUnitType[HevcNalUnitType[\"SPS_NUT\"] = 33] = \"SPS_NUT\";\n HevcNalUnitType[HevcNalUnitType[\"PPS_NUT\"] = 34] = \"PPS_NUT\";\n HevcNalUnitType[HevcNalUnitType[\"PREFIX_SEI_NUT\"] = 39] = \"PREFIX_SEI_NUT\";\n HevcNalUnitType[HevcNalUnitType[\"SUFFIX_SEI_NUT\"] = 40] = \"SUFFIX_SEI_NUT\";\n})(HevcNalUnitType || (HevcNalUnitType = {}));\n/** Finds all NAL units in an AVC packet in Annex B format. */\nexport const findNalUnitsInAnnexB = (packetData) => {\n const nalUnits = [];\n let i = 0;\n while (i < packetData.length) {\n let startCodePos = -1;\n let startCodeLength = 0;\n for (let j = i; j < packetData.length - 3; j++) {\n // Check for 3-byte start code (0x000001)\n if (packetData[j] === 0 && packetData[j + 1] === 0 && packetData[j + 2] === 1) {\n startCodePos = j;\n startCodeLength = 3;\n break;\n }\n // Check for 4-byte start code (0x00000001)\n if (j < packetData.length - 4\n && packetData[j] === 0\n && packetData[j + 1] === 0\n && packetData[j + 2] === 0\n && packetData[j + 3] === 1) {\n startCodePos = j;\n startCodeLength = 4;\n break;\n }\n }\n if (startCodePos === -1) {\n break; // No more start codes found\n }\n // If this isn't the first start code, extract the previous NAL unit\n if (i > 0 && startCodePos > i) {\n const nalData = packetData.subarray(i, startCodePos);\n if (nalData.length > 0) {\n nalUnits.push(nalData);\n }\n }\n i = startCodePos + startCodeLength;\n }\n // Extract the last NAL unit if there is one\n if (i < packetData.length) {\n const nalData = packetData.subarray(i);\n if (nalData.length > 0) {\n nalUnits.push(nalData);\n }\n }\n return nalUnits;\n};\n/** Finds all NAL units in an AVC packet in length-prefixed format. */\nconst findNalUnitsInLengthPrefixed = (packetData, lengthSize) => {\n const nalUnits = [];\n let offset = 0;\n const dataView = new DataView(packetData.buffer, packetData.byteOffset, packetData.byteLength);\n while (offset + lengthSize <= packetData.length) {\n let nalUnitLength;\n if (lengthSize === 1) {\n nalUnitLength = dataView.getUint8(offset);\n }\n else if (lengthSize === 2) {\n nalUnitLength = dataView.getUint16(offset, false);\n }\n else if (lengthSize === 3) {\n nalUnitLength = getUint24(dataView, offset, false);\n }\n else if (lengthSize === 4) {\n nalUnitLength = dataView.getUint32(offset, false);\n }\n else {\n assertNever(lengthSize);\n assert(false);\n }\n offset += lengthSize;\n const nalUnit = packetData.subarray(offset, offset + nalUnitLength);\n nalUnits.push(nalUnit);\n offset += nalUnitLength;\n }\n return nalUnits;\n};\nconst removeEmulationPreventionBytes = (data) => {\n const result = [];\n const len = data.length;\n for (let i = 0; i < len; i++) {\n // Look for the 0x000003 pattern\n if (i + 2 < len && data[i] === 0x00 && data[i + 1] === 0x00 && data[i + 2] === 0x03) {\n result.push(0x00, 0x00); // Push the first two bytes\n i += 2; // Skip the 0x03 byte\n }\n else {\n result.push(data[i]);\n }\n }\n return new Uint8Array(result);\n};\n/** Converts an AVC packet in Annex B format to length-prefixed format. */\nexport const transformAnnexBToLengthPrefixed = (packetData) => {\n const NAL_UNIT_LENGTH_SIZE = 4;\n const nalUnits = findNalUnitsInAnnexB(packetData);\n if (nalUnits.length === 0) {\n // If no NAL units were found, it's not valid Annex B data\n return null;\n }\n let totalSize = 0;\n for (const nalUnit of nalUnits) {\n totalSize += NAL_UNIT_LENGTH_SIZE + nalUnit.byteLength;\n }\n const avccData = new Uint8Array(totalSize);\n const dataView = new DataView(avccData.buffer);\n let offset = 0;\n // Write each NAL unit with its length prefix\n for (const nalUnit of nalUnits) {\n const length = nalUnit.byteLength;\n dataView.setUint32(offset, length, false);\n offset += 4;\n avccData.set(nalUnit, offset);\n offset += nalUnit.byteLength;\n }\n return avccData;\n};\nexport const extractAvcNalUnits = (packetData, decoderConfig) => {\n if (decoderConfig.description) {\n // Stream is length-prefixed. Let's extract the size of the length prefix from the decoder config\n const bytes = toUint8Array(decoderConfig.description);\n const lengthSizeMinusOne = bytes[4] & 0b11;\n const lengthSize = (lengthSizeMinusOne + 1);\n return findNalUnitsInLengthPrefixed(packetData, lengthSize);\n }\n else {\n // Stream is in Annex B format\n return findNalUnitsInAnnexB(packetData);\n }\n};\nconst extractNalUnitTypeForAvc = (data) => {\n return data[0] & 0x1F;\n};\n/** Builds an AvcDecoderConfigurationRecord from an AVC packet in Annex B format. */\nexport const extractAvcDecoderConfigurationRecord = (packetData) => {\n try {\n const nalUnits = findNalUnitsInAnnexB(packetData);\n const spsUnits = nalUnits.filter(unit => extractNalUnitTypeForAvc(unit) === AvcNalUnitType.SPS);\n const ppsUnits = nalUnits.filter(unit => extractNalUnitTypeForAvc(unit) === AvcNalUnitType.PPS);\n const spsExtUnits = nalUnits.filter(unit => extractNalUnitTypeForAvc(unit) === AvcNalUnitType.SPS_EXT);\n if (spsUnits.length === 0) {\n return null;\n }\n if (ppsUnits.length === 0) {\n return null;\n }\n // Let's get the first SPS for profile and level information\n const spsData = spsUnits[0];\n const spsInfo = parseAvcSps(spsData);\n assert(spsInfo !== null);\n const hasExtendedData = spsInfo.profileIdc === 100\n || spsInfo.profileIdc === 110\n || spsInfo.profileIdc === 122\n || spsInfo.profileIdc === 144;\n return {\n configurationVersion: 1,\n avcProfileIndication: spsInfo.profileIdc,\n profileCompatibility: spsInfo.constraintFlags,\n avcLevelIndication: spsInfo.levelIdc,\n lengthSizeMinusOne: 3, // Typically 4 bytes for length field\n sequenceParameterSets: spsUnits,\n pictureParameterSets: ppsUnits,\n chromaFormat: hasExtendedData ? spsInfo.chromaFormatIdc : null,\n bitDepthLumaMinus8: hasExtendedData ? spsInfo.bitDepthLumaMinus8 : null,\n bitDepthChromaMinus8: hasExtendedData ? spsInfo.bitDepthChromaMinus8 : null,\n sequenceParameterSetExt: hasExtendedData ? spsExtUnits : null,\n };\n }\n catch (error) {\n console.error('Error building AVC Decoder Configuration Record:', error);\n return null;\n }\n};\n/** Serializes an AvcDecoderConfigurationRecord into the format specified in Section 5.3.3.1 of ISO 14496-15. */\nexport const serializeAvcDecoderConfigurationRecord = (record) => {\n const bytes = [];\n // Write header\n bytes.push(record.configurationVersion);\n bytes.push(record.avcProfileIndication);\n bytes.push(record.profileCompatibility);\n bytes.push(record.avcLevelIndication);\n bytes.push(0xFC | (record.lengthSizeMinusOne & 0x03)); // Reserved bits (6) + lengthSizeMinusOne (2)\n // Reserved bits (3) + numOfSequenceParameterSets (5)\n bytes.push(0xE0 | (record.sequenceParameterSets.length & 0x1F));\n // Write SPS\n for (const sps of record.sequenceParameterSets) {\n const length = sps.byteLength;\n bytes.push(length >> 8); // High byte\n bytes.push(length & 0xFF); // Low byte\n for (let i = 0; i < length; i++) {\n bytes.push(sps[i]);\n }\n }\n bytes.push(record.pictureParameterSets.length);\n // Write PPS\n for (const pps of record.pictureParameterSets) {\n const length = pps.byteLength;\n bytes.push(length >> 8); // High byte\n bytes.push(length & 0xFF); // Low byte\n for (let i = 0; i < length; i++) {\n bytes.push(pps[i]);\n }\n }\n if (record.avcProfileIndication === 100\n || record.avcProfileIndication === 110\n || record.avcProfileIndication === 122\n || record.avcProfileIndication === 144) {\n assert(record.chromaFormat !== null);\n assert(record.bitDepthLumaMinus8 !== null);\n assert(record.bitDepthChromaMinus8 !== null);\n assert(record.sequenceParameterSetExt !== null);\n bytes.push(0xFC | (record.chromaFormat & 0x03)); // Reserved bits + chroma_format\n bytes.push(0xF8 | (record.bitDepthLumaMinus8 & 0x07)); // Reserved bits + bit_depth_luma_minus8\n bytes.push(0xF8 | (record.bitDepthChromaMinus8 & 0x07)); // Reserved bits + bit_depth_chroma_minus8\n bytes.push(record.sequenceParameterSetExt.length);\n // Write SPS Ext\n for (const spsExt of record.sequenceParameterSetExt) {\n const length = spsExt.byteLength;\n bytes.push(length >> 8); // High byte\n bytes.push(length & 0xFF); // Low byte\n for (let i = 0; i < length; i++) {\n bytes.push(spsExt[i]);\n }\n }\n }\n return new Uint8Array(bytes);\n};\n/** Deserializes an AvcDecoderConfigurationRecord from the format specified in Section 5.3.3.1 of ISO 14496-15. */\nexport const deserializeAvcDecoderConfigurationRecord = (data) => {\n try {\n const view = toDataView(data);\n let offset = 0;\n // Read header\n const configurationVersion = view.getUint8(offset++);\n const avcProfileIndication = view.getUint8(offset++);\n const profileCompatibility = view.getUint8(offset++);\n const avcLevelIndication = view.getUint8(offset++);\n const lengthSizeMinusOne = view.getUint8(offset++) & 0x03;\n const numOfSequenceParameterSets = view.getUint8(offset++) & 0x1F;\n // Read SPS\n const sequenceParameterSets = [];\n for (let i = 0; i < numOfSequenceParameterSets; i++) {\n const length = view.getUint16(offset, false);\n offset += 2;\n sequenceParameterSets.push(data.subarray(offset, offset + length));\n offset += length;\n }\n const numOfPictureParameterSets = view.getUint8(offset++);\n // Read PPS\n const pictureParameterSets = [];\n for (let i = 0; i < numOfPictureParameterSets; i++) {\n const length = view.getUint16(offset, false);\n offset += 2;\n pictureParameterSets.push(data.subarray(offset, offset + length));\n offset += length;\n }\n const record = {\n configurationVersion,\n avcProfileIndication,\n profileCompatibility,\n avcLevelIndication,\n lengthSizeMinusOne,\n sequenceParameterSets,\n pictureParameterSets,\n chromaFormat: null,\n bitDepthLumaMinus8: null,\n bitDepthChromaMinus8: null,\n sequenceParameterSetExt: null,\n };\n // Check if there are extended profile fields\n if ((avcProfileIndication === 100\n || avcProfileIndication === 110\n || avcProfileIndication === 122\n || avcProfileIndication === 144)\n && offset + 4 <= data.length) {\n const chromaFormat = view.getUint8(offset++) & 0x03;\n const bitDepthLumaMinus8 = view.getUint8(offset++) & 0x07;\n const bitDepthChromaMinus8 = view.getUint8(offset++) & 0x07;\n const numOfSequenceParameterSetExt = view.getUint8(offset++);\n record.chromaFormat = chromaFormat;\n record.bitDepthLumaMinus8 = bitDepthLumaMinus8;\n record.bitDepthChromaMinus8 = bitDepthChromaMinus8;\n // Read SPS Ext\n const sequenceParameterSetExt = [];\n for (let i = 0; i < numOfSequenceParameterSetExt; i++) {\n const length = view.getUint16(offset, false);\n offset += 2;\n sequenceParameterSetExt.push(data.subarray(offset, offset + length));\n offset += length;\n }\n record.sequenceParameterSetExt = sequenceParameterSetExt;\n }\n return record;\n }\n catch (error) {\n console.error('Error deserializing AVC Decoder Configuration Record:', error);\n return null;\n }\n};\n/** Parses an AVC SPS (Sequence Parameter Set) to extract basic information. */\nexport const parseAvcSps = (sps) => {\n try {\n const bitstream = new Bitstream(removeEmulationPreventionBytes(sps));\n bitstream.skipBits(1); // forbidden_zero_bit\n bitstream.skipBits(2); // nal_ref_idc\n const nalUnitType = bitstream.readBits(5);\n if (nalUnitType !== 7) { // SPS NAL unit type is 7\n return null;\n }\n const profileIdc = bitstream.readAlignedByte();\n const constraintFlags = bitstream.readAlignedByte();\n const levelIdc = bitstream.readAlignedByte();\n readExpGolomb(bitstream); // seq_parameter_set_id\n let chromaFormatIdc = null;\n let bitDepthLumaMinus8 = null;\n let bitDepthChromaMinus8 = null;\n // Handle high profile chroma_format_idc\n if (profileIdc === 100\n || profileIdc === 110\n || profileIdc === 122\n || profileIdc === 244\n || profileIdc === 44\n || profileIdc === 83\n || profileIdc === 86\n || profileIdc === 118\n || profileIdc === 128) {\n chromaFormatIdc = readExpGolomb(bitstream);\n if (chromaFormatIdc === 3) {\n bitstream.skipBits(1); // separate_colour_plane_flag\n }\n bitDepthLumaMinus8 = readExpGolomb(bitstream);\n bitDepthChromaMinus8 = readExpGolomb(bitstream);\n bitstream.skipBits(1); // qpprime_y_zero_transform_bypass_flag\n const seqScalingMatrixPresentFlag = bitstream.readBits(1);\n if (seqScalingMatrixPresentFlag) {\n for (let i = 0; i < (chromaFormatIdc !== 3 ? 8 : 12); i++) {\n const seqScalingListPresentFlag = bitstream.readBits(1);\n if (seqScalingListPresentFlag) {\n const sizeOfScalingList = i < 6 ? 16 : 64;\n let lastScale = 8;\n let nextScale = 8;\n for (let j = 0; j < sizeOfScalingList; j++) {\n if (nextScale !== 0) {\n const deltaScale = readSignedExpGolomb(bitstream);\n nextScale = (lastScale + deltaScale + 256) % 256;\n }\n lastScale = nextScale === 0 ? lastScale : nextScale;\n }\n }\n }\n }\n }\n readExpGolomb(bitstream); // log2_max_frame_num_minus4\n const picOrderCntType = readExpGolomb(bitstream);\n if (picOrderCntType === 0) {\n readExpGolomb(bitstream); // log2_max_pic_order_cnt_lsb_minus4\n }\n else if (picOrderCntType === 1) {\n bitstream.skipBits(1); // delta_pic_order_always_zero_flag\n readSignedExpGolomb(bitstream); // offset_for_non_ref_pic\n readSignedExpGolomb(bitstream); // offset_for_top_to_bottom_field\n const numRefFramesInPicOrderCntCycle = readExpGolomb(bitstream);\n for (let i = 0; i < numRefFramesInPicOrderCntCycle; i++) {\n readSignedExpGolomb(bitstream); // offset_for_ref_frame[i]\n }\n }\n readExpGolomb(bitstream); // max_num_ref_frames\n bitstream.skipBits(1); // gaps_in_frame_num_value_allowed_flag\n readExpGolomb(bitstream); // pic_width_in_mbs_minus1\n readExpGolomb(bitstream); // pic_height_in_map_units_minus1\n const frameMbsOnlyFlag = bitstream.readBits(1);\n return {\n profileIdc,\n constraintFlags,\n levelIdc,\n frameMbsOnlyFlag,\n chromaFormatIdc,\n bitDepthLumaMinus8,\n bitDepthChromaMinus8,\n };\n }\n catch (error) {\n console.error('Error parsing AVC SPS:', error);\n return null;\n }\n};\nexport const extractHevcNalUnits = (packetData, decoderConfig) => {\n if (decoderConfig.description) {\n // Stream is length-prefixed. Let's extract the size of the length prefix from the decoder config\n const bytes = toUint8Array(decoderConfig.description);\n const lengthSizeMinusOne = bytes[21] & 0b11;\n const lengthSize = (lengthSizeMinusOne + 1);\n return findNalUnitsInLengthPrefixed(packetData, lengthSize);\n }\n else {\n // Stream is in Annex B format\n return findNalUnitsInAnnexB(packetData);\n }\n};\nexport const extractNalUnitTypeForHevc = (data) => {\n return (data[0] >> 1) & 0x3F;\n};\n/** Builds a HevcDecoderConfigurationRecord from an HEVC packet in Annex B format. */\nexport const extractHevcDecoderConfigurationRecord = (packetData) => {\n try {\n const nalUnits = findNalUnitsInAnnexB(packetData);\n const vpsUnits = nalUnits.filter(unit => extractNalUnitTypeForHevc(unit) === HevcNalUnitType.VPS_NUT);\n const spsUnits = nalUnits.filter(unit => extractNalUnitTypeForHevc(unit) === HevcNalUnitType.SPS_NUT);\n const ppsUnits = nalUnits.filter(unit => extractNalUnitTypeForHevc(unit) === HevcNalUnitType.PPS_NUT);\n const seiUnits = nalUnits.filter(unit => extractNalUnitTypeForHevc(unit) === HevcNalUnitType.PREFIX_SEI_NUT\n || extractNalUnitTypeForHevc(unit) === HevcNalUnitType.SUFFIX_SEI_NUT);\n if (spsUnits.length === 0 || ppsUnits.length === 0)\n return null;\n const sps = spsUnits[0];\n const bitstream = new Bitstream(removeEmulationPreventionBytes(sps));\n bitstream.skipBits(16); // NAL header\n bitstream.readBits(4); // sps_video_parameter_set_id\n const sps_max_sub_layers_minus1 = bitstream.readBits(3);\n const sps_temporal_id_nesting_flag = bitstream.readBits(1);\n const { general_profile_space, general_tier_flag, general_profile_idc, general_profile_compatibility_flags, general_constraint_indicator_flags, general_level_idc, } = parseProfileTierLevel(bitstream, sps_max_sub_layers_minus1);\n readExpGolomb(bitstream); // sps_seq_parameter_set_id\n const chroma_format_idc = readExpGolomb(bitstream);\n if (chroma_format_idc === 3)\n bitstream.skipBits(1); // separate_colour_plane_flag\n readExpGolomb(bitstream); // pic_width_in_luma_samples\n readExpGolomb(bitstream); // pic_height_in_luma_samples\n if (bitstream.readBits(1)) { // conformance_window_flag\n readExpGolomb(bitstream); // conf_win_left_offset\n readExpGolomb(bitstream); // conf_win_right_offset\n readExpGolomb(bitstream); // conf_win_top_offset\n readExpGolomb(bitstream); // conf_win_bottom_offset\n }\n const bit_depth_luma_minus8 = readExpGolomb(bitstream);\n const bit_depth_chroma_minus8 = readExpGolomb(bitstream);\n readExpGolomb(bitstream); // log2_max_pic_order_cnt_lsb_minus4\n const sps_sub_layer_ordering_info_present_flag = bitstream.readBits(1);\n const maxNum = sps_sub_layer_ordering_info_present_flag ? 0 : sps_max_sub_layers_minus1;\n for (let i = maxNum; i <= sps_max_sub_layers_minus1; i++) {\n readExpGolomb(bitstream); // sps_max_dec_pic_buffering_minus1[i]\n readExpGolomb(bitstream); // sps_max_num_reorder_pics[i]\n readExpGolomb(bitstream); // sps_max_latency_increase_plus1[i]\n }\n readExpGolomb(bitstream); // log2_min_luma_coding_block_size_minus3\n readExpGolomb(bitstream); // log2_diff_max_min_luma_coding_block_size\n readExpGolomb(bitstream); // log2_min_luma_transform_block_size_minus2\n readExpGolomb(bitstream); // log2_diff_max_min_luma_transform_block_size\n readExpGolomb(bitstream); // max_transform_hierarchy_depth_inter\n readExpGolomb(bitstream); // max_transform_hierarchy_depth_intra\n if (bitstream.readBits(1)) { // scaling_list_enabled_flag\n if (bitstream.readBits(1)) {\n skipScalingListData(bitstream);\n }\n }\n bitstream.skipBits(1); // amp_enabled_flag\n bitstream.skipBits(1); // sample_adaptive_offset_enabled_flag\n if (bitstream.readBits(1)) { // pcm_enabled_flag\n bitstream.skipBits(4); // pcm_sample_bit_depth_luma_minus1\n bitstream.skipBits(4); // pcm_sample_bit_depth_chroma_minus1\n readExpGolomb(bitstream); // log2_min_pcm_luma_coding_block_size_minus3\n readExpGolomb(bitstream); // log2_diff_max_min_pcm_luma_coding_block_size\n bitstream.skipBits(1); // pcm_loop_filter_disabled_flag\n }\n const num_short_term_ref_pic_sets = readExpGolomb(bitstream);\n skipAllStRefPicSets(bitstream, num_short_term_ref_pic_sets);\n if (bitstream.readBits(1)) { // long_term_ref_pics_present_flag\n const num_long_term_ref_pics_sps = readExpGolomb(bitstream);\n for (let i = 0; i < num_long_term_ref_pics_sps; i++) {\n readExpGolomb(bitstream); // lt_ref_pic_poc_lsb_sps[i]\n bitstream.skipBits(1); // used_by_curr_pic_lt_sps_flag[i]\n }\n }\n bitstream.skipBits(1); // sps_temporal_mvp_enabled_flag\n bitstream.skipBits(1); // strong_intra_smoothing_enabled_flag\n let min_spatial_segmentation_idc = 0;\n if (bitstream.readBits(1)) { // vui_parameters_present_flag\n min_spatial_segmentation_idc = parseVuiForMinSpatialSegmentationIdc(bitstream, sps_max_sub_layers_minus1);\n }\n // Parse PPS for parallelismType\n let parallelismType = 0;\n if (ppsUnits.length > 0) {\n const pps = ppsUnits[0];\n const ppsBitstream = new Bitstream(removeEmulationPreventionBytes(pps));\n ppsBitstream.skipBits(16); // NAL header\n readExpGolomb(ppsBitstream); // pps_pic_parameter_set_id\n readExpGolomb(ppsBitstream); // pps_seq_parameter_set_id\n ppsBitstream.skipBits(1); // dependent_slice_segments_enabled_flag\n ppsBitstream.skipBits(1); // output_flag_present_flag\n ppsBitstream.skipBits(3); // num_extra_slice_header_bits\n ppsBitstream.skipBits(1); // sign_data_hiding_enabled_flag\n ppsBitstream.skipBits(1); // cabac_init_present_flag\n readExpGolomb(ppsBitstream); // num_ref_idx_l0_default_active_minus1\n readExpGolomb(ppsBitstream); // num_ref_idx_l1_default_active_minus1\n readSignedExpGolomb(ppsBitstream); // init_qp_minus26\n ppsBitstream.skipBits(1); // constrained_intra_pred_flag\n ppsBitstream.skipBits(1); // transform_skip_enabled_flag\n if (ppsBitstream.readBits(1)) { // cu_qp_delta_enabled_flag\n readExpGolomb(ppsBitstream); // diff_cu_qp_delta_depth\n }\n readSignedExpGolomb(ppsBitstream); // pps_cb_qp_offset\n readSignedExpGolomb(ppsBitstream); // pps_cr_qp_offset\n ppsBitstream.skipBits(1); // pps_slice_chroma_qp_offsets_present_flag\n ppsBitstream.skipBits(1); // weighted_pred_flag\n ppsBitstream.skipBits(1); // weighted_bipred_flag\n ppsBitstream.skipBits(1); // transquant_bypass_enabled_flag\n const tiles_enabled_flag = ppsBitstream.readBits(1);\n const entropy_coding_sync_enabled_flag = ppsBitstream.readBits(1);\n if (!tiles_enabled_flag && !entropy_coding_sync_enabled_flag)\n parallelismType = 0;\n else if (tiles_enabled_flag && !entropy_coding_sync_enabled_flag)\n parallelismType = 2;\n else if (!tiles_enabled_flag && entropy_coding_sync_enabled_flag)\n parallelismType = 3;\n else\n parallelismType = 0;\n }\n const arrays = [\n ...(vpsUnits.length\n ? [\n {\n arrayCompleteness: 1,\n nalUnitType: HevcNalUnitType.VPS_NUT,\n nalUnits: vpsUnits,\n },\n ]\n : []),\n ...(spsUnits.length\n ? [\n {\n arrayCompleteness: 1,\n nalUnitType: HevcNalUnitType.SPS_NUT,\n nalUnits: spsUnits,\n },\n ]\n : []),\n ...(ppsUnits.length\n ? [\n {\n arrayCompleteness: 1,\n nalUnitType: HevcNalUnitType.PPS_NUT,\n nalUnits: ppsUnits,\n },\n ]\n : []),\n ...(seiUnits.length\n ? [\n {\n arrayCompleteness: 1,\n nalUnitType: extractNalUnitTypeForHevc(seiUnits[0]),\n nalUnits: seiUnits,\n },\n ]\n : []),\n ];\n const record = {\n configurationVersion: 1,\n generalProfileSpace: general_profile_space,\n generalTierFlag: general_tier_flag,\n generalProfileIdc: general_profile_idc,\n generalProfileCompatibilityFlags: general_profile_compatibility_flags,\n generalConstraintIndicatorFlags: general_constraint_indicator_flags,\n generalLevelIdc: general_level_idc,\n minSpatialSegmentationIdc: min_spatial_segmentation_idc,\n parallelismType,\n chromaFormatIdc: chroma_format_idc,\n bitDepthLumaMinus8: bit_depth_luma_minus8,\n bitDepthChromaMinus8: bit_depth_chroma_minus8,\n avgFrameRate: 0,\n constantFrameRate: 0,\n numTemporalLayers: sps_max_sub_layers_minus1 + 1,\n temporalIdNested: sps_temporal_id_nesting_flag,\n lengthSizeMinusOne: 3,\n arrays,\n };\n return record;\n }\n catch (error) {\n console.error('Error building HEVC Decoder Configuration Record:', error);\n return null;\n }\n};\nconst parseProfileTierLevel = (bitstream, maxNumSubLayersMinus1) => {\n const general_profile_space = bitstream.readBits(2);\n const general_tier_flag = bitstream.readBits(1);\n const general_profile_idc = bitstream.readBits(5);\n let general_profile_compatibility_flags = 0;\n for (let i = 0; i < 32; i++) {\n general_profile_compatibility_flags = (general_profile_compatibility_flags << 1) | bitstream.readBits(1);\n }\n const general_constraint_indicator_flags = new Uint8Array(6);\n for (let i = 0; i < 6; i++) {\n general_constraint_indicator_flags[i] = bitstream.readBits(8);\n }\n const general_level_idc = bitstream.readBits(8);\n const sub_layer_profile_present_flag = [];\n const sub_layer_level_present_flag = [];\n for (let i = 0; i < maxNumSubLayersMinus1; i++) {\n sub_layer_profile_present_flag.push(bitstream.readBits(1));\n sub_layer_level_present_flag.push(bitstream.readBits(1));\n }\n if (maxNumSubLayersMinus1 > 0) {\n for (let i = maxNumSubLayersMinus1; i < 8; i++) {\n bitstream.skipBits(2); // reserved_zero_2bits\n }\n }\n for (let i = 0; i < maxNumSubLayersMinus1; i++) {\n if (sub_layer_profile_present_flag[i])\n bitstream.skipBits(88);\n if (sub_layer_level_present_flag[i])\n bitstream.skipBits(8);\n }\n return {\n general_profile_space,\n general_tier_flag,\n general_profile_idc,\n general_profile_compatibility_flags,\n general_constraint_indicator_flags,\n general_level_idc,\n };\n};\nconst skipScalingListData = (bitstream) => {\n for (let sizeId = 0; sizeId < 4; sizeId++) {\n for (let matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {\n const scaling_list_pred_mode_flag = bitstream.readBits(1);\n if (!scaling_list_pred_mode_flag) {\n readExpGolomb(bitstream); // scaling_list_pred_matrix_id_delta\n }\n else {\n const coefNum = Math.min(64, 1 << (4 + (sizeId << 1)));\n if (sizeId > 1) {\n readSignedExpGolomb(bitstream); // scaling_list_dc_coef_minus8\n }\n for (let i = 0; i < coefNum; i++) {\n readSignedExpGolomb(bitstream); // scaling_list_delta_coef\n }\n }\n }\n }\n};\nconst skipAllStRefPicSets = (bitstream, num_short_term_ref_pic_sets) => {\n const NumDeltaPocs = [];\n for (let stRpsIdx = 0; stRpsIdx < num_short_term_ref_pic_sets; stRpsIdx++) {\n NumDeltaPocs[stRpsIdx] = skipStRefPicSet(bitstream, stRpsIdx, num_short_term_ref_pic_sets, NumDeltaPocs);\n }\n};\nconst skipStRefPicSet = (bitstream, stRpsIdx, num_short_term_ref_pic_sets, NumDeltaPocs) => {\n let NumDeltaPocsThis = 0;\n let inter_ref_pic_set_prediction_flag = 0;\n let RefRpsIdx = 0;\n if (stRpsIdx !== 0) {\n inter_ref_pic_set_prediction_flag = bitstream.readBits(1);\n }\n if (inter_ref_pic_set_prediction_flag) {\n if (stRpsIdx === num_short_term_ref_pic_sets) {\n const delta_idx_minus1 = readExpGolomb(bitstream);\n RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1);\n }\n else {\n RefRpsIdx = stRpsIdx - 1;\n }\n bitstream.readBits(1); // delta_rps_sign\n readExpGolomb(bitstream); // abs_delta_rps_minus1\n // The number of iterations is NumDeltaPocs[RefRpsIdx] + 1\n const numDelta = NumDeltaPocs[RefRpsIdx] ?? 0;\n for (let j = 0; j <= numDelta; j++) {\n const used_by_curr_pic_flag = bitstream.readBits(1);\n if (!used_by_curr_pic_flag) {\n bitstream.readBits(1); // use_delta_flag\n }\n }\n NumDeltaPocsThis = NumDeltaPocs[RefRpsIdx];\n }\n else {\n const num_negative_pics = readExpGolomb(bitstream);\n const num_positive_pics = readExpGolomb(bitstream);\n for (let i = 0; i < num_negative_pics; i++) {\n readExpGolomb(bitstream); // delta_poc_s0_minus1[i]\n bitstream.readBits(1); // used_by_curr_pic_s0_flag[i]\n }\n for (let i = 0; i < num_positive_pics; i++) {\n readExpGolomb(bitstream); // delta_poc_s1_minus1[i]\n bitstream.readBits(1); // used_by_curr_pic_s1_flag[i]\n }\n NumDeltaPocsThis = num_negative_pics + num_positive_pics;\n }\n return NumDeltaPocsThis;\n};\nconst parseVuiForMinSpatialSegmentationIdc = (bitstream, sps_max_sub_layers_minus1) => {\n if (bitstream.readBits(1)) { // aspect_ratio_info_present_flag\n const aspect_ratio_idc = bitstream.readBits(8);\n if (aspect_ratio_idc === 255) {\n bitstream.readBits(16); // sar_width\n bitstream.readBits(16); // sar_height\n }\n }\n if (bitstream.readBits(1)) { // overscan_info_present_flag\n bitstream.readBits(1); // overscan_appropriate_flag\n }\n if (bitstream.readBits(1)) { // video_signal_type_present_flag\n bitstream.readBits(3); // video_format\n bitstream.readBits(1); // video_full_range_flag\n if (bitstream.readBits(1)) {\n bitstream.readBits(8); // colour_primaries\n bitstream.readBits(8); // transfer_characteristics\n bitstream.readBits(8); // matrix_coeffs\n }\n }\n if (bitstream.readBits(1)) { // chroma_loc_info_present_flag\n readExpGolomb(bitstream); // chroma_sample_loc_type_top_field\n readExpGolomb(bitstream); // chroma_sample_loc_type_bottom_field\n }\n bitstream.readBits(1); // neutral_chroma_indication_flag\n bitstream.readBits(1); // field_seq_flag\n bitstream.readBits(1); // frame_field_info_present_flag\n if (bitstream.readBits(1)) { // default_display_window_flag\n readExpGolomb(bitstream); // def_disp_win_left_offset\n readExpGolomb(bitstream); // def_disp_win_right_offset\n readExpGolomb(bitstream); // def_disp_win_top_offset\n readExpGolomb(bitstream); // def_disp_win_bottom_offset\n }\n if (bitstream.readBits(1)) { // vui_timing_info_present_flag\n bitstream.readBits(32); // vui_num_units_in_tick\n bitstream.readBits(32); // vui_time_scale\n if (bitstream.readBits(1)) { // vui_poc_proportional_to_timing_flag\n readExpGolomb(bitstream); // vui_num_ticks_poc_diff_one_minus1\n }\n if (bitstream.readBits(1)) {\n skipHrdParameters(bitstream, true, sps_max_sub_layers_minus1);\n }\n }\n if (bitstream.readBits(1)) { // bitstream_restriction_flag\n bitstream.readBits(1); // tiles_fixed_structure_flag\n bitstream.readBits(1); // motion_vectors_over_pic_boundaries_flag\n bitstream.readBits(1); // restricted_ref_pic_lists_flag\n const min_spatial_segmentation_idc = readExpGolomb(bitstream);\n // skip the rest\n readExpGolomb(bitstream); // max_bytes_per_pic_denom\n readExpGolomb(bitstream); // max_bits_per_min_cu_denom\n readExpGolomb(bitstream); // log2_max_mv_length_horizontal\n readExpGolomb(bitstream); // log2_max_mv_length_vertical\n return min_spatial_segmentation_idc;\n }\n return 0;\n};\nconst skipHrdParameters = (bitstream, commonInfPresentFlag, maxNumSubLayersMinus1) => {\n let nal_hrd_parameters_present_flag = false;\n let vcl_hrd_parameters_present_flag = false;\n let sub_pic_hrd_params_present_flag = false;\n if (commonInfPresentFlag) {\n nal_hrd_parameters_present_flag = bitstream.readBits(1) === 1;\n vcl_hrd_parameters_present_flag = bitstream.readBits(1) === 1;\n if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {\n sub_pic_hrd_params_present_flag = bitstream.readBits(1) === 1;\n if (sub_pic_hrd_params_present_flag) {\n bitstream.readBits(8); // tick_divisor_minus2\n bitstream.readBits(5); // du_cpb_removal_delay_increment_length_minus1\n bitstream.readBits(1); // sub_pic_cpb_params_in_pic_timing_sei_flag\n bitstream.readBits(5); // dpb_output_delay_du_length_minus1\n }\n bitstream.readBits(4); // bit_rate_scale\n bitstream.readBits(4); // cpb_size_scale\n if (sub_pic_hrd_params_present_flag) {\n bitstream.readBits(4); // cpb_size_du_scale\n }\n bitstream.readBits(5); // initial_cpb_removal_delay_length_minus1\n bitstream.readBits(5); // au_cpb_removal_delay_length_minus1\n bitstream.readBits(5); // dpb_output_delay_length_minus1\n }\n }\n for (let i = 0; i <= maxNumSubLayersMinus1; i++) {\n const fixed_pic_rate_general_flag = bitstream.readBits(1) === 1;\n let fixed_pic_rate_within_cvs_flag = true; // Default assumption if general is true\n if (!fixed_pic_rate_general_flag) {\n fixed_pic_rate_within_cvs_flag = bitstream.readBits(1) === 1;\n }\n let low_delay_hrd_flag = false; // Default assumption\n if (fixed_pic_rate_within_cvs_flag) {\n readExpGolomb(bitstream); // elemental_duration_in_tc_minus1[i]\n }\n else {\n low_delay_hrd_flag = bitstream.readBits(1) === 1;\n }\n let CpbCnt = 1; // Default if low_delay is true\n if (!low_delay_hrd_flag) {\n const cpb_cnt_minus1 = readExpGolomb(bitstream); // cpb_cnt_minus1[i]\n CpbCnt = cpb_cnt_minus1 + 1;\n }\n if (nal_hrd_parameters_present_flag) {\n skipSubLayerHrdParameters(bitstream, CpbCnt, sub_pic_hrd_params_present_flag);\n }\n if (vcl_hrd_parameters_present_flag) {\n skipSubLayerHrdParameters(bitstream, CpbCnt, sub_pic_hrd_params_present_flag);\n }\n }\n};\nconst skipSubLayerHrdParameters = (bitstream, CpbCnt, sub_pic_hrd_params_present_flag) => {\n for (let i = 0; i < CpbCnt; i++) {\n readExpGolomb(bitstream); // bit_rate_value_minus1[i]\n readExpGolomb(bitstream); // cpb_size_value_minus1[i]\n if (sub_pic_hrd_params_present_flag) {\n readExpGolomb(bitstream); // cpb_size_du_value_minus1[i]\n readExpGolomb(bitstream); // bit_rate_du_value_minus1[i]\n }\n bitstream.readBits(1); // cbr_flag[i]\n }\n};\n/** Serializes an HevcDecoderConfigurationRecord into the format specified in Section 8.3.3.1 of ISO 14496-15. */\nexport const serializeHevcDecoderConfigurationRecord = (record) => {\n const bytes = [];\n bytes.push(record.configurationVersion);\n bytes.push(((record.generalProfileSpace & 0x3) << 6)\n | ((record.generalTierFlag & 0x1) << 5)\n | (record.generalProfileIdc & 0x1F));\n bytes.push((record.generalProfileCompatibilityFlags >>> 24) & 0xFF);\n bytes.push((record.generalProfileCompatibilityFlags >>> 16) & 0xFF);\n bytes.push((record.generalProfileCompatibilityFlags >>> 8) & 0xFF);\n bytes.push(record.generalProfileCompatibilityFlags & 0xFF);\n bytes.push(...record.generalConstraintIndicatorFlags);\n bytes.push(record.generalLevelIdc & 0xFF);\n bytes.push(0xF0 | ((record.minSpatialSegmentationIdc >> 8) & 0x0F)); // Reserved + high nibble\n bytes.push(record.minSpatialSegmentationIdc & 0xFF); // Low byte\n bytes.push(0xFC | (record.parallelismType & 0x03));\n bytes.push(0xFC | (record.chromaFormatIdc & 0x03));\n bytes.push(0xF8 | (record.bitDepthLumaMinus8 & 0x07));\n bytes.push(0xF8 | (record.bitDepthChromaMinus8 & 0x07));\n bytes.push((record.avgFrameRate >> 8) & 0xFF); // High byte\n bytes.push(record.avgFrameRate & 0xFF); // Low byte\n bytes.push(((record.constantFrameRate & 0x03) << 6)\n | ((record.numTemporalLayers & 0x07) << 3)\n | ((record.temporalIdNested & 0x01) << 2)\n | (record.lengthSizeMinusOne & 0x03));\n bytes.push(record.arrays.length & 0xFF);\n for (const arr of record.arrays) {\n bytes.push(((arr.arrayCompleteness & 0x01) << 7)\n | (0 << 6)\n | (arr.nalUnitType & 0x3F));\n bytes.push((arr.nalUnits.length >> 8) & 0xFF); // High byte\n bytes.push(arr.nalUnits.length & 0xFF); // Low byte\n for (const nal of arr.nalUnits) {\n bytes.push((nal.length >> 8) & 0xFF); // High byte\n bytes.push(nal.length & 0xFF); // Low byte\n for (let i = 0; i < nal.length; i++) {\n bytes.push(nal[i]);\n }\n }\n }\n return new Uint8Array(bytes);\n};\nexport const extractVp9CodecInfoFromPacket = (packet) => {\n // eslint-disable-next-line @stylistic/max-len\n // https://storage.googleapis.com/downloads.webmproject.org/docs/vp9/vp9-bitstream-specification-v0.7-20170222-draft.pdf\n // http://downloads.webmproject.org/docs/vp9/vp9-bitstream_superframe-and-uncompressed-header_v1.0.pdf\n const bitstream = new Bitstream(packet);\n // Frame marker (0b10)\n const frameMarker = bitstream.readBits(2);\n if (frameMarker !== 2) {\n return null;\n }\n // Profile\n const profileLowBit = bitstream.readBits(1);\n const profileHighBit = bitstream.readBits(1);\n const profile = (profileHighBit << 1) + profileLowBit;\n // Skip reserved bit for profile 3\n if (profile === 3) {\n bitstream.skipBits(1);\n }\n // show_existing_frame\n const showExistingFrame = bitstream.readBits(1);\n if (showExistingFrame === 1) {\n return null;\n }\n // frame_type (0 = key frame)\n const frameType = bitstream.readBits(1);\n if (frameType !== 0) {\n return null;\n }\n // Skip show_frame and error_resilient_mode\n bitstream.skipBits(2);\n // Sync code (0x498342)\n const syncCode = bitstream.readBits(24);\n if (syncCode !== 0x498342) {\n return null;\n }\n // Color config\n let bitDepth = 8;\n if (profile >= 2) {\n const tenOrTwelveBit = bitstream.readBits(1);\n bitDepth = tenOrTwelveBit ? 12 : 10;\n }\n // Color space\n const colorSpace = bitstream.readBits(3);\n let chromaSubsampling = 0;\n let videoFullRangeFlag = 0;\n if (colorSpace !== 7) { // 7 is CS_RGB\n const colorRange = bitstream.readBits(1);\n videoFullRangeFlag = colorRange;\n if (profile === 1 || profile === 3) {\n const subsamplingX = bitstream.readBits(1);\n const subsamplingY = bitstream.readBits(1);\n // 0 = 4:2:0 vertical\n // 1 = 4:2:0 colocated\n // 2 = 4:2:2\n // 3 = 4:4:4\n chromaSubsampling = !subsamplingX && !subsamplingY\n ? 3 // 0,0 = 4:4:4\n : subsamplingX && !subsamplingY\n ? 2 // 1,0 = 4:2:2\n : 1; // 1,1 = 4:2:0 colocated (default)\n // Skip reserved bit\n bitstream.skipBits(1);\n }\n else {\n // For profile 0 and 2, always 4:2:0\n chromaSubsampling = 1; // Using colocated as default\n }\n }\n else {\n // RGB is always 4:4:4\n chromaSubsampling = 3;\n videoFullRangeFlag = 1;\n }\n // Parse frame size\n const widthMinusOne = bitstream.readBits(16);\n const heightMinusOne = bitstream.readBits(16);\n const width = widthMinusOne + 1;\n const height = heightMinusOne + 1;\n // Calculate level based on dimensions\n const pictureSize = width * height;\n let level = last(VP9_LEVEL_TABLE).level; // Default to highest level\n for (const entry of VP9_LEVEL_TABLE) {\n if (pictureSize <= entry.maxPictureSize) {\n level = entry.level;\n break;\n }\n }\n // Map color_space to standard values\n const matrixCoefficients = colorSpace === 7\n ? 0\n : colorSpace === 2\n ? 1\n : colorSpace === 1\n ? 6\n : 2;\n const colourPrimaries = colorSpace === 2\n ? 1\n : colorSpace === 1\n ? 6\n : 2;\n const transferCharacteristics = colorSpace === 2\n ? 1\n : colorSpace === 1\n ? 6\n : 2;\n return {\n profile,\n level,\n bitDepth,\n chromaSubsampling,\n videoFullRangeFlag,\n colourPrimaries,\n transferCharacteristics,\n matrixCoefficients,\n };\n};\n/** Iterates over all OBUs in an AV1 packet bistream. */\nexport const iterateAv1PacketObus = function* (packet) {\n // https://aomediacodec.github.io/av1-spec/av1-spec.pdf\n const bitstream = new Bitstream(packet);\n const readLeb128 = () => {\n let value = 0;\n for (let i = 0; i < 8; i++) {\n const byte = bitstream.readAlignedByte();\n value |= ((byte & 0x7f) << (i * 7));\n if (!(byte & 0x80)) {\n break;\n }\n // Spec requirement\n if (i === 7 && (byte & 0x80)) {\n return null;\n }\n }\n // Spec requirement\n if (value >= 2 ** 32 - 1) {\n return null;\n }\n return value;\n };\n while (bitstream.getBitsLeft() >= 8) {\n // Parse OBU header\n bitstream.skipBits(1);\n const obuType = bitstream.readBits(4);\n const obuExtension = bitstream.readBits(1);\n const obuHasSizeField = bitstream.readBits(1);\n bitstream.skipBits(1);\n // Skip extension header if present\n if (obuExtension) {\n bitstream.skipBits(8);\n }\n // Read OBU size if present\n let obuSize;\n if (obuHasSizeField) {\n const obuSizeValue = readLeb128();\n if (obuSizeValue === null)\n return; // It was invalid\n obuSize = obuSizeValue;\n }\n else {\n // Calculate remaining bits and convert to bytes, rounding down\n obuSize = Math.floor(bitstream.getBitsLeft() / 8);\n }\n assert(bitstream.pos % 8 === 0);\n yield {\n type: obuType,\n data: packet.subarray(bitstream.pos / 8, bitstream.pos / 8 + obuSize),\n };\n // Move to next OBU\n bitstream.skipBits(obuSize * 8);\n }\n};\n/**\n * When AV1 codec information is not provided by the container, we can still try to extract the information by digging\n * into the AV1 bitstream.\n */\nexport const extractAv1CodecInfoFromPacket = (packet) => {\n // https://aomediacodec.github.io/av1-spec/av1-spec.pdf\n for (const { type, data } of iterateAv1PacketObus(packet)) {\n if (type !== 1) {\n continue; // 1 == OBU_SEQUENCE_HEADER\n }\n const bitstream = new Bitstream(data);\n // Read sequence header fields\n const seqProfile = bitstream.readBits(3);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const stillPicture = bitstream.readBits(1);\n const reducedStillPictureHeader = bitstream.readBits(1);\n let seqLevel = 0;\n let seqTier = 0;\n let bufferDelayLengthMinus1 = 0;\n if (reducedStillPictureHeader) {\n seqLevel = bitstream.readBits(5);\n }\n else {\n // Parse timing_info_present_flag\n const timingInfoPresentFlag = bitstream.readBits(1);\n if (timingInfoPresentFlag) {\n // Skip timing info (num_units_in_display_tick, time_scale, equal_picture_interval)\n bitstream.skipBits(32); // num_units_in_display_tick\n bitstream.skipBits(32); // time_scale\n const equalPictureInterval = bitstream.readBits(1);\n if (equalPictureInterval) {\n // Skip num_ticks_per_picture_minus_1 (uvlc)\n // Since this is variable length, we'd need to implement uvlc reading\n // For now, we'll return null as this is rare\n return null;\n }\n }\n // Parse decoder_model_info_present_flag\n const decoderModelInfoPresentFlag = bitstream.readBits(1);\n if (decoderModelInfoPresentFlag) {\n // Store buffer_delay_length_minus_1 instead of just skipping\n bufferDelayLengthMinus1 = bitstream.readBits(5);\n bitstream.skipBits(32); // num_units_in_decoding_tick\n bitstream.skipBits(5); // buffer_removal_time_length_minus_1\n bitstream.skipBits(5); // frame_presentation_time_length_minus_1\n }\n // Parse operating_points_cnt_minus_1\n const operatingPointsCntMinus1 = bitstream.readBits(5);\n // For each operating point\n for (let i = 0; i <= operatingPointsCntMinus1; i++) {\n // operating_point_idc[i]\n bitstream.skipBits(12);\n // seq_level_idx[i]\n const seqLevelIdx = bitstream.readBits(5);\n if (i === 0) {\n seqLevel = seqLevelIdx;\n }\n if (seqLevelIdx > 7) {\n // seq_tier[i]\n const seqTierTemp = bitstream.readBits(1);\n if (i === 0) {\n seqTier = seqTierTemp;\n }\n }\n if (decoderModelInfoPresentFlag) {\n // decoder_model_present_for_this_op[i]\n const decoderModelPresentForThisOp = bitstream.readBits(1);\n if (decoderModelPresentForThisOp) {\n const n = bufferDelayLengthMinus1 + 1;\n bitstream.skipBits(n); // decoder_buffer_delay[op]\n bitstream.skipBits(n); // encoder_buffer_delay[op]\n bitstream.skipBits(1); // low_delay_mode_flag[op]\n }\n }\n // initial_display_delay_present_flag\n const initialDisplayDelayPresentFlag = bitstream.readBits(1);\n if (initialDisplayDelayPresentFlag) {\n // initial_display_delay_minus_1[i]\n bitstream.skipBits(4);\n }\n }\n }\n const highBitdepth = bitstream.readBits(1);\n let bitDepth = 8;\n if (seqProfile === 2 && highBitdepth) {\n const twelveBit = bitstream.readBits(1);\n bitDepth = twelveBit ? 12 : 10;\n }\n else if (seqProfile <= 2) {\n bitDepth = highBitdepth ? 10 : 8;\n }\n let monochrome = 0;\n if (seqProfile !== 1) {\n monochrome = bitstream.readBits(1);\n }\n let chromaSubsamplingX = 1;\n let chromaSubsamplingY = 1;\n let chromaSamplePosition = 0;\n if (!monochrome) {\n if (seqProfile === 0) {\n chromaSubsamplingX = 1;\n chromaSubsamplingY = 1;\n }\n else if (seqProfile === 1) {\n chromaSubsamplingX = 0;\n chromaSubsamplingY = 0;\n }\n else {\n if (bitDepth === 12) {\n chromaSubsamplingX = bitstream.readBits(1);\n if (chromaSubsamplingX) {\n chromaSubsamplingY = bitstream.readBits(1);\n }\n }\n }\n if (chromaSubsamplingX && chromaSubsamplingY) {\n chromaSamplePosition = bitstream.readBits(2);\n }\n }\n return {\n profile: seqProfile,\n level: seqLevel,\n tier: seqTier,\n bitDepth,\n monochrome,\n chromaSubsamplingX,\n chromaSubsamplingY,\n chromaSamplePosition,\n };\n }\n return null;\n};\nexport const parseOpusIdentificationHeader = (bytes) => {\n const view = toDataView(bytes);\n const outputChannelCount = view.getUint8(9);\n const preSkip = view.getUint16(10, true);\n const inputSampleRate = view.getUint32(12, true);\n const outputGain = view.getInt16(16, true);\n const channelMappingFamily = view.getUint8(18);\n let channelMappingTable = null;\n if (channelMappingFamily) {\n channelMappingTable = bytes.subarray(19, 19 + 2 + outputChannelCount);\n }\n return {\n outputChannelCount,\n preSkip,\n inputSampleRate,\n outputGain,\n channelMappingFamily,\n channelMappingTable,\n };\n};\n// From https://datatracker.ietf.org/doc/html/rfc6716, in 48 kHz samples\nconst OPUS_FRAME_DURATION_TABLE = [\n 480, 960, 1920, 2880,\n 480, 960, 1920, 2880,\n 480, 960, 1920, 2880,\n 480, 960,\n 480, 960,\n 120, 240, 480, 960,\n 120, 240, 480, 960,\n 120, 240, 480, 960,\n 120, 240, 480, 960,\n];\nexport const parseOpusTocByte = (packet) => {\n const config = packet[0] >> 3;\n return {\n durationInSamples: OPUS_FRAME_DURATION_TABLE[config],\n };\n};\n// Based on vorbis_parser.c from FFmpeg.\nexport const parseModesFromVorbisSetupPacket = (setupHeader) => {\n // Verify that this is a Setup header.\n if (setupHeader.length < 7) {\n throw new Error('Setup header is too short.');\n }\n if (setupHeader[0] !== 5) {\n throw new Error('Wrong packet type in Setup header.');\n }\n const signature = String.fromCharCode(...setupHeader.slice(1, 7));\n if (signature !== 'vorbis') {\n throw new Error('Invalid packet signature in Setup header.');\n }\n // Reverse the entire buffer.\n const bufSize = setupHeader.length;\n const revBuffer = new Uint8Array(bufSize);\n for (let i = 0; i < bufSize; i++) {\n revBuffer[i] = setupHeader[bufSize - 1 - i];\n }\n // Initialize a Bitstream on the reversed buffer.\n const bitstream = new Bitstream(revBuffer);\n // --- Find the framing bit.\n // In FFmpeg code, we scan until get_bits1() returns 1.\n let gotFramingBit = 0;\n while (bitstream.getBitsLeft() > 97) {\n if (bitstream.readBits(1) === 1) {\n gotFramingBit = bitstream.pos;\n break;\n }\n }\n if (gotFramingBit === 0) {\n throw new Error('Invalid Setup header: framing bit not found.');\n }\n // --- Search backwards for a valid mode header.\n // We try to “guess” the number of modes by reading a fixed pattern.\n let modeCount = 0;\n let gotModeHeader = false;\n let lastModeCount = 0;\n while (bitstream.getBitsLeft() >= 97) {\n const tempPos = bitstream.pos;\n const a = bitstream.readBits(8);\n const b = bitstream.readBits(16);\n const c = bitstream.readBits(16);\n // If a > 63 or b or c nonzero, assume we’ve gone too far.\n if (a > 63 || b !== 0 || c !== 0) {\n bitstream.pos = tempPos;\n break;\n }\n bitstream.skipBits(1);\n modeCount++;\n if (modeCount > 64) {\n break;\n }\n const bsClone = bitstream.clone();\n const candidate = bsClone.readBits(6) + 1;\n if (candidate === modeCount) {\n gotModeHeader = true;\n lastModeCount = modeCount;\n }\n }\n if (!gotModeHeader) {\n throw new Error('Invalid Setup header: mode header not found.');\n }\n if (lastModeCount > 63) {\n throw new Error(`Unsupported mode count: ${lastModeCount}.`);\n }\n const finalModeCount = lastModeCount;\n // --- Reinitialize the bitstream.\n bitstream.pos = 0;\n // Skip the bits up to the found framing bit.\n bitstream.skipBits(gotFramingBit);\n // --- Now read, for each mode (in reverse order), 40 bits then one bit.\n // That one bit is the mode blockflag.\n const modeBlockflags = Array(finalModeCount).fill(0);\n for (let i = finalModeCount - 1; i >= 0; i--) {\n bitstream.skipBits(40);\n modeBlockflags[i] = bitstream.readBits(1);\n }\n return { modeBlockflags };\n};\n/** Determines a packet's type (key or delta) by digging into the packet bitstream. */\nexport const determineVideoPacketType = (codec, decoderConfig, packetData) => {\n switch (codec) {\n case 'avc':\n {\n const nalUnits = extractAvcNalUnits(packetData, decoderConfig);\n const isKeyframe = nalUnits.some(x => extractNalUnitTypeForAvc(x) === AvcNalUnitType.IDR);\n return isKeyframe ? 'key' : 'delta';\n }\n ;\n case 'hevc':\n {\n const nalUnits = extractHevcNalUnits(packetData, decoderConfig);\n const isKeyframe = nalUnits.some((x) => {\n const type = extractNalUnitTypeForHevc(x);\n return HevcNalUnitType.BLA_W_LP <= type && type <= HevcNalUnitType.RSV_IRAP_VCL23;\n });\n return isKeyframe ? 'key' : 'delta';\n }\n ;\n case 'vp8':\n {\n // VP8, once again, by far the easiest to deal with.\n const frameType = packetData[0] & 0b1;\n return frameType === 0 ? 'key' : 'delta';\n }\n ;\n case 'vp9':\n {\n const bitstream = new Bitstream(packetData);\n if (bitstream.readBits(2) !== 2) {\n return null;\n }\n ;\n const profileLowBit = bitstream.readBits(1);\n const profileHighBit = bitstream.readBits(1);\n const profile = (profileHighBit << 1) + profileLowBit;\n // Skip reserved bit for profile 3\n if (profile === 3) {\n bitstream.skipBits(1);\n }\n const showExistingFrame = bitstream.readBits(1);\n if (showExistingFrame) {\n return null;\n }\n const frameType = bitstream.readBits(1);\n return frameType === 0 ? 'key' : 'delta';\n }\n ;\n case 'av1':\n {\n let reducedStillPictureHeader = false;\n for (const { type, data } of iterateAv1PacketObus(packetData)) {\n if (type === 1) { // OBU_SEQUENCE_HEADER\n const bitstream = new Bitstream(data);\n bitstream.skipBits(4);\n reducedStillPictureHeader = !!bitstream.readBits(1);\n }\n else if (type === 3 // OBU_FRAME_HEADER\n || type === 6 // OBU_FRAME\n || type === 7 // OBU_REDUNDANT_FRAME_HEADER\n ) {\n if (reducedStillPictureHeader) {\n return 'key';\n }\n const bitstream = new Bitstream(data);\n const showExistingFrame = bitstream.readBits(1);\n if (showExistingFrame) {\n return null;\n }\n const frameType = bitstream.readBits(2);\n return frameType === 0 ? 'key' : 'delta';\n }\n }\n return null;\n }\n ;\n default:\n {\n assertNever(codec);\n assert(false);\n }\n ;\n }\n};\nexport var FlacBlockType;\n(function (FlacBlockType) {\n FlacBlockType[FlacBlockType[\"STREAMINFO\"] = 0] = \"STREAMINFO\";\n FlacBlockType[FlacBlockType[\"VORBIS_COMMENT\"] = 4] = \"VORBIS_COMMENT\";\n FlacBlockType[FlacBlockType[\"PICTURE\"] = 6] = \"PICTURE\";\n})(FlacBlockType || (FlacBlockType = {}));\nexport const readVorbisComments = (bytes, metadataTags) => {\n // https://datatracker.ietf.org/doc/html/rfc7845#section-5.2\n const commentView = toDataView(bytes);\n let commentPos = 0;\n const vendorStringLength = commentView.getUint32(commentPos, true);\n commentPos += 4;\n const vendorString = textDecoder.decode(bytes.subarray(commentPos, commentPos + vendorStringLength));\n commentPos += vendorStringLength;\n if (vendorStringLength > 0) {\n // Expose the vendor string in the raw metadata\n metadataTags.raw ??= {};\n metadataTags.raw['vendor'] ??= vendorString;\n }\n const listLength = commentView.getUint32(commentPos, true);\n commentPos += 4;\n // Loop over all metadata tags\n for (let i = 0; i < listLength; i++) {\n const stringLength = commentView.getUint32(commentPos, true);\n commentPos += 4;\n const string = textDecoder.decode(bytes.subarray(commentPos, commentPos + stringLength));\n commentPos += stringLength;\n const separatorIndex = string.indexOf('=');\n if (separatorIndex === -1) {\n continue;\n }\n const key = string.slice(0, separatorIndex).toUpperCase();\n const value = string.slice(separatorIndex + 1);\n metadataTags.raw ??= {};\n metadataTags.raw[key] ??= value;\n switch (key) {\n case 'TITLE':\n {\n metadataTags.title ??= value;\n }\n ;\n break;\n case 'DESCRIPTION':\n {\n metadataTags.description ??= value;\n }\n ;\n break;\n case 'ARTIST':\n {\n metadataTags.artist ??= value;\n }\n ;\n break;\n case 'ALBUM':\n {\n metadataTags.album ??= value;\n }\n ;\n break;\n case 'ALBUMARTIST':\n {\n metadataTags.albumArtist ??= value;\n }\n ;\n break;\n case 'COMMENT':\n {\n metadataTags.comment ??= value;\n }\n ;\n break;\n case 'LYRICS':\n {\n metadataTags.lyrics ??= value;\n }\n ;\n break;\n case 'TRACKNUMBER':\n {\n const parts = value.split('/');\n const trackNum = Number.parseInt(parts[0], 10);\n const tracksTotal = parts[1] && Number.parseInt(parts[1], 10);\n if (Number.isInteger(trackNum) && trackNum > 0) {\n metadataTags.trackNumber ??= trackNum;\n }\n if (tracksTotal && Number.isInteger(tracksTotal) && tracksTotal > 0) {\n metadataTags.tracksTotal ??= tracksTotal;\n }\n }\n ;\n break;\n case 'TRACKTOTAL':\n {\n const tracksTotal = Number.parseInt(value, 10);\n if (Number.isInteger(tracksTotal) && tracksTotal > 0) {\n metadataTags.tracksTotal ??= tracksTotal;\n }\n }\n ;\n break;\n case 'DISCNUMBER':\n {\n const parts = value.split('/');\n const discNum = Number.parseInt(parts[0], 10);\n const discsTotal = parts[1] && Number.parseInt(parts[1], 10);\n if (Number.isInteger(discNum) && discNum > 0) {\n metadataTags.discNumber ??= discNum;\n }\n if (discsTotal && Number.isInteger(discsTotal) && discsTotal > 0) {\n metadataTags.discsTotal ??= discsTotal;\n }\n }\n ;\n break;\n case 'DISCTOTAL':\n {\n const discsTotal = Number.parseInt(value, 10);\n if (Number.isInteger(discsTotal) && discsTotal > 0) {\n metadataTags.discsTotal ??= discsTotal;\n }\n }\n ;\n break;\n case 'DATE':\n {\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) {\n metadataTags.date ??= date;\n }\n }\n ;\n break;\n case 'GENRE':\n {\n metadataTags.genre ??= value;\n }\n ;\n break;\n case 'METADATA_BLOCK_PICTURE':\n {\n // https://datatracker.ietf.org/doc/rfc9639/ Section 8.8\n const decoded = base64ToBytes(value);\n const view = toDataView(decoded);\n const pictureType = view.getUint32(0, false);\n const mediaTypeLength = view.getUint32(4, false);\n const mediaType = String.fromCharCode(...decoded.subarray(8, 8 + mediaTypeLength)); // ASCII\n const descriptionLength = view.getUint32(8 + mediaTypeLength, false);\n const description = textDecoder.decode(decoded.subarray(12 + mediaTypeLength, 12 + mediaTypeLength + descriptionLength));\n const dataLength = view.getUint32(mediaTypeLength + descriptionLength + 28);\n const data = decoded.subarray(mediaTypeLength + descriptionLength + 32, mediaTypeLength + descriptionLength + 32 + dataLength);\n metadataTags.images ??= [];\n metadataTags.images.push({\n data,\n mimeType: mediaType,\n kind: pictureType === 3 ? 'coverFront' : pictureType === 4 ? 'coverBack' : 'unknown',\n name: undefined,\n description: description || undefined,\n });\n }\n ;\n break;\n }\n }\n};\nexport const createVorbisComments = (headerBytes, tags, writeImages) => {\n // https://datatracker.ietf.org/doc/html/rfc7845#section-5.2\n const commentHeaderParts = [\n headerBytes,\n ];\n const vendorString = 'Mediabunny';\n const encodedVendorString = textEncoder.encode(vendorString);\n let currentBuffer = new Uint8Array(4 + encodedVendorString.length);\n let currentView = new DataView(currentBuffer.buffer);\n currentView.setUint32(0, encodedVendorString.length, true);\n currentBuffer.set(encodedVendorString, 4);\n commentHeaderParts.push(currentBuffer);\n const writtenTags = new Set();\n const addCommentTag = (key, value) => {\n const joined = `${key}=${value}`;\n const encoded = textEncoder.encode(joined);\n currentBuffer = new Uint8Array(4 + encoded.length);\n currentView = new DataView(currentBuffer.buffer);\n currentView.setUint32(0, encoded.length, true);\n currentBuffer.set(encoded, 4);\n commentHeaderParts.push(currentBuffer);\n writtenTags.add(key);\n };\n for (const { key, value } of keyValueIterator(tags)) {\n switch (key) {\n case 'title':\n {\n addCommentTag('TITLE', value);\n }\n ;\n break;\n case 'description':\n {\n addCommentTag('DESCRIPTION', value);\n }\n ;\n break;\n case 'artist':\n {\n addCommentTag('ARTIST', value);\n }\n ;\n break;\n case 'album':\n {\n addCommentTag('ALBUM', value);\n }\n ;\n break;\n case 'albumArtist':\n {\n addCommentTag('ALBUMARTIST', value);\n }\n ;\n break;\n case 'genre':\n {\n addCommentTag('GENRE', value);\n }\n ;\n break;\n case 'date':\n {\n const rawVersion = tags.raw?.['DATE'] ?? tags.raw?.['date'];\n if (rawVersion && typeof rawVersion === 'string') {\n addCommentTag('DATE', rawVersion);\n }\n else {\n addCommentTag('DATE', value.toISOString().slice(0, 10));\n }\n }\n ;\n break;\n case 'comment':\n {\n addCommentTag('COMMENT', value);\n }\n ;\n break;\n case 'lyrics':\n {\n addCommentTag('LYRICS', value);\n }\n ;\n break;\n case 'trackNumber':\n {\n addCommentTag('TRACKNUMBER', value.toString());\n }\n ;\n break;\n case 'tracksTotal':\n {\n addCommentTag('TRACKTOTAL', value.toString());\n }\n ;\n break;\n case 'discNumber':\n {\n addCommentTag('DISCNUMBER', value.toString());\n }\n ;\n break;\n case 'discsTotal':\n {\n addCommentTag('DISCTOTAL', value.toString());\n }\n ;\n break;\n case 'images':\n {\n // For example, in .flac, we put the pictures in a different section,\n // not in the Vorbis comment header.\n if (!writeImages) {\n break;\n }\n for (const image of value) {\n // https://datatracker.ietf.org/doc/rfc9639/ Section 8.8\n const pictureType = image.kind === 'coverFront' ? 3 : image.kind === 'coverBack' ? 4 : 0;\n const encodedMediaType = new Uint8Array(image.mimeType.length);\n for (let i = 0; i < image.mimeType.length; i++) {\n encodedMediaType[i] = image.mimeType.charCodeAt(i);\n }\n const encodedDescription = textEncoder.encode(image.description ?? '');\n const buffer = new Uint8Array(4 // Picture type\n + 4 // MIME type length\n + encodedMediaType.length // MIME type\n + 4 // Description length\n + encodedDescription.length // Description\n + 16 // Width, height, color depth, number of colors\n + 4 // Picture data length\n + image.data.length);\n const view = toDataView(buffer);\n view.setUint32(0, pictureType, false);\n view.setUint32(4, encodedMediaType.length, false);\n buffer.set(encodedMediaType, 8);\n view.setUint32(8 + encodedMediaType.length, encodedDescription.length, false);\n buffer.set(encodedDescription, 12 + encodedMediaType.length);\n // Skip a bunch of fields (width, height, color depth, number of colors)\n view.setUint32(28 + encodedMediaType.length + encodedDescription.length, image.data.length, false);\n buffer.set(image.data, 32 + encodedMediaType.length + encodedDescription.length);\n const encoded = bytesToBase64(buffer);\n addCommentTag('METADATA_BLOCK_PICTURE', encoded);\n }\n }\n ;\n break;\n case 'raw':\n {\n // Handled later\n }\n ;\n break;\n default: assertNever(key);\n }\n }\n if (tags.raw) {\n for (const key in tags.raw) {\n const value = tags.raw[key] ?? tags.raw[key.toLowerCase()];\n if (key === 'vendor' || value == null || writtenTags.has(key)) {\n continue;\n }\n if (typeof value === 'string') {\n addCommentTag(key, value);\n }\n }\n }\n const listLengthBuffer = new Uint8Array(4);\n toDataView(listLengthBuffer).setUint32(0, writtenTags.size, true);\n commentHeaderParts.splice(2, 0, listLengthBuffer); // Insert after the header and vendor section\n // Merge all comment header parts into a single buffer\n const commentHeaderLength = commentHeaderParts.reduce((a, b) => a + b.length, 0);\n const commentHeader = new Uint8Array(commentHeaderLength);\n let pos = 0;\n for (const part of commentHeaderParts) {\n commentHeader.set(part, pos);\n pos += part.length;\n }\n return commentHeader;\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { SECOND_TO_MICROSECOND_FACTOR } from './misc.js';\nexport const PLACEHOLDER_DATA = /* #__PURE__ */ new Uint8Array(0);\n/**\n * Represents an encoded chunk of media. Mainly used as an expressive wrapper around WebCodecs API's\n * [`EncodedVideoChunk`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedVideoChunk) and\n * [`EncodedAudioChunk`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedAudioChunk), but can also be used\n * standalone.\n * @group Packets\n * @public\n */\nexport class EncodedPacket {\n /** Creates a new {@link EncodedPacket} from raw bytes and timing information. */\n constructor(\n /** The encoded data of this packet. */\n data, \n /** The type of this packet. */\n type, \n /**\n * The presentation timestamp of this packet in seconds. May be negative. Samples with negative end timestamps\n * should not be presented.\n */\n timestamp, \n /** The duration of this packet in seconds. */\n duration, \n /**\n * The sequence number indicates the decode order of the packets. Packet A must be decoded before packet B if A\n * has a lower sequence number than B. If two packets have the same sequence number, they are the same packet.\n * Otherwise, sequence numbers are arbitrary and are not guaranteed to have any meaning besides their relative\n * ordering. Negative sequence numbers mean the sequence number is undefined.\n */\n sequenceNumber = -1, byteLength, sideData) {\n this.data = data;\n this.type = type;\n this.timestamp = timestamp;\n this.duration = duration;\n this.sequenceNumber = sequenceNumber;\n if (data === PLACEHOLDER_DATA && byteLength === undefined) {\n throw new Error('Internal error: byteLength must be explicitly provided when constructing metadata-only packets.');\n }\n if (byteLength === undefined) {\n byteLength = data.byteLength;\n }\n if (!(data instanceof Uint8Array)) {\n throw new TypeError('data must be a Uint8Array.');\n }\n if (type !== 'key' && type !== 'delta') {\n throw new TypeError('type must be either \"key\" or \"delta\".');\n }\n if (!Number.isFinite(timestamp)) {\n throw new TypeError('timestamp must be a number.');\n }\n if (!Number.isFinite(duration) || duration < 0) {\n throw new TypeError('duration must be a non-negative number.');\n }\n if (!Number.isFinite(sequenceNumber)) {\n throw new TypeError('sequenceNumber must be a number.');\n }\n if (!Number.isInteger(byteLength) || byteLength < 0) {\n throw new TypeError('byteLength must be a non-negative integer.');\n }\n if (sideData !== undefined && (typeof sideData !== 'object' || !sideData)) {\n throw new TypeError('sideData, when provided, must be an object.');\n }\n if (sideData?.alpha !== undefined && !(sideData.alpha instanceof Uint8Array)) {\n throw new TypeError('sideData.alpha, when provided, must be a Uint8Array.');\n }\n if (sideData?.alphaByteLength !== undefined\n && (!Number.isInteger(sideData.alphaByteLength) || sideData.alphaByteLength < 0)) {\n throw new TypeError('sideData.alphaByteLength, when provided, must be a non-negative integer.');\n }\n this.byteLength = byteLength;\n this.sideData = sideData ?? {};\n if (this.sideData.alpha && this.sideData.alphaByteLength === undefined) {\n this.sideData.alphaByteLength = this.sideData.alpha.byteLength;\n }\n }\n /**\n * If this packet is a metadata-only packet. Metadata-only packets don't contain their packet data. They are the\n * result of retrieving packets with {@link PacketRetrievalOptions.metadataOnly} set to `true`.\n */\n get isMetadataOnly() {\n return this.data === PLACEHOLDER_DATA;\n }\n /** The timestamp of this packet in microseconds. */\n get microsecondTimestamp() {\n return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.timestamp);\n }\n /** The duration of this packet in microseconds. */\n get microsecondDuration() {\n return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.duration);\n }\n /** Converts this packet to an\n * [`EncodedVideoChunk`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedVideoChunk) for use with the\n * WebCodecs API. */\n toEncodedVideoChunk() {\n if (this.isMetadataOnly) {\n throw new TypeError('Metadata-only packets cannot be converted to a video chunk.');\n }\n if (typeof EncodedVideoChunk === 'undefined') {\n throw new Error('Your browser does not support EncodedVideoChunk.');\n }\n return new EncodedVideoChunk({\n data: this.data,\n type: this.type,\n timestamp: this.microsecondTimestamp,\n duration: this.microsecondDuration,\n });\n }\n /**\n * Converts this packet to an\n * [`EncodedVideoChunk`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedVideoChunk) for use with the\n * WebCodecs API, using the alpha side data instead of the color data. Throws if no alpha side data is defined.\n */\n alphaToEncodedVideoChunk(type = this.type) {\n if (!this.sideData.alpha) {\n throw new TypeError('This packet does not contain alpha side data.');\n }\n if (this.isMetadataOnly) {\n throw new TypeError('Metadata-only packets cannot be converted to a video chunk.');\n }\n if (typeof EncodedVideoChunk === 'undefined') {\n throw new Error('Your browser does not support EncodedVideoChunk.');\n }\n return new EncodedVideoChunk({\n data: this.sideData.alpha,\n type,\n timestamp: this.microsecondTimestamp,\n duration: this.microsecondDuration,\n });\n }\n /** Converts this packet to an\n * [`EncodedAudioChunk`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedAudioChunk) for use with the\n * WebCodecs API. */\n toEncodedAudioChunk() {\n if (this.isMetadataOnly) {\n throw new TypeError('Metadata-only packets cannot be converted to an audio chunk.');\n }\n if (typeof EncodedAudioChunk === 'undefined') {\n throw new Error('Your browser does not support EncodedAudioChunk.');\n }\n return new EncodedAudioChunk({\n data: this.data,\n type: this.type,\n timestamp: this.microsecondTimestamp,\n duration: this.microsecondDuration,\n });\n }\n /**\n * Creates an {@link EncodedPacket} from an\n * [`EncodedVideoChunk`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedVideoChunk) or\n * [`EncodedAudioChunk`](https://developer.mozilla.org/en-US/docs/Web/API/EncodedAudioChunk). This method is useful\n * for converting chunks from the WebCodecs API to `EncodedPacket` instances.\n */\n static fromEncodedChunk(chunk, sideData) {\n if (!(chunk instanceof EncodedVideoChunk || chunk instanceof EncodedAudioChunk)) {\n throw new TypeError('chunk must be an EncodedVideoChunk or EncodedAudioChunk.');\n }\n const data = new Uint8Array(chunk.byteLength);\n chunk.copyTo(data);\n return new EncodedPacket(data, chunk.type, chunk.timestamp / 1e6, (chunk.duration ?? 0) / 1e6, undefined, undefined, sideData);\n }\n /** Clones this packet while optionally updating timing information. */\n clone(options) {\n if (options !== undefined && (typeof options !== 'object' || options === null)) {\n throw new TypeError('options, when provided, must be an object.');\n }\n if (options?.timestamp !== undefined && !Number.isFinite(options.timestamp)) {\n throw new TypeError('options.timestamp, when provided, must be a number.');\n }\n if (options?.duration !== undefined && !Number.isFinite(options.duration)) {\n throw new TypeError('options.duration, when provided, must be a number.');\n }\n return new EncodedPacket(this.data, this.type, options?.timestamp ?? this.timestamp, options?.duration ?? this.duration, this.sequenceNumber, this.byteLength);\n }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { assertNever, textDecoder, textEncoder } from '../misc.js';\nimport { readBytes, readF32Be, readF64Be, readU8 } from '../reader.js';\n/** Wrapper around a number to be able to differentiate it in the writer. */\nexport class EBMLFloat32 {\n constructor(value) {\n this.value = value;\n }\n}\n/** Wrapper around a number to be able to differentiate it in the writer. */\nexport class EBMLFloat64 {\n constructor(value) {\n this.value = value;\n }\n}\n/** Wrapper around a number to be able to differentiate it in the writer. */\nexport class EBMLSignedInt {\n constructor(value) {\n this.value = value;\n }\n}\nexport class EBMLUnicodeString {\n constructor(value) {\n this.value = value;\n }\n}\n/** Defines some of the EBML IDs used by Matroska files. */\nexport var EBMLId;\n(function (EBMLId) {\n EBMLId[EBMLId[\"EBML\"] = 440786851] = \"EBML\";\n EBMLId[EBMLId[\"EBMLVersion\"] = 17030] = \"EBMLVersion\";\n EBMLId[EBMLId[\"EBMLReadVersion\"] = 17143] = \"EBMLReadVersion\";\n EBMLId[EBMLId[\"EBMLMaxIDLength\"] = 17138] = \"EBMLMaxIDLength\";\n EBMLId[EBMLId[\"EBMLMaxSizeLength\"] = 17139] = \"EBMLMaxSizeLength\";\n EBMLId[EBMLId[\"DocType\"] = 17026] = \"DocType\";\n EBMLId[EBMLId[\"DocTypeVersion\"] = 17031] = \"DocTypeVersion\";\n EBMLId[EBMLId[\"DocTypeReadVersion\"] = 17029] = \"DocTypeReadVersion\";\n EBMLId[EBMLId[\"Void\"] = 236] = \"Void\";\n EBMLId[EBMLId[\"Segment\"] = 408125543] = \"Segment\";\n EBMLId[EBMLId[\"SeekHead\"] = 290298740] = \"SeekHead\";\n EBMLId[EBMLId[\"Seek\"] = 19899] = \"Seek\";\n EBMLId[EBMLId[\"SeekID\"] = 21419] = \"SeekID\";\n EBMLId[EBMLId[\"SeekPosition\"] = 21420] = \"SeekPosition\";\n EBMLId[EBMLId[\"Duration\"] = 17545] = \"Duration\";\n EBMLId[EBMLId[\"Info\"] = 357149030] = \"Info\";\n EBMLId[EBMLId[\"TimestampScale\"] = 2807729] = \"TimestampScale\";\n EBMLId[EBMLId[\"MuxingApp\"] = 19840] = \"MuxingApp\";\n EBMLId[EBMLId[\"WritingApp\"] = 22337] = \"WritingApp\";\n EBMLId[EBMLId[\"Tracks\"] = 374648427] = \"Tracks\";\n EBMLId[EBMLId[\"TrackEntry\"] = 174] = \"TrackEntry\";\n EBMLId[EBMLId[\"TrackNumber\"] = 215] = \"TrackNumber\";\n EBMLId[EBMLId[\"TrackUID\"] = 29637] = \"TrackUID\";\n EBMLId[EBMLId[\"TrackType\"] = 131] = \"TrackType\";\n EBMLId[EBMLId[\"FlagEnabled\"] = 185] = \"FlagEnabled\";\n EBMLId[EBMLId[\"FlagDefault\"] = 136] = \"FlagDefault\";\n EBMLId[EBMLId[\"FlagForced\"] = 21930] = \"FlagForced\";\n EBMLId[EBMLId[\"FlagOriginal\"] = 21934] = \"FlagOriginal\";\n EBMLId[EBMLId[\"FlagHearingImpaired\"] = 21931] = \"FlagHearingImpaired\";\n EBMLId[EBMLId[\"FlagVisualImpaired\"] = 21932] = \"FlagVisualImpaired\";\n EBMLId[EBMLId[\"FlagCommentary\"] = 21935] = \"FlagCommentary\";\n EBMLId[EBMLId[\"FlagLacing\"] = 156] = \"FlagLacing\";\n EBMLId[EBMLId[\"Name\"] = 21358] = \"Name\";\n EBMLId[EBMLId[\"Language\"] = 2274716] = \"Language\";\n EBMLId[EBMLId[\"LanguageBCP47\"] = 2274717] = \"LanguageBCP47\";\n EBMLId[EBMLId[\"CodecID\"] = 134] = \"CodecID\";\n EBMLId[EBMLId[\"CodecPrivate\"] = 25506] = \"CodecPrivate\";\n EBMLId[EBMLId[\"CodecDelay\"] = 22186] = \"CodecDelay\";\n EBMLId[EBMLId[\"SeekPreRoll\"] = 22203] = \"SeekPreRoll\";\n EBMLId[EBMLId[\"DefaultDuration\"] = 2352003] = \"DefaultDuration\";\n EBMLId[EBMLId[\"Video\"] = 224] = \"Video\";\n EBMLId[EBMLId[\"PixelWidth\"] = 176] = \"PixelWidth\";\n EBMLId[EBMLId[\"PixelHeight\"] = 186] = \"PixelHeight\";\n EBMLId[EBMLId[\"AlphaMode\"] = 21440] = \"AlphaMode\";\n EBMLId[EBMLId[\"Audio\"] = 225] = \"Audio\";\n EBMLId[EBMLId[\"SamplingFrequency\"] = 181] = \"SamplingFrequency\";\n EBMLId[EBMLId[\"Channels\"] = 159] = \"Channels\";\n EBMLId[EBMLId[\"BitDepth\"] = 25188] = \"BitDepth\";\n EBMLId[EBMLId[\"SimpleBlock\"] = 163] = \"SimpleBlock\";\n EBMLId[EBMLId[\"BlockGroup\"] = 160] = \"BlockGroup\";\n EBMLId[EBMLId[\"Block\"] = 161] = \"Block\";\n EBMLId[EBMLId[\"BlockAdditions\"] = 30113] = \"BlockAdditions\";\n EBMLId[EBMLId[\"BlockMore\"] = 166] = \"BlockMore\";\n EBMLId[EBMLId[\"BlockAdditional\"] = 165] = \"BlockAdditional\";\n EBMLId[EBMLId[\"BlockAddID\"] = 238] = \"BlockAddID\";\n EBMLId[EBMLId[\"BlockDuration\"] = 155] = \"BlockDuration\";\n EBMLId[EBMLId[\"ReferenceBlock\"] = 251] = \"ReferenceBlock\";\n EBMLId[EBMLId[\"Cluster\"] = 524531317] = \"Cluster\";\n EBMLId[EBMLId[\"Timestamp\"] = 231] = \"Timestamp\";\n EBMLId[EBMLId[\"Cues\"] = 475249515] = \"Cues\";\n EBMLId[EBMLId[\"CuePoint\"] = 187] = \"CuePoint\";\n EBMLId[EBMLId[\"CueTime\"] = 179] = \"CueTime\";\n EBMLId[EBMLId[\"CueTrackPositions\"] = 183] = \"CueTrackPositions\";\n EBMLId[EBMLId[\"CueTrack\"] = 247] = \"CueTrack\";\n EBMLId[EBMLId[\"CueClusterPosition\"] = 241] = \"CueClusterPosition\";\n EBMLId[EBMLId[\"Colour\"] = 21936] = \"Colour\";\n EBMLId[EBMLId[\"MatrixCoefficients\"] = 21937] = \"MatrixCoefficients\";\n EBMLId[EBMLId[\"TransferCharacteristics\"] = 21946] = \"TransferCharacteristics\";\n EBMLId[EBMLId[\"Primaries\"] = 21947] = \"Primaries\";\n EBMLId[EBMLId[\"Range\"] = 21945] = \"Range\";\n EBMLId[EBMLId[\"Projection\"] = 30320] = \"Projection\";\n EBMLId[EBMLId[\"ProjectionType\"] = 30321] = \"ProjectionType\";\n EBMLId[EBMLId[\"ProjectionPoseRoll\"] = 30325] = \"ProjectionPoseRoll\";\n EBMLId[EBMLId[\"Attachments\"] = 423732329] = \"Attachments\";\n EBMLId[EBMLId[\"AttachedFile\"] = 24999] = \"AttachedFile\";\n EBMLId[EBMLId[\"FileDescription\"] = 18046] = \"FileDescription\";\n EBMLId[EBMLId[\"FileName\"] = 18030] = \"FileName\";\n EBMLId[EBMLId[\"FileMediaType\"] = 18016] = \"FileMediaType\";\n EBMLId[EBMLId[\"FileData\"] = 18012] = \"FileData\";\n EBMLId[EBMLId[\"FileUID\"] = 18094] = \"FileUID\";\n EBMLId[EBMLId[\"Chapters\"] = 272869232] = \"Chapters\";\n EBMLId[EBMLId[\"Tags\"] = 307544935] = \"Tags\";\n EBMLId[EBMLId[\"Tag\"] = 29555] = \"Tag\";\n EBMLId[EBMLId[\"Targets\"] = 25536] = \"Targets\";\n EBMLId[EBMLId[\"TargetTypeValue\"] = 26826] = \"TargetTypeValue\";\n EBMLId[EBMLId[\"TargetType\"] = 25546] = \"TargetType\";\n EBMLId[EBMLId[\"TagTrackUID\"] = 25541] = \"TagTrackUID\";\n EBMLId[EBMLId[\"TagEditionUID\"] = 25545] = \"TagEditionUID\";\n EBMLId[EBMLId[\"TagChapterUID\"] = 25540] = \"TagChapterUID\";\n EBMLId[EBMLId[\"TagAttachmentUID\"] = 25542] = \"TagAttachmentUID\";\n EBMLId[EBMLId[\"SimpleTag\"] = 26568] = \"SimpleTag\";\n EBMLId[EBMLId[\"TagName\"] = 17827] = \"TagName\";\n EBMLId[EBMLId[\"TagLanguage\"] = 17530] = \"TagLanguage\";\n EBMLId[EBMLId[\"TagString\"] = 17543] = \"TagString\";\n EBMLId[EBMLId[\"TagBinary\"] = 17541] = \"TagBinary\";\n EBMLId[EBMLId[\"ContentEncodings\"] = 28032] = \"ContentEncodings\";\n EBMLId[EBMLId[\"ContentEncoding\"] = 25152] = \"ContentEncoding\";\n EBMLId[EBMLId[\"ContentEncodingOrder\"] = 20529] = \"ContentEncodingOrder\";\n EBMLId[EBMLId[\"ContentEncodingScope\"] = 20530] = \"ContentEncodingScope\";\n EBMLId[EBMLId[\"ContentCompression\"] = 20532] = \"ContentCompression\";\n EBMLId[EBMLId[\"ContentCompAlgo\"] = 16980] = \"ContentCompAlgo\";\n EBMLId[EBMLId[\"ContentCompSettings\"] = 16981] = \"ContentCompSettings\";\n EBMLId[EBMLId[\"ContentEncryption\"] = 20533] = \"ContentEncryption\";\n})(EBMLId || (EBMLId = {}));\nexport const LEVEL_0_EBML_IDS = [\n EBMLId.EBML,\n EBMLId.Segment,\n];\n// All the stuff that can appear in a segment, basically\nexport const LEVEL_1_EBML_IDS = [\n EBMLId.SeekHead,\n EBMLId.Info,\n EBMLId.Cluster,\n EBMLId.Tracks,\n EBMLId.Cues,\n EBMLId.Attachments,\n EBMLId.Chapters,\n EBMLId.Tags,\n];\nexport const LEVEL_0_AND_1_EBML_IDS = [\n ...LEVEL_0_EBML_IDS,\n ...LEVEL_1_EBML_IDS,\n];\nexport const measureUnsignedInt = (value) => {\n if (value < (1 << 8)) {\n return 1;\n }\n else if (value < (1 << 16)) {\n return 2;\n }\n else if (value < (1 << 24)) {\n return 3;\n }\n else if (value < 2 ** 32) {\n return 4;\n }\n else if (value < 2 ** 40) {\n return 5;\n }\n else {\n return 6;\n }\n};\nexport const measureUnsignedBigInt = (value) => {\n if (value < (1n << 8n)) {\n return 1;\n }\n else if (value < (1n << 16n)) {\n return 2;\n }\n else if (value < (1n << 24n)) {\n return 3;\n }\n else if (value < (1n << 32n)) {\n return 4;\n }\n else if (value < (1n << 40n)) {\n return 5;\n }\n else if (value < (1n << 48n)) {\n return 6;\n }\n else if (value < (1n << 56n)) {\n return 7;\n }\n else {\n return 8;\n }\n};\nexport const measureSignedInt = (value) => {\n if (value >= -(1 << 6) && value < (1 << 6)) {\n return 1;\n }\n else if (value >= -(1 << 13) && value < (1 << 13)) {\n return 2;\n }\n else if (value >= -(1 << 20) && value < (1 << 20)) {\n return 3;\n }\n else if (value >= -(1 << 27) && value < (1 << 27)) {\n return 4;\n }\n else if (value >= -(2 ** 34) && value < 2 ** 34) {\n return 5;\n }\n else {\n return 6;\n }\n};\nexport const measureVarInt = (value) => {\n if (value < (1 << 7) - 1) {\n /** Top bit is set, leaving 7 bits to hold the integer, but we can't store\n * 127 because \"all bits set to one\" is a reserved value. Same thing for the\n * other cases below:\n */\n return 1;\n }\n else if (value < (1 << 14) - 1) {\n return 2;\n }\n else if (value < (1 << 21) - 1) {\n return 3;\n }\n else if (value < (1 << 28) - 1) {\n return 4;\n }\n else if (value < 2 ** 35 - 1) {\n return 5;\n }\n else if (value < 2 ** 42 - 1) {\n return 6;\n }\n else {\n throw new Error('EBML varint size not supported ' + value);\n }\n};\nexport class EBMLWriter {\n constructor(writer) {\n this.writer = writer;\n this.helper = new Uint8Array(8);\n this.helperView = new DataView(this.helper.buffer);\n /**\n * Stores the position from the start of the file to where EBML elements have been written. This is used to\n * rewrite/edit elements that were already added before, and to measure sizes of things.\n */\n this.offsets = new WeakMap();\n /** Same as offsets, but stores position where the element's data starts (after ID and size fields). */\n this.dataOffsets = new WeakMap();\n }\n writeByte(value) {\n this.helperView.setUint8(0, value);\n this.writer.write(this.helper.subarray(0, 1));\n }\n writeFloat32(value) {\n this.helperView.setFloat32(0, value, false);\n this.writer.write(this.helper.subarray(0, 4));\n }\n writeFloat64(value) {\n this.helperView.setFloat64(0, value, false);\n this.writer.write(this.helper);\n }\n writeUnsignedInt(value, width = measureUnsignedInt(value)) {\n let pos = 0;\n // Each case falls through:\n switch (width) {\n case 6:\n // Need to use division to access >32 bits of floating point var\n this.helperView.setUint8(pos++, (value / 2 ** 40) | 0);\n // eslint-disable-next-line no-fallthrough\n case 5:\n this.helperView.setUint8(pos++, (value / 2 ** 32) | 0);\n // eslint-disable-next-line no-fallthrough\n case 4:\n this.helperView.setUint8(pos++, value >> 24);\n // eslint-disable-next-line no-fallthrough\n case 3:\n this.helperView.setUint8(pos++, value >> 16);\n // eslint-disable-next-line no-fallthrough\n case 2:\n this.helperView.setUint8(pos++, value >> 8);\n // eslint-disable-next-line no-fallthrough\n case 1:\n this.helperView.setUint8(pos++, value);\n break;\n default:\n throw new Error('Bad unsigned int size ' + width);\n }\n this.writer.write(this.helper.subarray(0, pos));\n }\n writeUnsignedBigInt(value, width = measureUnsignedBigInt(value)) {\n let pos = 0;\n for (let i = width - 1; i >= 0; i--) {\n this.helperView.setUint8(pos++, Number((value >> BigInt(i * 8)) & 0xffn));\n }\n this.writer.write(this.helper.subarray(0, pos));\n }\n writeSignedInt(value, width = measureSignedInt(value)) {\n if (value < 0) {\n // Two's complement stuff\n value += 2 ** (width * 8);\n }\n this.writeUnsignedInt(value, width);\n }\n writeVarInt(value, width = measureVarInt(value)) {\n let pos = 0;\n switch (width) {\n case 1:\n this.helperView.setUint8(pos++, (1 << 7) | value);\n break;\n case 2:\n this.helperView.setUint8(pos++, (1 << 6) | (value >> 8));\n this.helperView.setUint8(pos++, value);\n break;\n case 3:\n this.helperView.setUint8(pos++, (1 << 5) | (value >> 16));\n this.helperView.setUint8(pos++, value >> 8);\n this.helperView.setUint8(pos++, value);\n break;\n case 4:\n this.helperView.setUint8(pos++, (1 << 4) | (value >> 24));\n this.helperView.setUint8(pos++, value >> 16);\n this.helperView.setUint8(pos++, value >> 8);\n this.helperView.setUint8(pos++, value);\n break;\n case 5:\n /**\n * JavaScript converts its doubles to 32-bit integers for bitwise\n * operations, so we need to do a division by 2^32 instead of a\n * right-shift of 32 to retain those top 3 bits\n */\n this.helperView.setUint8(pos++, (1 << 3) | ((value / 2 ** 32) & 0x7));\n this.helperView.setUint8(pos++, value >> 24);\n this.helperView.setUint8(pos++, value >> 16);\n this.helperView.setUint8(pos++, value >> 8);\n this.helperView.setUint8(pos++, value);\n break;\n case 6:\n this.helperView.setUint8(pos++, (1 << 2) | ((value / 2 ** 40) & 0x3));\n this.helperView.setUint8(pos++, (value / 2 ** 32) | 0);\n this.helperView.setUint8(pos++, value >> 24);\n this.helperView.setUint8(pos++, value >> 16);\n this.helperView.setUint8(pos++, value >> 8);\n this.helperView.setUint8(pos++, value);\n break;\n default:\n throw new Error('Bad EBML varint size ' + width);\n }\n this.writer.write(this.helper.subarray(0, pos));\n }\n writeAsciiString(str) {\n this.writer.write(new Uint8Array(str.split('').map(x => x.charCodeAt(0))));\n }\n writeEBML(data) {\n if (data === null)\n return;\n if (data instanceof Uint8Array) {\n this.writer.write(data);\n }\n else if (Array.isArray(data)) {\n for (const elem of data) {\n this.writeEBML(elem);\n }\n }\n else {\n this.offsets.set(data, this.writer.getPos());\n this.writeUnsignedInt(data.id); // ID field\n if (Array.isArray(data.data)) {\n const sizePos = this.writer.getPos();\n const sizeSize = data.size === -1 ? 1 : (data.size ?? 4);\n if (data.size === -1) {\n // Write the reserved all-one-bits marker for unknown/unbounded size.\n this.writeByte(0xff);\n }\n else {\n this.writer.seek(this.writer.getPos() + sizeSize);\n }\n const startPos = this.writer.getPos();\n this.dataOffsets.set(data, startPos);\n this.writeEBML(data.data);\n if (data.size !== -1) {\n const size = this.writer.getPos() - startPos;\n const endPos = this.writer.getPos();\n this.writer.seek(sizePos);\n this.writeVarInt(size, sizeSize);\n this.writer.seek(endPos);\n }\n }\n else if (typeof data.data === 'number') {\n const size = data.size ?? measureUnsignedInt(data.data);\n this.writeVarInt(size);\n this.writeUnsignedInt(data.data, size);\n }\n else if (typeof data.data === 'bigint') {\n const size = data.size ?? measureUnsignedBigInt(data.data);\n this.writeVarInt(size);\n this.writeUnsignedBigInt(data.data, size);\n }\n else if (typeof data.data === 'string') {\n this.writeVarInt(data.data.length);\n this.writeAsciiString(data.data);\n }\n else if (data.data instanceof Uint8Array) {\n this.writeVarInt(data.data.byteLength, data.size);\n this.writer.write(data.data);\n }\n else if (data.data instanceof EBMLFloat32) {\n this.writeVarInt(4);\n this.writeFloat32(data.data.value);\n }\n else if (data.data instanceof EBMLFloat64) {\n this.writeVarInt(8);\n this.writeFloat64(data.data.value);\n }\n else if (data.data instanceof EBMLSignedInt) {\n const size = data.size ?? measureSignedInt(data.data.value);\n this.writeVarInt(size);\n this.writeSignedInt(data.data.value, size);\n }\n else if (data.data instanceof EBMLUnicodeString) {\n const bytes = textEncoder.encode(data.data.value);\n this.writeVarInt(bytes.length);\n this.writer.write(bytes);\n }\n else {\n assertNever(data.data);\n }\n }\n }\n}\nexport const MAX_VAR_INT_SIZE = 8;\nexport const MIN_HEADER_SIZE = 2; // 1-byte ID and 1-byte size\nexport const MAX_HEADER_SIZE = 2 * MAX_VAR_INT_SIZE; // 8-byte ID and 8-byte size\nexport const readVarIntSize = (slice) => {\n const firstByte = readU8(slice);\n slice.skip(-1);\n if (firstByte === 0) {\n return null; // Invalid VINT\n }\n let width = 1;\n let mask = 0x80;\n while ((firstByte & mask) === 0) {\n width++;\n mask >>= 1;\n }\n return width;\n};\nexport const readVarInt = (slice) => {\n // Read the first byte to determine the width of the variable-length integer\n const firstByte = readU8(slice);\n if (firstByte === 0) {\n return null; // Invalid VINT\n }\n // Find the position of VINT_MARKER, which determines the width\n let width = 1;\n let mask = 1 << 7;\n while ((firstByte & mask) === 0) {\n width++;\n mask >>= 1;\n }\n // First byte's value needs the marker bit cleared\n let value = firstByte & (mask - 1);\n // Read remaining bytes\n for (let i = 1; i < width; i++) {\n value *= 1 << 8;\n value += readU8(slice);\n }\n return value;\n};\nexport const readUnsignedInt = (slice, width) => {\n if (width < 1 || width > 8) {\n throw new Error('Bad unsigned int size ' + width);\n }\n let value = 0;\n // Read bytes from most significant to least significant\n for (let i = 0; i < width; i++) {\n value *= 1 << 8;\n value += readU8(slice);\n }\n return value;\n};\nexport const readUnsignedBigInt = (slice, width) => {\n if (width < 1) {\n throw new Error('Bad unsigned int size ' + width);\n }\n let value = 0n;\n for (let i = 0; i < width; i++) {\n value <<= 8n;\n value += BigInt(readU8(slice));\n }\n return value;\n};\nexport const readSignedInt = (slice, width) => {\n let value = readUnsignedInt(slice, width);\n // If the highest bit is set, convert from two's complement\n if (value & (1 << (width * 8 - 1))) {\n value -= 2 ** (width * 8);\n }\n return value;\n};\nexport const readElementId = (slice) => {\n const size = readVarIntSize(slice);\n if (size === null) {\n return null;\n }\n const id = readUnsignedInt(slice, size);\n return id;\n};\nexport const readElementSize = (slice) => {\n let size = readU8(slice);\n if (size === 0xff) {\n size = null;\n }\n else {\n slice.skip(-1);\n size = readVarInt(slice);\n // In some (livestreamed) files, this is the value of the size field. While this technically is just a very\n // large number, it is intended to behave like the reserved size 0xFF, meaning the size is undefined. We\n // catch the number here. Note that it cannot be perfectly represented as a double, but the comparison works\n // nonetheless.\n // eslint-disable-next-line no-loss-of-precision\n if (size === 0x00ffffffffffffff) {\n size = null;\n }\n }\n return size;\n};\nexport const readElementHeader = (slice) => {\n const id = readElementId(slice);\n if (id === null) {\n return null;\n }\n const size = readElementSize(slice);\n return { id, size };\n};\nexport const readAsciiString = (slice, length) => {\n const bytes = readBytes(slice, length);\n // Actual string length might be shorter due to null terminators\n let strLength = 0;\n while (strLength < length && bytes[strLength] !== 0) {\n strLength += 1;\n }\n return String.fromCharCode(...bytes.subarray(0, strLength));\n};\nexport const readUnicodeString = (slice, length) => {\n const bytes = readBytes(slice, length);\n // Actual string length might be shorter due to null terminators\n let strLength = 0;\n while (strLength < length && bytes[strLength] !== 0) {\n strLength += 1;\n }\n return textDecoder.decode(bytes.subarray(0, strLength));\n};\nexport const readFloat = (slice, width) => {\n if (width === 0) {\n return 0;\n }\n if (width !== 4 && width !== 8) {\n throw new Error('Bad float size ' + width);\n }\n return width === 4 ? readF32Be(slice) : readF64Be(slice);\n};\n/** Returns the byte offset in the file of the next element with a matching ID. */\nexport const searchForNextElementId = async (reader, startPos, ids, until) => {\n const idsSet = new Set(ids);\n let currentPos = startPos;\n while (until === null || currentPos < until) {\n let slice = reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);\n if (slice instanceof Promise)\n slice = await slice;\n if (!slice)\n break;\n const elementHeader = readElementHeader(slice);\n if (!elementHeader) {\n break;\n }\n if (idsSet.has(elementHeader.id)) {\n return { pos: currentPos, found: true };\n }\n assertDefinedSize(elementHeader.size);\n currentPos = slice.filePos + elementHeader.size;\n }\n return { pos: (until !== null && until > currentPos) ? until : currentPos, found: false };\n};\n/** Searches for the next occurrence of an element ID using a naive byte-wise search. */\nexport const resync = async (reader, startPos, ids, until) => {\n const CHUNK_SIZE = 2 ** 16; // So we don't need to grab thousands of slices\n const idsSet = new Set(ids);\n let currentPos = startPos;\n while (currentPos < until) {\n let slice = reader.requestSliceRange(currentPos, 0, Math.min(CHUNK_SIZE, until - currentPos));\n if (slice instanceof Promise)\n slice = await slice;\n if (!slice)\n break;\n if (slice.length < MAX_VAR_INT_SIZE)\n break;\n for (let i = 0; i < slice.length - MAX_VAR_INT_SIZE; i++) {\n slice.filePos = currentPos;\n const elementId = readElementId(slice);\n if (elementId !== null && idsSet.has(elementId)) {\n return currentPos;\n }\n currentPos++;\n }\n }\n return null;\n};\nexport const CODEC_STRING_MAP = {\n 'avc': 'V_MPEG4/ISO/AVC',\n 'hevc': 'V_MPEGH/ISO/HEVC',\n 'vp8': 'V_VP8',\n 'vp9': 'V_VP9',\n 'av1': 'V_AV1',\n 'aac': 'A_AAC',\n 'mp3': 'A_MPEG/L3',\n 'opus': 'A_OPUS',\n 'vorbis': 'A_VORBIS',\n 'flac': 'A_FLAC',\n 'pcm-u8': 'A_PCM/INT/LIT',\n 'pcm-s16': 'A_PCM/INT/LIT',\n 'pcm-s16be': 'A_PCM/INT/BIG',\n 'pcm-s24': 'A_PCM/INT/LIT',\n 'pcm-s24be': 'A_PCM/INT/BIG',\n 'pcm-s32': 'A_PCM/INT/LIT',\n 'pcm-s32be': 'A_PCM/INT/BIG',\n 'pcm-f32': 'A_PCM/FLOAT/IEEE',\n 'pcm-f64': 'A_PCM/FLOAT/IEEE',\n 'webvtt': 'S_TEXT/WEBVTT',\n};\nexport function assertDefinedSize(size) {\n if (size === null) {\n throw new Error('Undefined element size is used in a place where it is not supported.');\n }\n}\n;\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nconst cueBlockHeaderRegex = /(?:(.+?)\\n)?((?:\\d{2}:)?\\d{2}:\\d{2}.\\d{3})\\s+-->\\s+((?:\\d{2}:)?\\d{2}:\\d{2}.\\d{3})/g;\nconst preambleStartRegex = /^WEBVTT(.|\\n)*?\\n{2}/;\nexport const inlineTimestampRegex = /<(?:(\\d{2}):)?(\\d{2}):(\\d{2}).(\\d{3})>/g;\nexport class SubtitleParser {\n constructor(options) {\n this.preambleText = null;\n this.preambleEmitted = false;\n this.options = options;\n }\n parse(text) {\n text = text.replaceAll('\\r\\n', '\\n').replaceAll('\\r', '\\n');\n cueBlockHeaderRegex.lastIndex = 0;\n let match;\n if (!this.preambleText) {\n if (!preambleStartRegex.test(text)) {\n throw new Error('WebVTT preamble incorrect.');\n }\n match = cueBlockHeaderRegex.exec(text);\n const preamble = text.slice(0, match?.index ?? text.length).trimEnd();\n if (!preamble) {\n throw new Error('No WebVTT preamble provided.');\n }\n this.preambleText = preamble;\n if (match) {\n text = text.slice(match.index);\n cueBlockHeaderRegex.lastIndex = 0;\n }\n }\n while ((match = cueBlockHeaderRegex.exec(text))) {\n const notes = text.slice(0, match.index);\n const cueIdentifier = match[1];\n const matchEnd = match.index + match[0].length;\n const bodyStart = text.indexOf('\\n', matchEnd) + 1;\n const cueSettings = text.slice(matchEnd, bodyStart).trim();\n let bodyEnd = text.indexOf('\\n\\n', matchEnd);\n if (bodyEnd === -1)\n bodyEnd = text.length;\n const startTime = parseSubtitleTimestamp(match[2]);\n const endTime = parseSubtitleTimestamp(match[3]);\n const duration = endTime - startTime;\n const body = text.slice(bodyStart, bodyEnd).trim();\n text = text.slice(bodyEnd).trimStart();\n cueBlockHeaderRegex.lastIndex = 0;\n const cue = {\n timestamp: startTime / 1000,\n duration: duration / 1000,\n text: body,\n identifier: cueIdentifier,\n settings: cueSettings,\n notes,\n };\n const meta = {};\n if (!this.preambleEmitted) {\n meta.config = {\n description: this.preambleText,\n };\n this.preambleEmitted = true;\n }\n this.options.output(cue, meta);\n }\n }\n}\nconst timestampRegex = /(?:(\\d{2}):)?(\\d{2}):(\\d{2}).(\\d{3})/;\nexport const parseSubtitleTimestamp = (string) => {\n const match = timestampRegex.exec(string);\n if (!match)\n throw new Error('Expected match.');\n return 60 * 60 * 1000 * Number(match[1] || '0')\n + 60 * 1000 * Number(match[2])\n + 1000 * Number(match[3])\n + Number(match[4]);\n};\nexport const formatSubtitleTimestamp = (timestamp) => {\n const hours = Math.floor(timestamp / (60 * 60 * 1000));\n const minutes = Math.floor((timestamp % (60 * 60 * 1000)) / (60 * 1000));\n const seconds = Math.floor((timestamp % (60 * 1000)) / 1000);\n const milliseconds = timestamp % 1000;\n return hours.toString().padStart(2, '0') + ':'\n + minutes.toString().padStart(2, '0') + ':'\n + seconds.toString().padStart(2, '0') + '.'\n + milliseconds.toString().padStart(3, '0');\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { toUint8Array, assert, isU32, last, textEncoder, COLOR_PRIMARIES_MAP, TRANSFER_CHARACTERISTICS_MAP, MATRIX_COEFFICIENTS_MAP, colorSpaceIsComplete, UNDETERMINED_LANGUAGE, assertNever, keyValueIterator, } from '../misc.js';\nimport { generateAv1CodecConfigurationFromCodecString, parsePcmCodec, PCM_AUDIO_CODECS, } from '../codec.js';\nimport { formatSubtitleTimestamp } from '../subtitles.js';\nimport { getTrackMetadata, GLOBAL_TIMESCALE, intoTimescale, } from './isobmff-muxer.js';\nimport { parseOpusIdentificationHeader } from '../codec-data.js';\nimport { RichImageData } from '../metadata.js';\nexport class IsobmffBoxWriter {\n constructor(writer) {\n this.writer = writer;\n this.helper = new Uint8Array(8);\n this.helperView = new DataView(this.helper.buffer);\n /**\n * Stores the position from the start of the file to where boxes elements have been written. This is used to\n * rewrite/edit elements that were already added before, and to measure sizes of things.\n */\n this.offsets = new WeakMap();\n }\n writeU32(value) {\n this.helperView.setUint32(0, value, false);\n this.writer.write(this.helper.subarray(0, 4));\n }\n writeU64(value) {\n this.helperView.setUint32(0, Math.floor(value / 2 ** 32), false);\n this.helperView.setUint32(4, value, false);\n this.writer.write(this.helper.subarray(0, 8));\n }\n writeAscii(text) {\n for (let i = 0; i < text.length; i++) {\n this.helperView.setUint8(i % 8, text.charCodeAt(i));\n if (i % 8 === 7)\n this.writer.write(this.helper);\n }\n if (text.length % 8 !== 0) {\n this.writer.write(this.helper.subarray(0, text.length % 8));\n }\n }\n writeBox(box) {\n this.offsets.set(box, this.writer.getPos());\n if (box.contents && !box.children) {\n this.writeBoxHeader(box, box.size ?? box.contents.byteLength + 8);\n this.writer.write(box.contents);\n }\n else {\n const startPos = this.writer.getPos();\n this.writeBoxHeader(box, 0);\n if (box.contents)\n this.writer.write(box.contents);\n if (box.children)\n for (const child of box.children)\n if (child)\n this.writeBox(child);\n const endPos = this.writer.getPos();\n const size = box.size ?? endPos - startPos;\n this.writer.seek(startPos);\n this.writeBoxHeader(box, size);\n this.writer.seek(endPos);\n }\n }\n writeBoxHeader(box, size) {\n this.writeU32(box.largeSize ? 1 : size);\n this.writeAscii(box.type);\n if (box.largeSize)\n this.writeU64(size);\n }\n measureBoxHeader(box) {\n return 8 + (box.largeSize ? 8 : 0);\n }\n patchBox(box) {\n const boxOffset = this.offsets.get(box);\n assert(boxOffset !== undefined);\n const endPos = this.writer.getPos();\n this.writer.seek(boxOffset);\n this.writeBox(box);\n this.writer.seek(endPos);\n }\n measureBox(box) {\n if (box.contents && !box.children) {\n const headerSize = this.measureBoxHeader(box);\n return headerSize + box.contents.byteLength;\n }\n else {\n let result = this.measureBoxHeader(box);\n if (box.contents)\n result += box.contents.byteLength;\n if (box.children)\n for (const child of box.children)\n if (child)\n result += this.measureBox(child);\n return result;\n }\n }\n}\nconst bytes = /* #__PURE__ */ new Uint8Array(8);\nconst view = /* #__PURE__ */ new DataView(bytes.buffer);\nconst u8 = (value) => {\n return [(value % 0x100 + 0x100) % 0x100];\n};\nconst u16 = (value) => {\n view.setUint16(0, value, false);\n return [bytes[0], bytes[1]];\n};\nconst i16 = (value) => {\n view.setInt16(0, value, false);\n return [bytes[0], bytes[1]];\n};\nconst u24 = (value) => {\n view.setUint32(0, value, false);\n return [bytes[1], bytes[2], bytes[3]];\n};\nconst u32 = (value) => {\n view.setUint32(0, value, false);\n return [bytes[0], bytes[1], bytes[2], bytes[3]];\n};\nconst i32 = (value) => {\n view.setInt32(0, value, false);\n return [bytes[0], bytes[1], bytes[2], bytes[3]];\n};\nconst u64 = (value) => {\n view.setUint32(0, Math.floor(value / 2 ** 32), false);\n view.setUint32(4, value, false);\n return [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]];\n};\nconst fixed_8_8 = (value) => {\n view.setInt16(0, 2 ** 8 * value, false);\n return [bytes[0], bytes[1]];\n};\nconst fixed_16_16 = (value) => {\n view.setInt32(0, 2 ** 16 * value, false);\n return [bytes[0], bytes[1], bytes[2], bytes[3]];\n};\nconst fixed_2_30 = (value) => {\n view.setInt32(0, 2 ** 30 * value, false);\n return [bytes[0], bytes[1], bytes[2], bytes[3]];\n};\nconst variableUnsignedInt = (value, byteLength) => {\n const bytes = [];\n let remaining = value;\n do {\n let byte = remaining & 0x7f;\n remaining >>= 7;\n // If this isn't the first byte we're adding (meaning there will be more bytes after it\n // when we reverse the array), set the continuation bit\n if (bytes.length > 0) {\n byte |= 0x80;\n }\n bytes.push(byte);\n if (byteLength !== undefined) {\n byteLength--;\n }\n } while (remaining > 0 || byteLength);\n // Reverse the array since we built it backwards\n return bytes.reverse();\n};\nconst ascii = (text, nullTerminated = false) => {\n const bytes = Array(text.length).fill(null).map((_, i) => text.charCodeAt(i));\n if (nullTerminated)\n bytes.push(0x00);\n return bytes;\n};\nconst lastPresentedSample = (samples) => {\n let result = null;\n for (const sample of samples) {\n if (!result || sample.timestamp > result.timestamp) {\n result = sample;\n }\n }\n return result;\n};\nconst rotationMatrix = (rotationInDegrees) => {\n const theta = rotationInDegrees * (Math.PI / 180);\n const cosTheta = Math.round(Math.cos(theta));\n const sinTheta = Math.round(Math.sin(theta));\n // Matrices are post-multiplied in ISOBMFF, meaning this is the transpose of your typical rotation matrix\n return [\n cosTheta, sinTheta, 0,\n -sinTheta, cosTheta, 0,\n 0, 0, 1,\n ];\n};\nconst IDENTITY_MATRIX = /* #__PURE__ */ rotationMatrix(0);\nconst matrixToBytes = (matrix) => {\n return [\n fixed_16_16(matrix[0]), fixed_16_16(matrix[1]), fixed_2_30(matrix[2]),\n fixed_16_16(matrix[3]), fixed_16_16(matrix[4]), fixed_2_30(matrix[5]),\n fixed_16_16(matrix[6]), fixed_16_16(matrix[7]), fixed_2_30(matrix[8]),\n ];\n};\nexport const box = (type, contents, children) => ({\n type,\n contents: contents && new Uint8Array(contents.flat(10)),\n children,\n});\n/** A FullBox always starts with a version byte, followed by three flag bytes. */\nexport const fullBox = (type, version, flags, contents, children) => box(type, [u8(version), u24(flags), contents ?? []], children);\n/**\n * File Type Compatibility Box: Allows the reader to determine whether this is a type of file that the\n * reader understands.\n */\nexport const ftyp = (details) => {\n // You can find the full logic for this at\n // https://github.com/FFmpeg/FFmpeg/blob/de2fb43e785773738c660cdafb9309b1ef1bc80d/libavformat/movenc.c#L5518\n // Obviously, this lib only needs a small subset of that logic.\n const minorVersion = 0x200;\n if (details.isQuickTime) {\n return box('ftyp', [\n ascii('qt '), // Major brand\n u32(minorVersion), // Minor version\n // Compatible brands\n ascii('qt '),\n ]);\n }\n if (details.fragmented) {\n return box('ftyp', [\n ascii('iso5'), // Major brand\n u32(minorVersion), // Minor version\n // Compatible brands\n ascii('iso5'),\n ascii('iso6'),\n ascii('mp41'),\n ]);\n }\n return box('ftyp', [\n ascii('isom'), // Major brand\n u32(minorVersion), // Minor version\n // Compatible brands\n ascii('isom'),\n details.holdsAvc ? ascii('avc1') : [],\n ascii('mp41'),\n ]);\n};\n/** Movie Sample Data Box. Contains the actual frames/samples of the media. */\nexport const mdat = (reserveLargeSize) => ({ type: 'mdat', largeSize: reserveLargeSize });\n/** Free Space Box: A box that designates unused space in the movie data file. */\nexport const free = (size) => ({ type: 'free', size });\n/**\n * Movie Box: Used to specify the information that defines a movie - that is, the information that allows\n * an application to interpret the sample data that is stored elsewhere.\n */\nexport const moov = (muxer) => box('moov', undefined, [\n mvhd(muxer.creationTime, muxer.trackDatas),\n ...muxer.trackDatas.map(x => trak(x, muxer.creationTime)),\n muxer.isFragmented ? mvex(muxer.trackDatas) : null,\n udta(muxer),\n]);\n/** Movie Header Box: Used to specify the characteristics of the entire movie, such as timescale and duration. */\nexport const mvhd = (creationTime, trackDatas) => {\n const duration = intoTimescale(Math.max(0, ...trackDatas\n .filter(x => x.samples.length > 0)\n .map((x) => {\n const lastSample = lastPresentedSample(x.samples);\n return lastSample.timestamp + lastSample.duration;\n })), GLOBAL_TIMESCALE);\n const nextTrackId = Math.max(0, ...trackDatas.map(x => x.track.id)) + 1;\n // Conditionally use u64 if u32 isn't enough\n const needsU64 = !isU32(creationTime) || !isU32(duration);\n const u32OrU64 = needsU64 ? u64 : u32;\n return fullBox('mvhd', +needsU64, 0, [\n u32OrU64(creationTime), // Creation time\n u32OrU64(creationTime), // Modification time\n u32(GLOBAL_TIMESCALE), // Timescale\n u32OrU64(duration), // Duration\n fixed_16_16(1), // Preferred rate\n fixed_8_8(1), // Preferred volume\n Array(10).fill(0), // Reserved\n matrixToBytes(IDENTITY_MATRIX), // Matrix\n Array(24).fill(0), // Pre-defined\n u32(nextTrackId), // Next track ID\n ]);\n};\n/**\n * Track Box: Defines a single track of a movie. A movie may consist of one or more tracks. Each track is\n * independent of the other tracks in the movie and carries its own temporal and spatial information. Each Track Box\n * contains its associated Media Box.\n */\nexport const trak = (trackData, creationTime) => {\n const trackMetadata = getTrackMetadata(trackData);\n return box('trak', undefined, [\n tkhd(trackData, creationTime),\n mdia(trackData, creationTime),\n trackMetadata.name !== undefined\n ? box('udta', undefined, [\n box('name', [\n ...textEncoder.encode(trackMetadata.name),\n ]),\n ])\n : null,\n ]);\n};\n/** Track Header Box: Specifies the characteristics of a single track within a movie. */\nexport const tkhd = (trackData, creationTime) => {\n const lastSample = lastPresentedSample(trackData.samples);\n const durationInGlobalTimescale = intoTimescale(lastSample ? lastSample.timestamp + lastSample.duration : 0, GLOBAL_TIMESCALE);\n const needsU64 = !isU32(creationTime) || !isU32(durationInGlobalTimescale);\n const u32OrU64 = needsU64 ? u64 : u32;\n let matrix;\n if (trackData.type === 'video') {\n const rotation = trackData.track.metadata.rotation;\n matrix = rotationMatrix(rotation ?? 0);\n }\n else {\n matrix = IDENTITY_MATRIX;\n }\n let flags = 0x2; // Track in movie\n if (trackData.track.metadata.disposition?.default !== false) {\n flags |= 0x1; // Track enabled\n }\n return fullBox('tkhd', +needsU64, flags, [\n u32OrU64(creationTime), // Creation time\n u32OrU64(creationTime), // Modification time\n u32(trackData.track.id), // Track ID\n u32(0), // Reserved\n u32OrU64(durationInGlobalTimescale), // Duration\n Array(8).fill(0), // Reserved\n u16(0), // Layer\n u16(trackData.track.id), // Alternate group\n fixed_8_8(trackData.type === 'audio' ? 1 : 0), // Volume\n u16(0), // Reserved\n matrixToBytes(matrix), // Matrix\n fixed_16_16(trackData.type === 'video' ? trackData.info.width : 0), // Track width\n fixed_16_16(trackData.type === 'video' ? trackData.info.height : 0), // Track height\n ]);\n};\n/** Media Box: Describes and define a track's media type and sample data. */\nexport const mdia = (trackData, creationTime) => box('mdia', undefined, [\n mdhd(trackData, creationTime),\n hdlr(true, TRACK_TYPE_TO_COMPONENT_SUBTYPE[trackData.type], TRACK_TYPE_TO_HANDLER_NAME[trackData.type]),\n minf(trackData),\n]);\n/** Media Header Box: Specifies the characteristics of a media, including timescale and duration. */\nexport const mdhd = (trackData, creationTime) => {\n const lastSample = lastPresentedSample(trackData.samples);\n const localDuration = intoTimescale(lastSample ? lastSample.timestamp + lastSample.duration : 0, trackData.timescale);\n const needsU64 = !isU32(creationTime) || !isU32(localDuration);\n const u32OrU64 = needsU64 ? u64 : u32;\n return fullBox('mdhd', +needsU64, 0, [\n u32OrU64(creationTime), // Creation time\n u32OrU64(creationTime), // Modification time\n u32(trackData.timescale), // Timescale\n u32OrU64(localDuration), // Duration\n u16(getLanguageCodeInt(trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE)), // Language\n u16(0), // Quality\n ]);\n};\nconst TRACK_TYPE_TO_COMPONENT_SUBTYPE = {\n video: 'vide',\n audio: 'soun',\n subtitle: 'text',\n};\nconst TRACK_TYPE_TO_HANDLER_NAME = {\n video: 'MediabunnyVideoHandler',\n audio: 'MediabunnySoundHandler',\n subtitle: 'MediabunnyTextHandler',\n};\n/** Handler Reference Box. */\nexport const hdlr = (hasComponentType, handlerType, name, manufacturer = '\\0\\0\\0\\0') => fullBox('hdlr', 0, 0, [\n hasComponentType ? ascii('mhlr') : u32(0), // Component type\n ascii(handlerType), // Component subtype\n ascii(manufacturer), // Component manufacturer\n u32(0), // Component flags\n u32(0), // Component flags mask\n ascii(name, true), // Component name\n]);\n/**\n * Media Information Box: Stores handler-specific information for a track's media data. The media handler uses this\n * information to map from media time to media data and to process the media data.\n */\nexport const minf = (trackData) => box('minf', undefined, [\n TRACK_TYPE_TO_HEADER_BOX[trackData.type](),\n dinf(),\n stbl(trackData),\n]);\n/** Video Media Information Header Box: Defines specific color and graphics mode information. */\nexport const vmhd = () => fullBox('vmhd', 0, 1, [\n u16(0), // Graphics mode\n u16(0), // Opcolor R\n u16(0), // Opcolor G\n u16(0), // Opcolor B\n]);\n/** Sound Media Information Header Box: Stores the sound media's control information, such as balance. */\nexport const smhd = () => fullBox('smhd', 0, 0, [\n u16(0), // Balance\n u16(0), // Reserved\n]);\n/** Null Media Header Box. */\nexport const nmhd = () => fullBox('nmhd', 0, 0);\nconst TRACK_TYPE_TO_HEADER_BOX = {\n video: vmhd,\n audio: smhd,\n subtitle: nmhd,\n};\n/**\n * Data Information Box: Contains information specifying the data handler component that provides access to the\n * media data. The data handler component uses the Data Information Box to interpret the media's data.\n */\nexport const dinf = () => box('dinf', undefined, [\n dref(),\n]);\n/**\n * Data Reference Box: Contains tabular data that instructs the data handler component how to access the media's data.\n */\nexport const dref = () => fullBox('dref', 0, 0, [\n u32(1), // Entry count\n], [\n url(),\n]);\nexport const url = () => fullBox('url ', 0, 1); // Self-reference flag enabled\n/**\n * Sample Table Box: Contains information for converting from media time to sample number to sample location. This box\n * also indicates how to interpret the sample (for example, whether to decompress the video data and, if so, how).\n */\nexport const stbl = (trackData) => {\n const needsCtts = trackData.compositionTimeOffsetTable.length > 1\n || trackData.compositionTimeOffsetTable.some(x => x.sampleCompositionTimeOffset !== 0);\n return box('stbl', undefined, [\n stsd(trackData),\n stts(trackData),\n needsCtts ? ctts(trackData) : null,\n needsCtts ? cslg(trackData) : null,\n stsc(trackData),\n stsz(trackData),\n stco(trackData),\n stss(trackData),\n ]);\n};\n/**\n * Sample Description Box: Stores information that allows you to decode samples in the media. The data stored in the\n * sample description varies, depending on the media type.\n */\nexport const stsd = (trackData) => {\n let sampleDescription;\n if (trackData.type === 'video') {\n sampleDescription = videoSampleDescription(videoCodecToBoxName(trackData.track.source._codec, trackData.info.decoderConfig.codec), trackData);\n }\n else if (trackData.type === 'audio') {\n const boxName = audioCodecToBoxName(trackData.track.source._codec, trackData.muxer.isQuickTime);\n assert(boxName);\n sampleDescription = soundSampleDescription(boxName, trackData);\n }\n else if (trackData.type === 'subtitle') {\n sampleDescription = subtitleSampleDescription(SUBTITLE_CODEC_TO_BOX_NAME[trackData.track.source._codec], trackData);\n }\n assert(sampleDescription);\n return fullBox('stsd', 0, 0, [\n u32(1), // Entry count\n ], [\n sampleDescription,\n ]);\n};\n/** Video Sample Description Box: Contains information that defines how to interpret video media data. */\nexport const videoSampleDescription = (compressionType, trackData) => box(compressionType, [\n Array(6).fill(0), // Reserved\n u16(1), // Data reference index\n u16(0), // Pre-defined\n u16(0), // Reserved\n Array(12).fill(0), // Pre-defined\n u16(trackData.info.width), // Width\n u16(trackData.info.height), // Height\n u32(0x00480000), // Horizontal resolution\n u32(0x00480000), // Vertical resolution\n u32(0), // Reserved\n u16(1), // Frame count\n Array(32).fill(0), // Compressor name\n u16(0x0018), // Depth\n i16(0xffff), // Pre-defined\n], [\n VIDEO_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData),\n colorSpaceIsComplete(trackData.info.decoderConfig.colorSpace) ? colr(trackData) : null,\n]);\n/** Colour Information Box: Specifies the color space of the video. */\nexport const colr = (trackData) => box('colr', [\n ascii('nclx'), // Colour type\n u16(COLOR_PRIMARIES_MAP[trackData.info.decoderConfig.colorSpace.primaries]), // Colour primaries\n u16(TRANSFER_CHARACTERISTICS_MAP[trackData.info.decoderConfig.colorSpace.transfer]), // Transfer characteristics\n u16(MATRIX_COEFFICIENTS_MAP[trackData.info.decoderConfig.colorSpace.matrix]), // Matrix coefficients\n u8((trackData.info.decoderConfig.colorSpace.fullRange ? 1 : 0) << 7), // Full range flag\n]);\n/** AVC Configuration Box: Provides additional information to the decoder. */\nexport const avcC = (trackData) => trackData.info.decoderConfig && box('avcC', [\n // For AVC, description is an AVCDecoderConfigurationRecord, so nothing else to do here\n ...toUint8Array(trackData.info.decoderConfig.description),\n]);\n/** HEVC Configuration Box: Provides additional information to the decoder. */\nexport const hvcC = (trackData) => trackData.info.decoderConfig && box('hvcC', [\n // For HEVC, description is an HEVCDecoderConfigurationRecord, so nothing else to do here\n ...toUint8Array(trackData.info.decoderConfig.description),\n]);\n/** VP Configuration Box: Provides additional information to the decoder. */\nexport const vpcC = (trackData) => {\n // Reference: https://www.webmproject.org/vp9/mp4/\n if (!trackData.info.decoderConfig) {\n return null;\n }\n const decoderConfig = trackData.info.decoderConfig;\n const parts = decoderConfig.codec.split('.'); // We can derive the required values from the codec string\n const profile = Number(parts[1]);\n const level = Number(parts[2]);\n const bitDepth = Number(parts[3]);\n const chromaSubsampling = parts[4] ? Number(parts[4]) : 1; // 4:2:0 colocated with luma (0,0)\n const videoFullRangeFlag = parts[8] ? Number(parts[8]) : Number(decoderConfig.colorSpace?.fullRange ?? 0);\n const thirdByte = (bitDepth << 4) + (chromaSubsampling << 1) + videoFullRangeFlag;\n const colourPrimaries = parts[5]\n ? Number(parts[5])\n : decoderConfig.colorSpace?.primaries\n ? COLOR_PRIMARIES_MAP[decoderConfig.colorSpace.primaries]\n : 2; // Default to undetermined\n const transferCharacteristics = parts[6]\n ? Number(parts[6])\n : decoderConfig.colorSpace?.transfer\n ? TRANSFER_CHARACTERISTICS_MAP[decoderConfig.colorSpace.transfer]\n : 2;\n const matrixCoefficients = parts[7]\n ? Number(parts[7])\n : decoderConfig.colorSpace?.matrix\n ? MATRIX_COEFFICIENTS_MAP[decoderConfig.colorSpace.matrix]\n : 2;\n return fullBox('vpcC', 1, 0, [\n u8(profile), // Profile\n u8(level), // Level\n u8(thirdByte), // Bit depth, chroma subsampling, full range\n u8(colourPrimaries), // Colour primaries\n u8(transferCharacteristics), // Transfer characteristics\n u8(matrixCoefficients), // Matrix coefficients\n u16(0), // Codec initialization data size\n ]);\n};\n/** AV1 Configuration Box: Provides additional information to the decoder. */\nexport const av1C = (trackData) => {\n return box('av1C', generateAv1CodecConfigurationFromCodecString(trackData.info.decoderConfig.codec));\n};\n/** Sound Sample Description Box: Contains information that defines how to interpret sound media data. */\nexport const soundSampleDescription = (compressionType, trackData) => {\n let version = 0;\n let contents;\n let sampleSizeInBits = 16;\n if (PCM_AUDIO_CODECS.includes(trackData.track.source._codec)) {\n const codec = trackData.track.source._codec;\n const { sampleSize } = parsePcmCodec(codec);\n sampleSizeInBits = 8 * sampleSize;\n if (sampleSizeInBits > 16) {\n version = 1;\n }\n }\n if (version === 0) {\n contents = [\n Array(6).fill(0), // Reserved\n u16(1), // Data reference index\n u16(version), // Version\n u16(0), // Revision level\n u32(0), // Vendor\n u16(trackData.info.numberOfChannels), // Number of channels\n u16(sampleSizeInBits), // Sample size (bits)\n u16(0), // Compression ID\n u16(0), // Packet size\n u16(trackData.info.sampleRate < 2 ** 16 ? trackData.info.sampleRate : 0), // Sample rate (upper)\n u16(0), // Sample rate (lower)\n ];\n }\n else {\n contents = [\n Array(6).fill(0), // Reserved\n u16(1), // Data reference index\n u16(version), // Version\n u16(0), // Revision level\n u32(0), // Vendor\n u16(trackData.info.numberOfChannels), // Number of channels\n u16(Math.min(sampleSizeInBits, 16)), // Sample size (bits)\n u16(0), // Compression ID\n u16(0), // Packet size\n u16(trackData.info.sampleRate < 2 ** 16 ? trackData.info.sampleRate : 0), // Sample rate (upper)\n u16(0), // Sample rate (lower)\n u32(1), // Samples per packet (must be 1 for uncompressed formats)\n u32(sampleSizeInBits / 8), // Bytes per packet\n u32(trackData.info.numberOfChannels * sampleSizeInBits / 8), // Bytes per frame\n u32(2), // Bytes per sample (constant in FFmpeg)\n ];\n }\n return box(compressionType, contents, [\n audioCodecToConfigurationBox(trackData.track.source._codec, trackData.muxer.isQuickTime)?.(trackData) ?? null,\n ]);\n};\n/** MPEG-4 Elementary Stream Descriptor Box. */\nexport const esds = (trackData) => {\n // We build up the bytes in a layered way which reflects the nested structure\n let objectTypeIndication;\n switch (trackData.track.source._codec) {\n case 'aac':\n {\n objectTypeIndication = 0x40;\n }\n ;\n break;\n case 'mp3':\n {\n objectTypeIndication = 0x6b;\n }\n ;\n break;\n case 'vorbis':\n {\n objectTypeIndication = 0xdd;\n }\n ;\n break;\n default: throw new Error(`Unhandled audio codec: ${trackData.track.source._codec}`);\n }\n let bytes = [\n ...u8(objectTypeIndication), // Object type indication\n ...u8(0x15), // stream type(6bits)=5 audio, flags(2bits)=1\n ...u24(0), // 24bit buffer size\n ...u32(0), // max bitrate\n ...u32(0), // avg bitrate\n ];\n if (trackData.info.decoderConfig.description) {\n const description = toUint8Array(trackData.info.decoderConfig.description);\n // Add the decoder description to the end\n bytes = [\n ...bytes,\n ...u8(0x05), // TAG(5) = DecoderSpecificInfo\n ...variableUnsignedInt(description.byteLength),\n ...description,\n ];\n }\n bytes = [\n ...u16(1), // ES_ID = 1\n ...u8(0x00), // flags etc = 0\n ...u8(0x04), // TAG(4) = ES Descriptor\n ...variableUnsignedInt(bytes.length),\n ...bytes,\n ...u8(0x06), // TAG(6)\n ...u8(0x01), // length\n ...u8(0x02), // data\n ];\n bytes = [\n ...u8(0x03), // TAG(3) = Object Descriptor\n ...variableUnsignedInt(bytes.length),\n ...bytes,\n ];\n return fullBox('esds', 0, 0, bytes);\n};\nexport const wave = (trackData) => {\n return box('wave', undefined, [\n frma(trackData),\n enda(trackData),\n box('\\x00\\x00\\x00\\x00'), // NULL tag at the end\n ]);\n};\nexport const frma = (trackData) => {\n return box('frma', [\n ascii(audioCodecToBoxName(trackData.track.source._codec, trackData.muxer.isQuickTime)),\n ]);\n};\n// This box specifies PCM endianness\nexport const enda = (trackData) => {\n const { littleEndian } = parsePcmCodec(trackData.track.source._codec);\n return box('enda', [\n u16(+littleEndian),\n ]);\n};\n/** Opus Specific Box. */\nexport const dOps = (trackData) => {\n let outputChannelCount = trackData.info.numberOfChannels;\n // Default PreSkip, should be at least 80 milliseconds worth of playback, measured in 48000 Hz samples\n let preSkip = 3840;\n let inputSampleRate = trackData.info.sampleRate;\n let outputGain = 0;\n let channelMappingFamily = 0;\n let channelMappingTable = new Uint8Array(0);\n // Read preskip and from codec private data from the encoder\n // https://www.rfc-editor.org/rfc/rfc7845#section-5\n const description = trackData.info.decoderConfig?.description;\n if (description) {\n assert(description.byteLength >= 18);\n const bytes = toUint8Array(description);\n const header = parseOpusIdentificationHeader(bytes);\n outputChannelCount = header.outputChannelCount;\n preSkip = header.preSkip;\n inputSampleRate = header.inputSampleRate;\n outputGain = header.outputGain;\n channelMappingFamily = header.channelMappingFamily;\n if (header.channelMappingTable) {\n channelMappingTable = header.channelMappingTable;\n }\n }\n // https://www.opus-codec.org/docs/opus_in_isobmff.html\n return box('dOps', [\n u8(0), // Version\n u8(outputChannelCount), // OutputChannelCount\n u16(preSkip), // PreSkip\n u32(inputSampleRate), // InputSampleRate\n i16(outputGain), // OutputGain\n u8(channelMappingFamily), // ChannelMappingFamily\n ...channelMappingTable,\n ]);\n};\n/** FLAC specific box. */\nexport const dfLa = (trackData) => {\n const description = trackData.info.decoderConfig?.description;\n assert(description);\n const bytes = toUint8Array(description);\n return fullBox('dfLa', 0, 0, [\n ...bytes.subarray(4),\n ]);\n};\n/** PCM Configuration Box, ISO/IEC 23003-5. */\nconst pcmC = (trackData) => {\n const { littleEndian, sampleSize } = parsePcmCodec(trackData.track.source._codec);\n const formatFlags = +littleEndian;\n return fullBox('pcmC', 0, 0, [\n u8(formatFlags),\n u8(8 * sampleSize),\n ]);\n};\nexport const subtitleSampleDescription = (compressionType, trackData) => box(compressionType, [\n Array(6).fill(0), // Reserved\n u16(1), // Data reference index\n], [\n SUBTITLE_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData),\n]);\nexport const vttC = (trackData) => box('vttC', [\n ...textEncoder.encode(trackData.info.config.description),\n]);\nexport const txtC = (textConfig) => fullBox('txtC', 0, 0, [\n ...textConfig, 0, // Text config (null-terminated)\n]);\n/**\n * Time-To-Sample Box: Stores duration information for a media's samples, providing a mapping from a time in a media\n * to the corresponding data sample. The table is compact, meaning that consecutive samples with the same time delta\n * will be grouped.\n */\nexport const stts = (trackData) => {\n return fullBox('stts', 0, 0, [\n u32(trackData.timeToSampleTable.length), // Number of entries\n trackData.timeToSampleTable.map(x => [\n u32(x.sampleCount), // Sample count\n u32(x.sampleDelta), // Sample duration\n ]),\n ]);\n};\n/** Sync Sample Box: Identifies the key frames in the media, marking the random access points within a stream. */\nexport const stss = (trackData) => {\n if (trackData.samples.every(x => x.type === 'key'))\n return null; // No stss box -> every frame is a key frame\n const keySamples = [...trackData.samples.entries()].filter(([, sample]) => sample.type === 'key');\n return fullBox('stss', 0, 0, [\n u32(keySamples.length), // Number of entries\n keySamples.map(([index]) => u32(index + 1)), // Sync sample table\n ]);\n};\n/**\n * Sample-To-Chunk Box: As samples are added to a media, they are collected into chunks that allow optimized data\n * access. A chunk contains one or more samples. Chunks in a media may have different sizes, and the samples within a\n * chunk may have different sizes. The Sample-To-Chunk Box stores chunk information for the samples in a media, stored\n * in a compactly-coded fashion.\n */\nexport const stsc = (trackData) => {\n return fullBox('stsc', 0, 0, [\n u32(trackData.compactlyCodedChunkTable.length), // Number of entries\n trackData.compactlyCodedChunkTable.map(x => [\n u32(x.firstChunk), // First chunk\n u32(x.samplesPerChunk), // Samples per chunk\n u32(1), // Sample description index\n ]),\n ]);\n};\n/** Sample Size Box: Specifies the byte size of each sample in the media. */\nexport const stsz = (trackData) => {\n if (trackData.type === 'audio' && trackData.info.requiresPcmTransformation) {\n const { sampleSize } = parsePcmCodec(trackData.track.source._codec);\n // With PCM, every sample has the same size\n return fullBox('stsz', 0, 0, [\n u32(sampleSize * trackData.info.numberOfChannels), // Sample size\n u32(trackData.samples.reduce((acc, x) => acc + intoTimescale(x.duration, trackData.timescale), 0)),\n ]);\n }\n return fullBox('stsz', 0, 0, [\n u32(0), // Sample size (0 means non-constant size)\n u32(trackData.samples.length), // Number of entries\n trackData.samples.map(x => u32(x.size)), // Sample size table\n ]);\n};\n/** Chunk Offset Box: Identifies the location of each chunk of data in the media's data stream, relative to the file. */\nexport const stco = (trackData) => {\n if (trackData.finalizedChunks.length > 0 && last(trackData.finalizedChunks).offset >= 2 ** 32) {\n // If the file is large, use the co64 box\n return fullBox('co64', 0, 0, [\n u32(trackData.finalizedChunks.length), // Number of entries\n trackData.finalizedChunks.map(x => u64(x.offset)), // Chunk offset table\n ]);\n }\n return fullBox('stco', 0, 0, [\n u32(trackData.finalizedChunks.length), // Number of entries\n trackData.finalizedChunks.map(x => u32(x.offset)), // Chunk offset table\n ]);\n};\n/**\n * Composition Time to Sample Box: Stores composition time offset information (PTS-DTS) for a\n * media's samples. The table is compact, meaning that consecutive samples with the same time\n * composition time offset will be grouped.\n */\nexport const ctts = (trackData) => {\n return fullBox('ctts', 1, 0, [\n u32(trackData.compositionTimeOffsetTable.length), // Number of entries\n trackData.compositionTimeOffsetTable.map(x => [\n u32(x.sampleCount), // Sample count\n i32(x.sampleCompositionTimeOffset), // Sample offset\n ]),\n ]);\n};\n/**\n * Composition to Decode Box: Stores information about the composition and display times of the media samples.\n */\nexport const cslg = (trackData) => {\n let leastDecodeToDisplayDelta = Infinity;\n let greatestDecodeToDisplayDelta = -Infinity;\n let compositionStartTime = Infinity;\n let compositionEndTime = -Infinity;\n assert(trackData.compositionTimeOffsetTable.length > 0);\n assert(trackData.samples.length > 0);\n for (let i = 0; i < trackData.compositionTimeOffsetTable.length; i++) {\n const entry = trackData.compositionTimeOffsetTable[i];\n leastDecodeToDisplayDelta = Math.min(leastDecodeToDisplayDelta, entry.sampleCompositionTimeOffset);\n greatestDecodeToDisplayDelta = Math.max(greatestDecodeToDisplayDelta, entry.sampleCompositionTimeOffset);\n }\n for (let i = 0; i < trackData.samples.length; i++) {\n const sample = trackData.samples[i];\n compositionStartTime = Math.min(compositionStartTime, intoTimescale(sample.timestamp, trackData.timescale));\n compositionEndTime = Math.max(compositionEndTime, intoTimescale(sample.timestamp + sample.duration, trackData.timescale));\n }\n const compositionToDtsShift = Math.max(-leastDecodeToDisplayDelta, 0);\n if (compositionEndTime >= 2 ** 31) {\n // For very large files, the composition end time can't be represented in i32, so let's just scrap the box in\n // that case. QuickTime fails to read the file if there's a cslg box with version 1, so that's sadly not an\n // option.\n return null;\n }\n return fullBox('cslg', 0, 0, [\n i32(compositionToDtsShift), // Composition to DTS shift\n i32(leastDecodeToDisplayDelta), // Least decode to display delta\n i32(greatestDecodeToDisplayDelta), // Greatest decode to display delta\n i32(compositionStartTime), // Composition start time\n i32(compositionEndTime), // Composition end time\n ]);\n};\n/**\n * Movie Extends Box: This box signals to readers that the file is fragmented. Contains a single Track Extends Box\n * for each track in the movie.\n */\nexport const mvex = (trackDatas) => {\n return box('mvex', undefined, trackDatas.map(trex));\n};\n/** Track Extends Box: Contains the default values used by the movie fragments. */\nexport const trex = (trackData) => {\n return fullBox('trex', 0, 0, [\n u32(trackData.track.id), // Track ID\n u32(1), // Default sample description index\n u32(0), // Default sample duration\n u32(0), // Default sample size\n u32(0), // Default sample flags\n ]);\n};\n/**\n * Movie Fragment Box: The movie fragments extend the presentation in time. They provide the information that would\n * previously have been\tin the Movie Box.\n */\nexport const moof = (sequenceNumber, trackDatas) => {\n return box('moof', undefined, [\n mfhd(sequenceNumber),\n ...trackDatas.map(traf),\n ]);\n};\n/** Movie Fragment Header Box: Contains a sequence number as a safety check. */\nexport const mfhd = (sequenceNumber) => {\n return fullBox('mfhd', 0, 0, [\n u32(sequenceNumber), // Sequence number\n ]);\n};\nconst fragmentSampleFlags = (sample) => {\n let byte1 = 0;\n let byte2 = 0;\n const byte3 = 0;\n const byte4 = 0;\n const sampleIsDifferenceSample = sample.type === 'delta';\n byte2 |= +sampleIsDifferenceSample;\n if (sampleIsDifferenceSample) {\n byte1 |= 1; // There is redundant coding in this sample\n }\n else {\n byte1 |= 2; // There is no redundant coding in this sample\n }\n // Note that there are a lot of other flags to potentially set here, but most are irrelevant / non-necessary\n return byte1 << 24 | byte2 << 16 | byte3 << 8 | byte4;\n};\n/** Track Fragment Box */\nexport const traf = (trackData) => {\n return box('traf', undefined, [\n tfhd(trackData),\n tfdt(trackData),\n trun(trackData),\n ]);\n};\n/** Track Fragment Header Box: Provides a reference to the extended track, and flags. */\nexport const tfhd = (trackData) => {\n assert(trackData.currentChunk);\n let tfFlags = 0;\n tfFlags |= 0x00008; // Default sample duration present\n tfFlags |= 0x00010; // Default sample size present\n tfFlags |= 0x00020; // Default sample flags present\n tfFlags |= 0x20000; // Default base is moof\n // Prefer the second sample over the first one, as the first one is a sync sample and therefore the \"odd one out\"\n const referenceSample = trackData.currentChunk.samples[1] ?? trackData.currentChunk.samples[0];\n const referenceSampleInfo = {\n duration: referenceSample.timescaleUnitsToNextSample,\n size: referenceSample.size,\n flags: fragmentSampleFlags(referenceSample),\n };\n return fullBox('tfhd', 0, tfFlags, [\n u32(trackData.track.id), // Track ID\n u32(referenceSampleInfo.duration), // Default sample duration\n u32(referenceSampleInfo.size), // Default sample size\n u32(referenceSampleInfo.flags), // Default sample flags\n ]);\n};\n/**\n * Track Fragment Decode Time Box: Provides the absolute decode time of the first sample of the fragment. This is\n * useful for performing random access on the media file.\n */\nexport const tfdt = (trackData) => {\n assert(trackData.currentChunk);\n return fullBox('tfdt', 1, 0, [\n u64(intoTimescale(trackData.currentChunk.startTimestamp, trackData.timescale)), // Base Media Decode Time\n ]);\n};\n/** Track Run Box: Specifies a run of contiguous samples for a given track. */\nexport const trun = (trackData) => {\n assert(trackData.currentChunk);\n const allSampleDurations = trackData.currentChunk.samples.map(x => x.timescaleUnitsToNextSample);\n const allSampleSizes = trackData.currentChunk.samples.map(x => x.size);\n const allSampleFlags = trackData.currentChunk.samples.map(fragmentSampleFlags);\n const allSampleCompositionTimeOffsets = trackData.currentChunk.samples\n .map(x => intoTimescale(x.timestamp - x.decodeTimestamp, trackData.timescale));\n const uniqueSampleDurations = new Set(allSampleDurations);\n const uniqueSampleSizes = new Set(allSampleSizes);\n const uniqueSampleFlags = new Set(allSampleFlags);\n const uniqueSampleCompositionTimeOffsets = new Set(allSampleCompositionTimeOffsets);\n const firstSampleFlagsPresent = uniqueSampleFlags.size === 2 && allSampleFlags[0] !== allSampleFlags[1];\n const sampleDurationPresent = uniqueSampleDurations.size > 1;\n const sampleSizePresent = uniqueSampleSizes.size > 1;\n const sampleFlagsPresent = !firstSampleFlagsPresent && uniqueSampleFlags.size > 1;\n const sampleCompositionTimeOffsetsPresent = uniqueSampleCompositionTimeOffsets.size > 1 || [...uniqueSampleCompositionTimeOffsets].some(x => x !== 0);\n let flags = 0;\n flags |= 0x0001; // Data offset present\n flags |= 0x0004 * +firstSampleFlagsPresent; // First sample flags present\n flags |= 0x0100 * +sampleDurationPresent; // Sample duration present\n flags |= 0x0200 * +sampleSizePresent; // Sample size present\n flags |= 0x0400 * +sampleFlagsPresent; // Sample flags present\n flags |= 0x0800 * +sampleCompositionTimeOffsetsPresent; // Sample composition time offsets present\n return fullBox('trun', 1, flags, [\n u32(trackData.currentChunk.samples.length), // Sample count\n u32(trackData.currentChunk.offset - trackData.currentChunk.moofOffset || 0), // Data offset\n firstSampleFlagsPresent ? u32(allSampleFlags[0]) : [],\n trackData.currentChunk.samples.map((_, i) => [\n sampleDurationPresent ? u32(allSampleDurations[i]) : [], // Sample duration\n sampleSizePresent ? u32(allSampleSizes[i]) : [], // Sample size\n sampleFlagsPresent ? u32(allSampleFlags[i]) : [], // Sample flags\n // Sample composition time offsets\n sampleCompositionTimeOffsetsPresent ? i32(allSampleCompositionTimeOffsets[i]) : [],\n ]),\n ]);\n};\n/**\n * Movie Fragment Random Access Box: For each track, provides pointers to sync samples within the file\n * for random access.\n */\nexport const mfra = (trackDatas) => {\n return box('mfra', undefined, [\n ...trackDatas.map(tfra),\n mfro(),\n ]);\n};\n/** Track Fragment Random Access Box: Provides pointers to sync samples within the file for random access. */\nexport const tfra = (trackData, trackIndex) => {\n const version = 1; // Using this version allows us to use 64-bit time and offset values\n return fullBox('tfra', version, 0, [\n u32(trackData.track.id), // Track ID\n u32(0b111111), // This specifies that traf number, trun number and sample number are 32-bit ints\n u32(trackData.finalizedChunks.length), // Number of entries\n trackData.finalizedChunks.map(chunk => [\n u64(intoTimescale(chunk.samples[0].timestamp, trackData.timescale)), // Time (in presentation time)\n u64(chunk.moofOffset), // moof offset\n u32(trackIndex + 1), // traf number\n u32(1), // trun number\n u32(1), // Sample number\n ]),\n ]);\n};\n/**\n * Movie Fragment Random Access Offset Box: Provides the size of the enclosing mfra box. This box can be used by readers\n * to quickly locate the mfra box by searching from the end of the file.\n */\nexport const mfro = () => {\n return fullBox('mfro', 0, 0, [\n // This value needs to be overwritten manually from the outside, where the actual size of the enclosing mfra box\n // is known\n u32(0), // Size\n ]);\n};\n/** VTT Empty Cue Box */\nexport const vtte = () => box('vtte');\n/** VTT Cue Box */\nexport const vttc = (payload, timestamp, identifier, settings, sourceId) => box('vttc', undefined, [\n sourceId !== null ? box('vsid', [i32(sourceId)]) : null,\n identifier !== null ? box('iden', [...textEncoder.encode(identifier)]) : null,\n timestamp !== null ? box('ctim', [...textEncoder.encode(formatSubtitleTimestamp(timestamp))]) : null,\n settings !== null ? box('sttg', [...textEncoder.encode(settings)]) : null,\n box('payl', [...textEncoder.encode(payload)]),\n]);\n/** VTT Additional Text Box */\nexport const vtta = (notes) => box('vtta', [...textEncoder.encode(notes)]);\n/** User Data Box */\nconst udta = (muxer) => {\n const boxes = [];\n const metadataFormat = muxer.format._options.metadataFormat ?? 'auto';\n const metadataTags = muxer.output._metadataTags;\n // Depending on the format, metadata tags are written differently\n if (metadataFormat === 'mdir' || (metadataFormat === 'auto' && !muxer.isQuickTime)) {\n const metaBox = metaMdir(metadataTags);\n if (metaBox)\n boxes.push(metaBox);\n }\n else if (metadataFormat === 'mdta') {\n const metaBox = metaMdta(metadataTags);\n if (metaBox)\n boxes.push(metaBox);\n }\n else if (metadataFormat === 'udta' || (metadataFormat === 'auto' && muxer.isQuickTime)) {\n addQuickTimeMetadataTagBoxes(boxes, muxer.output._metadataTags);\n }\n if (boxes.length === 0) {\n return null;\n }\n return box('udta', undefined, boxes);\n};\nconst addQuickTimeMetadataTagBoxes = (boxes, tags) => {\n // https://exiftool.org/TagNames/QuickTime.html (QuickTime UserData Tags)\n // For QuickTime files, metadata tags are dumped into the udta box\n for (const { key, value } of keyValueIterator(tags)) {\n switch (key) {\n case 'title':\n {\n boxes.push(metadataTagStringBoxShort('©nam', value));\n }\n ;\n break;\n case 'description':\n {\n boxes.push(metadataTagStringBoxShort('©des', value));\n }\n ;\n break;\n case 'artist':\n {\n boxes.push(metadataTagStringBoxShort('©ART', value));\n }\n ;\n break;\n case 'album':\n {\n boxes.push(metadataTagStringBoxShort('©alb', value));\n }\n ;\n break;\n case 'albumArtist':\n {\n boxes.push(metadataTagStringBoxShort('albr', value));\n }\n ;\n break;\n case 'genre':\n {\n boxes.push(metadataTagStringBoxShort('©gen', value));\n }\n ;\n break;\n case 'date':\n {\n boxes.push(metadataTagStringBoxShort('©day', value.toISOString().slice(0, 10)));\n }\n ;\n break;\n case 'comment':\n {\n boxes.push(metadataTagStringBoxShort('©cmt', value));\n }\n ;\n break;\n case 'lyrics':\n {\n boxes.push(metadataTagStringBoxShort('©lyr', value));\n }\n ;\n break;\n case 'raw':\n {\n // Handled later\n }\n ;\n break;\n case 'discNumber':\n case 'discsTotal':\n case 'trackNumber':\n case 'tracksTotal':\n case 'images':\n {\n // Not written for QuickTime (common Apple L)\n }\n ;\n break;\n default: assertNever(key);\n }\n }\n if (tags.raw) {\n for (const key in tags.raw) {\n const value = tags.raw[key];\n if (value == null || key.length !== 4 || boxes.some(x => x.type === key)) {\n continue;\n }\n if (typeof value === 'string') {\n boxes.push(metadataTagStringBoxShort(key, value));\n }\n else if (value instanceof Uint8Array) {\n boxes.push(box(key, Array.from(value)));\n }\n }\n }\n};\nconst metadataTagStringBoxShort = (name, value) => {\n const encoded = textEncoder.encode(value);\n return box(name, [\n u16(encoded.length),\n u16(getLanguageCodeInt('und')),\n Array.from(encoded),\n ]);\n};\nconst DATA_BOX_MIME_TYPE_MAP = {\n 'image/jpeg': 13,\n 'image/png': 14,\n 'image/bmp': 27,\n};\n/**\n * Generates key-value metadata for inclusion in the \"meta\" box.\n */\nconst generateMetadataPairs = (tags, isMdta) => {\n const pairs = [];\n // https://exiftool.org/TagNames/QuickTime.html (QuickTime ItemList Tags)\n // This is the metadata format used for MP4 files\n for (const { key, value } of keyValueIterator(tags)) {\n switch (key) {\n case 'title':\n {\n pairs.push({ key: isMdta ? 'title' : '©nam', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'description':\n {\n pairs.push({ key: isMdta ? 'description' : '©des', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'artist':\n {\n pairs.push({ key: isMdta ? 'artist' : '©ART', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'album':\n {\n pairs.push({ key: isMdta ? 'album' : '©alb', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'albumArtist':\n {\n pairs.push({ key: isMdta ? 'album_artist' : 'aART', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'comment':\n {\n pairs.push({ key: isMdta ? 'comment' : '©cmt', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'genre':\n {\n pairs.push({ key: isMdta ? 'genre' : '©gen', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'lyrics':\n {\n pairs.push({ key: isMdta ? 'lyrics' : '©lyr', value: dataStringBoxLong(value) });\n }\n ;\n break;\n case 'date':\n {\n pairs.push({\n key: isMdta ? 'date' : '©day',\n value: dataStringBoxLong(value.toISOString().slice(0, 10)),\n });\n }\n ;\n break;\n case 'images':\n {\n for (const image of value) {\n if (image.kind !== 'coverFront') {\n continue;\n }\n pairs.push({ key: 'covr', value: box('data', [\n u32(DATA_BOX_MIME_TYPE_MAP[image.mimeType] ?? 0), // Type indicator\n u32(0), // Locale indicator\n Array.from(image.data), // Kinda slow, hopefully temp\n ]) });\n }\n }\n ;\n break;\n case 'trackNumber':\n {\n if (isMdta) {\n const string = tags.tracksTotal !== undefined\n ? `${value}/${tags.tracksTotal}`\n : value.toString();\n pairs.push({ key: 'track', value: dataStringBoxLong(string) });\n }\n else {\n pairs.push({ key: 'trkn', value: box('data', [\n u32(0), // 8 bytes empty\n u32(0),\n u16(0), // Empty\n u16(value),\n u16(tags.tracksTotal ?? 0),\n u16(0), // Empty\n ]) });\n }\n }\n ;\n break;\n case 'discNumber':\n {\n if (!isMdta) {\n // Only written for mdir\n pairs.push({ key: 'disc', value: box('data', [\n u32(0), // 8 bytes empty\n u32(0),\n u16(0), // Empty\n u16(value),\n u16(tags.discsTotal ?? 0),\n u16(0), // Empty\n ]) });\n }\n }\n ;\n break;\n case 'tracksTotal':\n case 'discsTotal':\n {\n // These are included with 'trackNumber' and 'discNumber' respectively\n }\n ;\n break;\n case 'raw':\n {\n // Handled later\n }\n ;\n break;\n default: assertNever(key);\n }\n }\n if (tags.raw) {\n for (const key in tags.raw) {\n const value = tags.raw[key];\n if (value == null || (!isMdta && key.length !== 4) || pairs.some(x => x.key === key)) {\n continue;\n }\n if (typeof value === 'string') {\n pairs.push({ key, value: dataStringBoxLong(value) });\n }\n else if (value instanceof Uint8Array) {\n pairs.push({ key, value: box('data', [\n u32(0), // Type indicator\n u32(0), // Locale indicator\n Array.from(value),\n ]) });\n }\n else if (value instanceof RichImageData) {\n pairs.push({ key, value: box('data', [\n u32(DATA_BOX_MIME_TYPE_MAP[value.mimeType] ?? 0), // Type indicator\n u32(0), // Locale indicator\n Array.from(value.data), // Kinda slow, hopefully temp\n ]) });\n }\n }\n }\n return pairs;\n};\n/** Metadata Box (mdir format) */\nconst metaMdir = (tags) => {\n const pairs = generateMetadataPairs(tags, false);\n if (pairs.length === 0) {\n return null;\n }\n // fullBox format\n return fullBox('meta', 0, 0, undefined, [\n hdlr(false, 'mdir', '', 'appl'), // mdir handler\n box('ilst', undefined, pairs.map(pair => box(pair.key, undefined, [pair.value]))), // Item list without keys box\n ]);\n};\n/** Metadata Box (mdta format with keys box) */\nconst metaMdta = (tags) => {\n const pairs = generateMetadataPairs(tags, true);\n if (pairs.length === 0) {\n return null;\n }\n // box without version and flags\n return box('meta', undefined, [\n hdlr(false, 'mdta', ''), // mdta handler\n fullBox('keys', 0, 0, [\n u32(pairs.length),\n ], pairs.map(pair => box('mdta', [\n ...textEncoder.encode(pair.key),\n ]))),\n box('ilst', undefined, pairs.map((pair, i) => {\n const boxName = String.fromCharCode(...u32(i + 1));\n return box(boxName, undefined, [pair.value]);\n })),\n ]);\n};\nconst dataStringBoxLong = (value) => {\n return box('data', [\n u32(1), // Type indicator (UTF-8)\n u32(0), // Locale indicator\n ...textEncoder.encode(value),\n ]);\n};\nconst videoCodecToBoxName = (codec, fullCodecString) => {\n switch (codec) {\n case 'avc': return fullCodecString.startsWith('avc3') ? 'avc3' : 'avc1';\n case 'hevc': return 'hvc1';\n case 'vp8': return 'vp08';\n case 'vp9': return 'vp09';\n case 'av1': return 'av01';\n }\n};\nconst VIDEO_CODEC_TO_CONFIGURATION_BOX = {\n avc: avcC,\n hevc: hvcC,\n vp8: vpcC,\n vp9: vpcC,\n av1: av1C,\n};\nconst audioCodecToBoxName = (codec, isQuickTime) => {\n switch (codec) {\n case 'aac': return 'mp4a';\n case 'mp3': return 'mp4a';\n case 'opus': return 'Opus';\n case 'vorbis': return 'mp4a';\n case 'flac': return 'fLaC';\n case 'ulaw': return 'ulaw';\n case 'alaw': return 'alaw';\n case 'pcm-u8': return 'raw ';\n case 'pcm-s8': return 'sowt';\n }\n // Logic diverges here\n if (isQuickTime) {\n switch (codec) {\n case 'pcm-s16': return 'sowt';\n case 'pcm-s16be': return 'twos';\n case 'pcm-s24': return 'in24';\n case 'pcm-s24be': return 'in24';\n case 'pcm-s32': return 'in32';\n case 'pcm-s32be': return 'in32';\n case 'pcm-f32': return 'fl32';\n case 'pcm-f32be': return 'fl32';\n case 'pcm-f64': return 'fl64';\n case 'pcm-f64be': return 'fl64';\n }\n }\n else {\n switch (codec) {\n case 'pcm-s16': return 'ipcm';\n case 'pcm-s16be': return 'ipcm';\n case 'pcm-s24': return 'ipcm';\n case 'pcm-s24be': return 'ipcm';\n case 'pcm-s32': return 'ipcm';\n case 'pcm-s32be': return 'ipcm';\n case 'pcm-f32': return 'fpcm';\n case 'pcm-f32be': return 'fpcm';\n case 'pcm-f64': return 'fpcm';\n case 'pcm-f64be': return 'fpcm';\n }\n }\n};\nconst audioCodecToConfigurationBox = (codec, isQuickTime) => {\n switch (codec) {\n case 'aac': return esds;\n case 'mp3': return esds;\n case 'opus': return dOps;\n case 'vorbis': return esds;\n case 'flac': return dfLa;\n }\n // Logic diverges here\n if (isQuickTime) {\n switch (codec) {\n case 'pcm-s24': return wave;\n case 'pcm-s24be': return wave;\n case 'pcm-s32': return wave;\n case 'pcm-s32be': return wave;\n case 'pcm-f32': return wave;\n case 'pcm-f32be': return wave;\n case 'pcm-f64': return wave;\n case 'pcm-f64be': return wave;\n }\n }\n else {\n switch (codec) {\n case 'pcm-s16': return pcmC;\n case 'pcm-s16be': return pcmC;\n case 'pcm-s24': return pcmC;\n case 'pcm-s24be': return pcmC;\n case 'pcm-s32': return pcmC;\n case 'pcm-s32be': return pcmC;\n case 'pcm-f32': return pcmC;\n case 'pcm-f32be': return pcmC;\n case 'pcm-f64': return pcmC;\n case 'pcm-f64be': return pcmC;\n }\n }\n return null;\n};\nconst SUBTITLE_CODEC_TO_BOX_NAME = {\n webvtt: 'wvtt',\n};\nconst SUBTITLE_CODEC_TO_CONFIGURATION_BOX = {\n webvtt: vttC,\n};\nconst getLanguageCodeInt = (code) => {\n assert(code.length === 3);\n ;\n let language = 0;\n for (let i = 0; i < 3; i++) {\n language <<= 5;\n language += code.charCodeAt(i) - 0x60;\n }\n return language;\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { assert } from './misc.js';\nexport class Writer {\n constructor() {\n /** Setting this to true will cause the writer to ensure data is written in a strictly monotonic, streamable way. */\n this.ensureMonotonicity = false;\n this.trackedWrites = null;\n this.trackedStart = -1;\n this.trackedEnd = -1;\n }\n start() { }\n maybeTrackWrites(data) {\n if (!this.trackedWrites) {\n return;\n }\n // Handle negative relative write positions\n let pos = this.getPos();\n if (pos < this.trackedStart) {\n if (pos + data.byteLength <= this.trackedStart) {\n return;\n }\n data = data.subarray(this.trackedStart - pos);\n pos = 0;\n }\n const neededSize = pos + data.byteLength - this.trackedStart;\n let newLength = this.trackedWrites.byteLength;\n while (newLength < neededSize) {\n newLength *= 2;\n }\n // Check if we need to resize the buffer\n if (newLength !== this.trackedWrites.byteLength) {\n const copy = new Uint8Array(newLength);\n copy.set(this.trackedWrites, 0);\n this.trackedWrites = copy;\n }\n this.trackedWrites.set(data, pos - this.trackedStart);\n this.trackedEnd = Math.max(this.trackedEnd, pos + data.byteLength);\n }\n startTrackingWrites() {\n this.trackedWrites = new Uint8Array(2 ** 10);\n this.trackedStart = this.getPos();\n this.trackedEnd = this.trackedStart;\n }\n stopTrackingWrites() {\n if (!this.trackedWrites) {\n throw new Error('Internal error: Can\\'t get tracked writes since nothing was tracked.');\n }\n const slice = this.trackedWrites.subarray(0, this.trackedEnd - this.trackedStart);\n const result = {\n data: slice,\n start: this.trackedStart,\n end: this.trackedEnd,\n };\n this.trackedWrites = null;\n return result;\n }\n}\nconst ARRAY_BUFFER_INITIAL_SIZE = 2 ** 16;\nconst ARRAY_BUFFER_MAX_SIZE = 2 ** 32;\nexport class BufferTargetWriter extends Writer {\n constructor(target) {\n super();\n this.pos = 0;\n this.maxPos = 0;\n this.target = target;\n this.supportsResize = 'resize' in new ArrayBuffer(0);\n if (this.supportsResize) {\n try {\n // @ts-expect-error Don't want to bump \"lib\" in tsconfig\n this.buffer = new ArrayBuffer(ARRAY_BUFFER_INITIAL_SIZE, { maxByteLength: ARRAY_BUFFER_MAX_SIZE });\n }\n catch {\n this.buffer = new ArrayBuffer(ARRAY_BUFFER_INITIAL_SIZE);\n this.supportsResize = false;\n }\n }\n else {\n this.buffer = new ArrayBuffer(ARRAY_BUFFER_INITIAL_SIZE);\n }\n this.bytes = new Uint8Array(this.buffer);\n }\n ensureSize(size) {\n let newLength = this.buffer.byteLength;\n while (newLength < size)\n newLength *= 2;\n if (newLength === this.buffer.byteLength)\n return;\n if (newLength > ARRAY_BUFFER_MAX_SIZE) {\n throw new Error(`ArrayBuffer exceeded maximum size of ${ARRAY_BUFFER_MAX_SIZE} bytes. Please consider using another`\n + ` target.`);\n }\n if (this.supportsResize) {\n // Use resize if it exists\n // @ts-expect-error Don't want to bump \"lib\" in tsconfig\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n this.buffer.resize(newLength);\n // The Uint8Array scales automatically\n }\n else {\n const newBuffer = new ArrayBuffer(newLength);\n const newBytes = new Uint8Array(newBuffer);\n newBytes.set(this.bytes, 0);\n this.buffer = newBuffer;\n this.bytes = newBytes;\n }\n }\n write(data) {\n this.maybeTrackWrites(data);\n this.ensureSize(this.pos + data.byteLength);\n this.bytes.set(data, this.pos);\n this.target.onwrite?.(this.pos, this.pos + data.byteLength);\n this.pos += data.byteLength;\n this.maxPos = Math.max(this.maxPos, this.pos);\n }\n seek(newPos) {\n this.pos = newPos;\n }\n getPos() {\n return this.pos;\n }\n async flush() { }\n async finalize() {\n this.ensureSize(this.pos);\n this.target.buffer = this.buffer.slice(0, Math.max(this.maxPos, this.pos));\n }\n async close() { }\n getSlice(start, end) {\n return this.bytes.slice(start, end);\n }\n}\nconst DEFAULT_CHUNK_SIZE = 2 ** 24;\nconst MAX_CHUNKS_AT_ONCE = 2;\n/**\n * Writes to a StreamTarget every time it is flushed, sending out all of the new data written since the\n * last flush. This is useful for streaming applications, like piping the output to disk. When using the chunked mode,\n * data will first be accumulated in larger chunks, and then the entire chunk will be flushed out at once when ready.\n */\nexport class StreamTargetWriter extends Writer {\n constructor(target) {\n super();\n this.pos = 0;\n this.sections = [];\n this.lastWriteEnd = 0;\n this.lastFlushEnd = 0;\n this.writer = null;\n /**\n * The data is divided up into fixed-size chunks, whose contents are first filled in RAM and then flushed out.\n * A chunk is flushed if all of its contents have been written.\n */\n this.chunks = [];\n this.target = target;\n this.chunked = target._options.chunked ?? false;\n this.chunkSize = target._options.chunkSize ?? DEFAULT_CHUNK_SIZE;\n }\n start() {\n this.writer = this.target._writable.getWriter();\n }\n write(data) {\n if (this.pos > this.lastWriteEnd) {\n const paddingBytesNeeded = this.pos - this.lastWriteEnd;\n this.pos = this.lastWriteEnd;\n this.write(new Uint8Array(paddingBytesNeeded));\n }\n this.maybeTrackWrites(data);\n this.sections.push({\n data: data.slice(),\n start: this.pos,\n });\n this.target.onwrite?.(this.pos, this.pos + data.byteLength);\n this.pos += data.byteLength;\n this.lastWriteEnd = Math.max(this.lastWriteEnd, this.pos);\n }\n seek(newPos) {\n this.pos = newPos;\n }\n getPos() {\n return this.pos;\n }\n async flush() {\n if (this.pos > this.lastWriteEnd) {\n // There's a \"void\" between the last written byte and the next byte we're about to write. Let's pad that\n // void with zeroes explicitly.\n const paddingBytesNeeded = this.pos - this.lastWriteEnd;\n this.pos = this.lastWriteEnd;\n this.write(new Uint8Array(paddingBytesNeeded));\n }\n assert(this.writer);\n if (this.sections.length === 0)\n return;\n const chunks = [];\n const sorted = [...this.sections].sort((a, b) => a.start - b.start);\n chunks.push({\n start: sorted[0].start,\n size: sorted[0].data.byteLength,\n });\n // Figure out how many contiguous chunks we have\n for (let i = 1; i < sorted.length; i++) {\n const lastChunk = chunks[chunks.length - 1];\n const section = sorted[i];\n if (section.start <= lastChunk.start + lastChunk.size) {\n lastChunk.size = Math.max(lastChunk.size, section.start + section.data.byteLength - lastChunk.start);\n }\n else {\n chunks.push({\n start: section.start,\n size: section.data.byteLength,\n });\n }\n }\n for (const chunk of chunks) {\n chunk.data = new Uint8Array(chunk.size);\n // Make sure to write the data in the correct order for correct overwriting\n for (const section of this.sections) {\n // Check if the section is in the chunk\n if (chunk.start <= section.start && section.start < chunk.start + chunk.size) {\n chunk.data.set(section.data, section.start - chunk.start);\n }\n }\n if (this.writer.desiredSize !== null && this.writer.desiredSize <= 0) {\n await this.writer.ready; // Allow the writer to apply backpressure\n }\n if (this.chunked) {\n // Let's first gather the data into bigger chunks before writing it\n this.writeDataIntoChunks(chunk.data, chunk.start);\n this.tryToFlushChunks();\n }\n else {\n if (this.ensureMonotonicity && chunk.start !== this.lastFlushEnd) {\n throw new Error('Internal error: Monotonicity violation.');\n }\n // Write out the data immediately\n void this.writer.write({\n type: 'write',\n data: chunk.data,\n position: chunk.start,\n });\n this.lastFlushEnd = chunk.start + chunk.data.byteLength;\n }\n }\n this.sections.length = 0;\n }\n writeDataIntoChunks(data, position) {\n // First, find the chunk to write the data into, or create one if none exists\n let chunkIndex = this.chunks.findIndex(x => x.start <= position && position < x.start + this.chunkSize);\n if (chunkIndex === -1)\n chunkIndex = this.createChunk(position);\n const chunk = this.chunks[chunkIndex];\n // Figure out how much to write to the chunk, and then write to the chunk\n const relativePosition = position - chunk.start;\n const toWrite = data.subarray(0, Math.min(this.chunkSize - relativePosition, data.byteLength));\n chunk.data.set(toWrite, relativePosition);\n // Create a section describing the region of data that was just written to\n const section = {\n start: relativePosition,\n end: relativePosition + toWrite.byteLength,\n };\n this.insertSectionIntoChunk(chunk, section);\n // Queue chunk for flushing to target if it has been fully written to\n if (chunk.written[0].start === 0 && chunk.written[0].end === this.chunkSize) {\n chunk.shouldFlush = true;\n }\n // Make sure we don't hold too many chunks in memory at once to keep memory usage down\n if (this.chunks.length > MAX_CHUNKS_AT_ONCE) {\n // Flush all but the last chunk\n for (let i = 0; i < this.chunks.length - 1; i++) {\n this.chunks[i].shouldFlush = true;\n }\n this.tryToFlushChunks();\n }\n // If the data didn't fit in one chunk, recurse with the remaining data\n if (toWrite.byteLength < data.byteLength) {\n this.writeDataIntoChunks(data.subarray(toWrite.byteLength), position + toWrite.byteLength);\n }\n }\n insertSectionIntoChunk(chunk, section) {\n let low = 0;\n let high = chunk.written.length - 1;\n let index = -1;\n // Do a binary search to find the last section with a start not larger than `section`'s start\n while (low <= high) {\n const mid = Math.floor(low + (high - low + 1) / 2);\n if (chunk.written[mid].start <= section.start) {\n low = mid + 1;\n index = mid;\n }\n else {\n high = mid - 1;\n }\n }\n // Insert the new section\n chunk.written.splice(index + 1, 0, section);\n if (index === -1 || chunk.written[index].end < section.start)\n index++;\n // Merge overlapping sections\n while (index < chunk.written.length - 1 && chunk.written[index].end >= chunk.written[index + 1].start) {\n chunk.written[index].end = Math.max(chunk.written[index].end, chunk.written[index + 1].end);\n chunk.written.splice(index + 1, 1);\n }\n }\n createChunk(includesPosition) {\n const start = Math.floor(includesPosition / this.chunkSize) * this.chunkSize;\n const chunk = {\n start,\n data: new Uint8Array(this.chunkSize),\n written: [],\n shouldFlush: false,\n };\n this.chunks.push(chunk);\n this.chunks.sort((a, b) => a.start - b.start);\n return this.chunks.indexOf(chunk);\n }\n tryToFlushChunks(force = false) {\n assert(this.writer);\n for (let i = 0; i < this.chunks.length; i++) {\n const chunk = this.chunks[i];\n if (!chunk.shouldFlush && !force)\n continue;\n for (const section of chunk.written) {\n const position = chunk.start + section.start;\n if (this.ensureMonotonicity && position !== this.lastFlushEnd) {\n throw new Error('Internal error: Monotonicity violation.');\n }\n void this.writer.write({\n type: 'write',\n data: chunk.data.subarray(section.start, section.end),\n position,\n });\n this.lastFlushEnd = chunk.start + section.end;\n }\n this.chunks.splice(i--, 1);\n }\n }\n finalize() {\n if (this.chunked) {\n this.tryToFlushChunks(true);\n }\n assert(this.writer);\n return this.writer.close();\n }\n async close() {\n return this.writer?.close();\n }\n}\nexport class NullTargetWriter extends Writer {\n constructor(target) {\n super();\n this.target = target;\n this.pos = 0;\n }\n write(data) {\n this.maybeTrackWrites(data);\n this.target.onwrite?.(this.pos, this.pos + data.byteLength);\n this.pos += data.byteLength;\n }\n getPos() {\n return this.pos;\n }\n seek(newPos) {\n this.pos = newPos;\n }\n async flush() { }\n async finalize() { }\n async close() { }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { BufferTargetWriter, NullTargetWriter, StreamTargetWriter } from './writer.js';\nimport * as nodeAlias from './node.js';\nimport { assert } from './misc.js';\nconst node = typeof nodeAlias !== 'undefined'\n ? nodeAlias // Aliasing it prevents some bundler warnings\n : undefined;\n/**\n * Base class for targets, specifying where output files are written.\n * @group Output targets\n * @public\n */\nexport class Target {\n constructor() {\n /** @internal */\n this._output = null;\n /**\n * Called each time data is written to the target. Will be called with the byte range into which data was written.\n *\n * Use this callback to track the size of the output file as it grows. But be warned, this function is chatty and\n * gets called *extremely* often.\n */\n this.onwrite = null;\n }\n}\n/**\n * A target that writes data directly into an ArrayBuffer in memory. Great for performance, but not suitable for very\n * large files. The buffer will be available once the output has been finalized.\n * @group Output targets\n * @public\n */\nexport class BufferTarget extends Target {\n constructor() {\n super(...arguments);\n /** Stores the final output buffer. Until the output is finalized, this will be `null`. */\n this.buffer = null;\n }\n /** @internal */\n _createWriter() {\n return new BufferTargetWriter(this);\n }\n}\n/**\n * This target writes data to a [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream),\n * making it a general-purpose target for writing data anywhere. It is also compatible with\n * [`FileSystemWritableFileStream`](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream) for\n * use with the [File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API). The\n * `WritableStream` can also apply backpressure, which will propagate to the output and throttle the encoders.\n * @group Output targets\n * @public\n */\nexport class StreamTarget extends Target {\n /** Creates a new {@link StreamTarget} which writes to the specified `writable`. */\n constructor(writable, options = {}) {\n super();\n if (!(writable instanceof WritableStream)) {\n throw new TypeError('StreamTarget requires a WritableStream instance.');\n }\n if (options != null && typeof options !== 'object') {\n throw new TypeError('StreamTarget options, when provided, must be an object.');\n }\n if (options.chunked !== undefined && typeof options.chunked !== 'boolean') {\n throw new TypeError('options.chunked, when provided, must be a boolean.');\n }\n if (options.chunkSize !== undefined && (!Number.isInteger(options.chunkSize) || options.chunkSize < 1024)) {\n throw new TypeError('options.chunkSize, when provided, must be an integer and not smaller than 1024.');\n }\n this._writable = writable;\n this._options = options;\n }\n /** @internal */\n _createWriter() {\n return new StreamTargetWriter(this);\n }\n}\n/**\n * A target that writes to a file at the specified path. Intended for server-side usage in Node, Bun, or Deno.\n *\n * Writing is chunked by default. The internally held file handle will be closed when `.finalize()` or `.cancel()` are\n * called on the corresponding {@link Output}.\n * @group Output targets\n * @public\n */\nexport class FilePathTarget extends Target {\n /** Creates a new {@link FilePathTarget} that writes to the file at the specified file path. */\n constructor(filePath, options = {}) {\n if (typeof filePath !== 'string') {\n throw new TypeError('filePath must be a string.');\n }\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n super();\n /** @internal */\n this._fileHandle = null;\n // Let's back this target with a StreamTarget, makes the implementation very simple\n const writable = new WritableStream({\n start: async () => {\n this._fileHandle = await node.fs.open(filePath, 'w');\n },\n write: async (chunk) => {\n assert(this._fileHandle);\n await this._fileHandle.write(chunk.data, 0, chunk.data.byteLength, chunk.position);\n },\n close: async () => {\n if (this._fileHandle) {\n await this._fileHandle.close();\n this._fileHandle = null;\n }\n },\n });\n this._streamTarget = new StreamTarget(writable, {\n chunked: true,\n ...options,\n });\n this._streamTarget._output = this._output;\n }\n /** @internal */\n _createWriter() {\n return this._streamTarget._createWriter();\n }\n}\n/**\n * This target just discards all incoming data. It is useful for when you need an {@link Output} but extract data from\n * it differently, for example through format-specific callbacks (`onMoof`, `onMdat`, ...) or encoder events.\n * @group Output targets\n * @public\n */\nexport class NullTarget extends Target {\n /** @internal */\n _createWriter() {\n return new NullTargetWriter(this);\n }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { free, ftyp, IsobmffBoxWriter, mdat, mfra, moof, moov, vtta, vttc, vtte } from './isobmff-boxes.js';\nimport { Muxer } from '../muxer.js';\nimport { BufferTargetWriter } from '../writer.js';\nimport { assert, computeRationalApproximation, last, promiseWithResolvers } from '../misc.js';\nimport { MovOutputFormat } from '../output-format.js';\nimport { inlineTimestampRegex } from '../subtitles.js';\nimport { parsePcmCodec, PCM_AUDIO_CODECS, validateAudioChunkMetadata, validateSubtitleMetadata, validateVideoChunkMetadata, } from '../codec.js';\nimport { BufferTarget } from '../target.js';\nimport { extractAvcDecoderConfigurationRecord, extractHevcDecoderConfigurationRecord, serializeAvcDecoderConfigurationRecord, serializeHevcDecoderConfigurationRecord, transformAnnexBToLengthPrefixed, } from '../codec-data.js';\nimport { buildIsobmffMimeType } from './isobmff-misc.js';\nimport { MAX_BOX_HEADER_SIZE, MIN_BOX_HEADER_SIZE } from './isobmff-reader.js';\nexport const GLOBAL_TIMESCALE = 1000;\nconst TIMESTAMP_OFFSET = 2_082_844_800; // Seconds between Jan 1 1904 and Jan 1 1970\nexport const getTrackMetadata = (trackData) => {\n const metadata = {};\n const track = trackData.track;\n if (track.metadata.name !== undefined) {\n metadata.name = track.metadata.name;\n }\n return metadata;\n};\nexport const intoTimescale = (timeInSeconds, timescale, round = true) => {\n const value = timeInSeconds * timescale;\n return round ? Math.round(value) : value;\n};\nexport class IsobmffMuxer extends Muxer {\n constructor(output, format) {\n super(output);\n this.auxTarget = new BufferTarget();\n this.auxWriter = this.auxTarget._createWriter();\n this.auxBoxWriter = new IsobmffBoxWriter(this.auxWriter);\n this.mdat = null;\n this.ftypSize = null;\n this.trackDatas = [];\n this.allTracksKnown = promiseWithResolvers();\n this.creationTime = Math.floor(Date.now() / 1000) + TIMESTAMP_OFFSET;\n this.finalizedChunks = [];\n this.nextFragmentNumber = 1;\n // Only relevant for fragmented files, to make sure new fragments start with the highest timestamp seen so far\n this.maxWrittenTimestamp = -Infinity;\n this.format = format;\n this.writer = output._writer;\n this.boxWriter = new IsobmffBoxWriter(this.writer);\n this.isQuickTime = format instanceof MovOutputFormat;\n // If the fastStart option isn't defined, enable in-memory fast start if the target is an ArrayBuffer, as the\n // memory usage remains identical\n const fastStartDefault = this.writer instanceof BufferTargetWriter ? 'in-memory' : false;\n this.fastStart = format._options.fastStart ?? fastStartDefault;\n this.isFragmented = this.fastStart === 'fragmented';\n if (this.fastStart === 'in-memory' || this.isFragmented) {\n this.writer.ensureMonotonicity = true;\n }\n this.minimumFragmentDuration = format._options.minimumFragmentDuration ?? 1;\n }\n async start() {\n const release = await this.mutex.acquire();\n const holdsAvc = this.output._tracks.some(x => x.type === 'video' && x.source._codec === 'avc');\n // Write the header\n {\n if (this.format._options.onFtyp) {\n this.writer.startTrackingWrites();\n }\n this.boxWriter.writeBox(ftyp({\n isQuickTime: this.isQuickTime,\n holdsAvc: holdsAvc,\n fragmented: this.isFragmented,\n }));\n if (this.format._options.onFtyp) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onFtyp(data, start);\n }\n }\n this.ftypSize = this.writer.getPos();\n if (this.fastStart === 'in-memory') {\n // We're write at finalization\n }\n else if (this.fastStart === 'reserve') {\n // Validate that all tracks have set maximumPacketCount\n for (const track of this.output._tracks) {\n if (track.metadata.maximumPacketCount === undefined) {\n throw new Error('All tracks must specify maximumPacketCount in their metadata when using'\n + ' fastStart: \\'reserve\\'.');\n }\n }\n // We'll start writing once we know all tracks\n }\n else if (this.isFragmented) {\n // We write the moov box once we write out the first fragment to make sure we get the decoder configs\n }\n else {\n if (this.format._options.onMdat) {\n this.writer.startTrackingWrites();\n }\n this.mdat = mdat(true); // Reserve large size by default, can refine this when finalizing.\n this.boxWriter.writeBox(this.mdat);\n }\n await this.writer.flush();\n release();\n }\n allTracksAreKnown() {\n for (const track of this.output._tracks) {\n if (!track.source._closed && !this.trackDatas.some(x => x.track === track)) {\n return false; // We haven't seen a sample from this open track yet\n }\n }\n return true;\n }\n async getMimeType() {\n await this.allTracksKnown.promise;\n const codecStrings = this.trackDatas.map((trackData) => {\n if (trackData.type === 'video') {\n return trackData.info.decoderConfig.codec;\n }\n else if (trackData.type === 'audio') {\n return trackData.info.decoderConfig.codec;\n }\n else {\n const map = {\n webvtt: 'wvtt',\n };\n return map[trackData.track.source._codec];\n }\n });\n return buildIsobmffMimeType({\n isQuickTime: this.isQuickTime,\n hasVideo: this.trackDatas.some(x => x.type === 'video'),\n hasAudio: this.trackDatas.some(x => x.type === 'audio'),\n codecStrings,\n });\n }\n getVideoTrackData(track, packet, meta) {\n const existingTrackData = this.trackDatas.find(x => x.track === track);\n if (existingTrackData) {\n return existingTrackData;\n }\n validateVideoChunkMetadata(meta);\n assert(meta);\n assert(meta.decoderConfig);\n const decoderConfig = { ...meta.decoderConfig };\n assert(decoderConfig.codedWidth !== undefined);\n assert(decoderConfig.codedHeight !== undefined);\n let requiresAnnexBTransformation = false;\n if (track.source._codec === 'avc' && !decoderConfig.description) {\n // ISOBMFF can only hold AVC in the AVCC format, not in Annex B, but the missing description indicates\n // Annex B. This means we'll need to do some converterino.\n const decoderConfigurationRecord = extractAvcDecoderConfigurationRecord(packet.data);\n if (!decoderConfigurationRecord) {\n throw new Error('Couldn\\'t extract an AVCDecoderConfigurationRecord from the AVC packet. Make sure the packets are'\n + ' in Annex B format (as specified in ITU-T-REC-H.264) when not providing a description, or'\n + ' provide a description (must be an AVCDecoderConfigurationRecord as specified in ISO 14496-15)'\n + ' and ensure the packets are in AVCC format.');\n }\n decoderConfig.description = serializeAvcDecoderConfigurationRecord(decoderConfigurationRecord);\n requiresAnnexBTransformation = true;\n }\n else if (track.source._codec === 'hevc' && !decoderConfig.description) {\n // ISOBMFF can only hold HEVC in the HEVC format, not in Annex B, but the missing description indicates\n // Annex B. This means we'll need to do some converterino.\n const decoderConfigurationRecord = extractHevcDecoderConfigurationRecord(packet.data);\n if (!decoderConfigurationRecord) {\n throw new Error('Couldn\\'t extract an HEVCDecoderConfigurationRecord from the HEVC packet. Make sure the packets'\n + ' are in Annex B format (as specified in ITU-T-REC-H.265) when not providing a description, or'\n + ' provide a description (must be an HEVCDecoderConfigurationRecord as specified in ISO 14496-15)'\n + ' and ensure the packets are in HEVC format.');\n }\n decoderConfig.description = serializeHevcDecoderConfigurationRecord(decoderConfigurationRecord);\n requiresAnnexBTransformation = true;\n }\n // The frame rate set by the user may not be an integer. Since timescale is an integer, we'll approximate the\n // frame time (inverse of frame rate) with a rational number, then use that approximation's denominator\n // as the timescale.\n const timescale = computeRationalApproximation(1 / (track.metadata.frameRate ?? 57600), 1e6).denominator;\n const newTrackData = {\n muxer: this,\n track,\n type: 'video',\n info: {\n width: decoderConfig.codedWidth,\n height: decoderConfig.codedHeight,\n decoderConfig: decoderConfig,\n requiresAnnexBTransformation,\n },\n timescale,\n samples: [],\n sampleQueue: [],\n timestampProcessingQueue: [],\n timeToSampleTable: [],\n compositionTimeOffsetTable: [],\n lastTimescaleUnits: null,\n lastSample: null,\n finalizedChunks: [],\n currentChunk: null,\n compactlyCodedChunkTable: [],\n };\n this.trackDatas.push(newTrackData);\n this.trackDatas.sort((a, b) => a.track.id - b.track.id);\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n return newTrackData;\n }\n getAudioTrackData(track, meta) {\n const existingTrackData = this.trackDatas.find(x => x.track === track);\n if (existingTrackData) {\n return existingTrackData;\n }\n validateAudioChunkMetadata(meta);\n assert(meta);\n assert(meta.decoderConfig);\n const newTrackData = {\n muxer: this,\n track,\n type: 'audio',\n info: {\n numberOfChannels: meta.decoderConfig.numberOfChannels,\n sampleRate: meta.decoderConfig.sampleRate,\n decoderConfig: meta.decoderConfig,\n requiresPcmTransformation: !this.isFragmented\n && PCM_AUDIO_CODECS.includes(track.source._codec),\n },\n timescale: meta.decoderConfig.sampleRate,\n samples: [],\n sampleQueue: [],\n timestampProcessingQueue: [],\n timeToSampleTable: [],\n compositionTimeOffsetTable: [],\n lastTimescaleUnits: null,\n lastSample: null,\n finalizedChunks: [],\n currentChunk: null,\n compactlyCodedChunkTable: [],\n };\n this.trackDatas.push(newTrackData);\n this.trackDatas.sort((a, b) => a.track.id - b.track.id);\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n return newTrackData;\n }\n getSubtitleTrackData(track, meta) {\n const existingTrackData = this.trackDatas.find(x => x.track === track);\n if (existingTrackData) {\n return existingTrackData;\n }\n validateSubtitleMetadata(meta);\n assert(meta);\n assert(meta.config);\n const newTrackData = {\n muxer: this,\n track,\n type: 'subtitle',\n info: {\n config: meta.config,\n },\n timescale: 1000, // Reasonable\n samples: [],\n sampleQueue: [],\n timestampProcessingQueue: [],\n timeToSampleTable: [],\n compositionTimeOffsetTable: [],\n lastTimescaleUnits: null,\n lastSample: null,\n finalizedChunks: [],\n currentChunk: null,\n compactlyCodedChunkTable: [],\n lastCueEndTimestamp: 0,\n cueQueue: [],\n nextSourceId: 0,\n cueToSourceId: new WeakMap(),\n };\n this.trackDatas.push(newTrackData);\n this.trackDatas.sort((a, b) => a.track.id - b.track.id);\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n return newTrackData;\n }\n async addEncodedVideoPacket(track, packet, meta) {\n const release = await this.mutex.acquire();\n try {\n const trackData = this.getVideoTrackData(track, packet, meta);\n let packetData = packet.data;\n if (trackData.info.requiresAnnexBTransformation) {\n const transformedData = transformAnnexBToLengthPrefixed(packetData);\n if (!transformedData) {\n throw new Error('Failed to transform packet data. Make sure all packets are provided in Annex B format, as'\n + ' specified in ITU-T-REC-H.264 and ITU-T-REC-H.265.');\n }\n packetData = transformedData;\n }\n const timestamp = this.validateAndNormalizeTimestamp(trackData.track, packet.timestamp, packet.type === 'key');\n const internalSample = this.createSampleForTrack(trackData, packetData, timestamp, packet.duration, packet.type);\n await this.registerSample(trackData, internalSample);\n }\n finally {\n release();\n }\n }\n async addEncodedAudioPacket(track, packet, meta) {\n const release = await this.mutex.acquire();\n try {\n const trackData = this.getAudioTrackData(track, meta);\n const timestamp = this.validateAndNormalizeTimestamp(trackData.track, packet.timestamp, packet.type === 'key');\n const internalSample = this.createSampleForTrack(trackData, packet.data, timestamp, packet.duration, packet.type);\n if (trackData.info.requiresPcmTransformation) {\n await this.maybePadWithSilence(trackData, timestamp);\n }\n await this.registerSample(trackData, internalSample);\n }\n finally {\n release();\n }\n }\n async maybePadWithSilence(trackData, untilTimestamp) {\n // The PCM transformation assumes that all samples are contiguous. This is not something that is enforced, so\n // we need to pad the \"holes\" in between samples (and before the first sample) with additional\n // \"silence samples\".\n const lastSample = last(trackData.samples);\n const lastEndTimestamp = lastSample\n ? lastSample.timestamp + lastSample.duration\n : 0;\n const delta = untilTimestamp - lastEndTimestamp;\n const deltaInTimescale = intoTimescale(delta, trackData.timescale);\n if (deltaInTimescale > 0) {\n const { sampleSize, silentValue } = parsePcmCodec(trackData.info.decoderConfig.codec);\n const samplesNeeded = deltaInTimescale * trackData.info.numberOfChannels;\n const data = new Uint8Array(sampleSize * samplesNeeded).fill(silentValue);\n const paddingSample = this.createSampleForTrack(trackData, new Uint8Array(data.buffer), lastEndTimestamp, delta, 'key');\n await this.registerSample(trackData, paddingSample);\n }\n }\n async addSubtitleCue(track, cue, meta) {\n const release = await this.mutex.acquire();\n try {\n const trackData = this.getSubtitleTrackData(track, meta);\n this.validateAndNormalizeTimestamp(trackData.track, cue.timestamp, true);\n if (track.source._codec === 'webvtt') {\n trackData.cueQueue.push(cue);\n await this.processWebVTTCues(trackData, cue.timestamp);\n }\n else {\n // TODO\n }\n }\n finally {\n release();\n }\n }\n async processWebVTTCues(trackData, until) {\n // WebVTT cues need to undergo special processing as empty sections need to be padded out with samples, and\n // overlapping samples require special logic. The algorithm produces the format specified in ISO 14496-30.\n while (trackData.cueQueue.length > 0) {\n const timestamps = new Set([]);\n for (const cue of trackData.cueQueue) {\n assert(cue.timestamp <= until);\n assert(trackData.lastCueEndTimestamp <= cue.timestamp + cue.duration);\n timestamps.add(Math.max(cue.timestamp, trackData.lastCueEndTimestamp)); // Start timestamp\n timestamps.add(cue.timestamp + cue.duration); // End timestamp\n }\n const sortedTimestamps = [...timestamps].sort((a, b) => a - b);\n // These are the timestamps of the next sample we'll create:\n const sampleStart = sortedTimestamps[0];\n const sampleEnd = sortedTimestamps[1] ?? sampleStart;\n if (until < sampleEnd) {\n break;\n }\n // We may need to pad out empty space with an vtte box\n if (trackData.lastCueEndTimestamp < sampleStart) {\n this.auxWriter.seek(0);\n const box = vtte();\n this.auxBoxWriter.writeBox(box);\n const body = this.auxWriter.getSlice(0, this.auxWriter.getPos());\n const sample = this.createSampleForTrack(trackData, body, trackData.lastCueEndTimestamp, sampleStart - trackData.lastCueEndTimestamp, 'key');\n await this.registerSample(trackData, sample);\n trackData.lastCueEndTimestamp = sampleStart;\n }\n this.auxWriter.seek(0);\n for (let i = 0; i < trackData.cueQueue.length; i++) {\n const cue = trackData.cueQueue[i];\n if (cue.timestamp >= sampleEnd) {\n break;\n }\n inlineTimestampRegex.lastIndex = 0;\n const containsTimestamp = inlineTimestampRegex.test(cue.text);\n const endTimestamp = cue.timestamp + cue.duration;\n let sourceId = trackData.cueToSourceId.get(cue);\n if (sourceId === undefined && sampleEnd < endTimestamp) {\n // We know this cue will appear in more than one sample, therefore we need to mark it with a\n // unique ID\n sourceId = trackData.nextSourceId++;\n trackData.cueToSourceId.set(cue, sourceId);\n }\n if (cue.notes) {\n // Any notes/comments are included in a special vtta box\n const box = vtta(cue.notes);\n this.auxBoxWriter.writeBox(box);\n }\n const box = vttc(cue.text, containsTimestamp ? sampleStart : null, cue.identifier ?? null, cue.settings ?? null, sourceId ?? null);\n this.auxBoxWriter.writeBox(box);\n if (endTimestamp === sampleEnd) {\n // The cue won't appear in any future sample, so we're done with it\n trackData.cueQueue.splice(i--, 1);\n }\n }\n const body = this.auxWriter.getSlice(0, this.auxWriter.getPos());\n const sample = this.createSampleForTrack(trackData, body, sampleStart, sampleEnd - sampleStart, 'key');\n await this.registerSample(trackData, sample);\n trackData.lastCueEndTimestamp = sampleEnd;\n }\n }\n createSampleForTrack(trackData, data, timestamp, duration, type) {\n const sample = {\n timestamp,\n decodeTimestamp: timestamp, // This may be refined later\n duration,\n data,\n size: data.byteLength,\n type,\n timescaleUnitsToNextSample: intoTimescale(duration, trackData.timescale), // Will be refined\n };\n return sample;\n }\n processTimestamps(trackData, nextSample) {\n if (trackData.timestampProcessingQueue.length === 0) {\n return;\n }\n if (trackData.type === 'audio' && trackData.info.requiresPcmTransformation) {\n let totalDuration = 0;\n // Compute the total duration in the track timescale (which is equal to the amount of PCM audio samples)\n // and simply say that's how many new samples there are.\n for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {\n const sample = trackData.timestampProcessingQueue[i];\n const duration = intoTimescale(sample.duration, trackData.timescale);\n totalDuration += duration;\n }\n if (trackData.timeToSampleTable.length === 0) {\n trackData.timeToSampleTable.push({\n sampleCount: totalDuration,\n sampleDelta: 1,\n });\n }\n else {\n const lastEntry = last(trackData.timeToSampleTable);\n lastEntry.sampleCount += totalDuration;\n }\n trackData.timestampProcessingQueue.length = 0;\n return;\n }\n const sortedTimestamps = trackData.timestampProcessingQueue.map(x => x.timestamp).sort((a, b) => a - b);\n for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {\n const sample = trackData.timestampProcessingQueue[i];\n // Since the user only supplies presentation time, but these may be out of order, we reverse-engineer from\n // that a sensible decode timestamp. The notion of a decode timestamp doesn't really make sense\n // (presentation timestamp & decode order are all you need), but it is a concept in ISOBMFF so we need to\n // model it.\n sample.decodeTimestamp = sortedTimestamps[i];\n if (!this.isFragmented && trackData.lastTimescaleUnits === null) {\n // In non-fragmented files, the first decode timestamp is always zero. If the first presentation\n // timestamp isn't zero, we'll simply use the composition time offset to achieve it.\n sample.decodeTimestamp = 0;\n }\n const sampleCompositionTimeOffset = intoTimescale(sample.timestamp - sample.decodeTimestamp, trackData.timescale);\n const durationInTimescale = intoTimescale(sample.duration, trackData.timescale);\n if (trackData.lastTimescaleUnits !== null) {\n assert(trackData.lastSample);\n const timescaleUnits = intoTimescale(sample.decodeTimestamp, trackData.timescale, false);\n const delta = Math.round(timescaleUnits - trackData.lastTimescaleUnits);\n assert(delta >= 0);\n trackData.lastTimescaleUnits += delta;\n trackData.lastSample.timescaleUnitsToNextSample = delta;\n if (!this.isFragmented) {\n let lastTableEntry = last(trackData.timeToSampleTable);\n assert(lastTableEntry);\n if (lastTableEntry.sampleCount === 1) {\n lastTableEntry.sampleDelta = delta;\n const entryBefore = trackData.timeToSampleTable[trackData.timeToSampleTable.length - 2];\n if (entryBefore && entryBefore.sampleDelta === delta) {\n // If the delta is the same as the previous one, merge the two entries\n entryBefore.sampleCount++;\n trackData.timeToSampleTable.pop();\n lastTableEntry = entryBefore;\n }\n }\n else if (lastTableEntry.sampleDelta !== delta) {\n // The delta has changed, so we need a new entry to reach the current sample\n lastTableEntry.sampleCount--;\n trackData.timeToSampleTable.push(lastTableEntry = {\n sampleCount: 1,\n sampleDelta: delta,\n });\n }\n if (lastTableEntry.sampleDelta === durationInTimescale) {\n // The sample's duration matches the delta, so we can increment the count\n lastTableEntry.sampleCount++;\n }\n else {\n // Add a new entry in order to maintain the last sample's true duration\n trackData.timeToSampleTable.push({\n sampleCount: 1,\n sampleDelta: durationInTimescale,\n });\n }\n const lastCompositionTimeOffsetTableEntry = last(trackData.compositionTimeOffsetTable);\n assert(lastCompositionTimeOffsetTableEntry);\n if (lastCompositionTimeOffsetTableEntry.sampleCompositionTimeOffset === sampleCompositionTimeOffset) {\n // Simply increment the count\n lastCompositionTimeOffsetTableEntry.sampleCount++;\n }\n else {\n // The composition time offset has changed, so create a new entry with the new composition time\n // offset\n trackData.compositionTimeOffsetTable.push({\n sampleCount: 1,\n sampleCompositionTimeOffset: sampleCompositionTimeOffset,\n });\n }\n }\n }\n else {\n // Decode timestamp of the first sample\n trackData.lastTimescaleUnits = intoTimescale(sample.decodeTimestamp, trackData.timescale, false);\n if (!this.isFragmented) {\n trackData.timeToSampleTable.push({\n sampleCount: 1,\n sampleDelta: durationInTimescale,\n });\n trackData.compositionTimeOffsetTable.push({\n sampleCount: 1,\n sampleCompositionTimeOffset: sampleCompositionTimeOffset,\n });\n }\n }\n trackData.lastSample = sample;\n }\n trackData.timestampProcessingQueue.length = 0;\n assert(trackData.lastSample);\n assert(trackData.lastTimescaleUnits !== null);\n if (nextSample !== undefined && trackData.lastSample.timescaleUnitsToNextSample === 0) {\n assert(nextSample.type === 'key');\n // Given the next sample, we can make a guess about the duration of the last sample. This avoids having\n // the last sample's duration in each fragment be \"0\" for fragmented files. The guess we make here is\n // actually correct most of the time, since typically, no delta frame with a lower timestamp follows the key\n // frame (although it can happen).\n const timescaleUnits = intoTimescale(nextSample.timestamp, trackData.timescale, false);\n const delta = Math.round(timescaleUnits - trackData.lastTimescaleUnits);\n trackData.lastSample.timescaleUnitsToNextSample = delta;\n }\n }\n async registerSample(trackData, sample) {\n if (sample.type === 'key') {\n this.processTimestamps(trackData, sample);\n }\n trackData.timestampProcessingQueue.push(sample);\n if (this.isFragmented) {\n trackData.sampleQueue.push(sample);\n await this.interleaveSamples();\n }\n else if (this.fastStart === 'reserve') {\n await this.registerSampleFastStartReserve(trackData, sample);\n }\n else {\n await this.addSampleToTrack(trackData, sample);\n }\n }\n async addSampleToTrack(trackData, sample) {\n if (!this.isFragmented) {\n trackData.samples.push(sample);\n if (this.fastStart === 'reserve') {\n const maximumPacketCount = trackData.track.metadata.maximumPacketCount;\n assert(maximumPacketCount !== undefined);\n if (trackData.samples.length > maximumPacketCount) {\n throw new Error(`Track #${trackData.track.id} has already reached the maximum packet count`\n + ` (${maximumPacketCount}). Either add less packets or increase the maximum packet count.`);\n }\n }\n }\n let beginNewChunk = false;\n if (!trackData.currentChunk) {\n beginNewChunk = true;\n }\n else {\n // Timestamp don't need to be monotonic (think B-frames), so we may need to update the start timestamp of\n // the chunk\n trackData.currentChunk.startTimestamp = Math.min(trackData.currentChunk.startTimestamp, sample.timestamp);\n const currentChunkDuration = sample.timestamp - trackData.currentChunk.startTimestamp;\n if (this.isFragmented) {\n // We can only finalize this fragment (and begin a new one) if we know that each track will be able to\n // start the new one with a key frame.\n const keyFrameQueuedEverywhere = this.trackDatas.every((otherTrackData) => {\n if (trackData === otherTrackData) {\n return sample.type === 'key';\n }\n const firstQueuedSample = otherTrackData.sampleQueue[0];\n if (firstQueuedSample) {\n return firstQueuedSample.type === 'key';\n }\n return otherTrackData.track.source._closed;\n });\n if (currentChunkDuration >= this.minimumFragmentDuration\n && keyFrameQueuedEverywhere\n && sample.timestamp > this.maxWrittenTimestamp) {\n beginNewChunk = true;\n await this.finalizeFragment();\n }\n }\n else {\n beginNewChunk = currentChunkDuration >= 0.5; // Chunk is long enough, we need a new one\n }\n }\n if (beginNewChunk) {\n if (trackData.currentChunk) {\n await this.finalizeCurrentChunk(trackData);\n }\n trackData.currentChunk = {\n startTimestamp: sample.timestamp,\n samples: [],\n offset: null,\n moofOffset: null,\n };\n }\n assert(trackData.currentChunk);\n trackData.currentChunk.samples.push(sample);\n if (this.isFragmented) {\n this.maxWrittenTimestamp = Math.max(this.maxWrittenTimestamp, sample.timestamp);\n }\n }\n async finalizeCurrentChunk(trackData) {\n assert(!this.isFragmented);\n if (!trackData.currentChunk)\n return;\n trackData.finalizedChunks.push(trackData.currentChunk);\n this.finalizedChunks.push(trackData.currentChunk);\n let sampleCount = trackData.currentChunk.samples.length;\n if (trackData.type === 'audio' && trackData.info.requiresPcmTransformation) {\n sampleCount = trackData.currentChunk.samples\n .reduce((acc, sample) => acc + intoTimescale(sample.duration, trackData.timescale), 0);\n }\n if (trackData.compactlyCodedChunkTable.length === 0\n || last(trackData.compactlyCodedChunkTable).samplesPerChunk !== sampleCount) {\n trackData.compactlyCodedChunkTable.push({\n firstChunk: trackData.finalizedChunks.length, // 1-indexed\n samplesPerChunk: sampleCount,\n });\n }\n if (this.fastStart === 'in-memory') {\n trackData.currentChunk.offset = 0; // We'll compute the proper offset when finalizing\n return;\n }\n // Write out the data\n trackData.currentChunk.offset = this.writer.getPos();\n for (const sample of trackData.currentChunk.samples) {\n assert(sample.data);\n this.writer.write(sample.data);\n sample.data = null; // Can be GC'd\n }\n await this.writer.flush();\n }\n async interleaveSamples(isFinalCall = false) {\n assert(this.isFragmented);\n if (!isFinalCall && !this.allTracksAreKnown()) {\n return; // We can't interleave yet as we don't yet know how many tracks we'll truly have\n }\n outer: while (true) {\n let trackWithMinTimestamp = null;\n let minTimestamp = Infinity;\n for (const trackData of this.trackDatas) {\n if (!isFinalCall && trackData.sampleQueue.length === 0 && !trackData.track.source._closed) {\n break outer;\n }\n if (trackData.sampleQueue.length > 0 && trackData.sampleQueue[0].timestamp < minTimestamp) {\n trackWithMinTimestamp = trackData;\n minTimestamp = trackData.sampleQueue[0].timestamp;\n }\n }\n if (!trackWithMinTimestamp) {\n break;\n }\n const sample = trackWithMinTimestamp.sampleQueue.shift();\n await this.addSampleToTrack(trackWithMinTimestamp, sample);\n }\n }\n async finalizeFragment(flushWriter = true) {\n assert(this.isFragmented);\n const fragmentNumber = this.nextFragmentNumber++;\n if (fragmentNumber === 1) {\n if (this.format._options.onMoov) {\n this.writer.startTrackingWrites();\n }\n // Write the moov box now that we have all decoder configs\n const movieBox = moov(this);\n this.boxWriter.writeBox(movieBox);\n if (this.format._options.onMoov) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onMoov(data, start);\n }\n }\n // Not all tracks need to be present in every fragment\n const tracksInFragment = this.trackDatas.filter(x => x.currentChunk);\n // Create an initial moof box and measure it; we need this to know where the following mdat box will begin\n const moofBox = moof(fragmentNumber, tracksInFragment);\n const moofOffset = this.writer.getPos();\n const mdatStartPos = moofOffset + this.boxWriter.measureBox(moofBox);\n let currentPos = mdatStartPos + MIN_BOX_HEADER_SIZE;\n let fragmentStartTimestamp = Infinity;\n for (const trackData of tracksInFragment) {\n trackData.currentChunk.offset = currentPos;\n trackData.currentChunk.moofOffset = moofOffset;\n for (const sample of trackData.currentChunk.samples) {\n currentPos += sample.size;\n }\n fragmentStartTimestamp = Math.min(fragmentStartTimestamp, trackData.currentChunk.startTimestamp);\n }\n const mdatSize = currentPos - mdatStartPos;\n const needsLargeMdatSize = mdatSize >= 2 ** 32;\n if (needsLargeMdatSize) {\n // Shift all offsets by 8. Previously, all chunks were shifted assuming the large box size, but due to what\n // I suspect is a bug in WebKit, it failed in Safari (when livestreaming with MSE, not for static playback).\n for (const trackData of tracksInFragment) {\n trackData.currentChunk.offset += MAX_BOX_HEADER_SIZE - MIN_BOX_HEADER_SIZE;\n }\n }\n if (this.format._options.onMoof) {\n this.writer.startTrackingWrites();\n }\n const newMoofBox = moof(fragmentNumber, tracksInFragment);\n this.boxWriter.writeBox(newMoofBox);\n if (this.format._options.onMoof) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onMoof(data, start, fragmentStartTimestamp);\n }\n assert(this.writer.getPos() === mdatStartPos);\n if (this.format._options.onMdat) {\n this.writer.startTrackingWrites();\n }\n const mdatBox = mdat(needsLargeMdatSize);\n mdatBox.size = mdatSize;\n this.boxWriter.writeBox(mdatBox);\n this.writer.seek(mdatStartPos + (needsLargeMdatSize ? MAX_BOX_HEADER_SIZE : MIN_BOX_HEADER_SIZE));\n // Write sample data\n for (const trackData of tracksInFragment) {\n for (const sample of trackData.currentChunk.samples) {\n this.writer.write(sample.data);\n sample.data = null; // Can be GC'd\n }\n }\n if (this.format._options.onMdat) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onMdat(data, start);\n }\n for (const trackData of tracksInFragment) {\n trackData.finalizedChunks.push(trackData.currentChunk);\n this.finalizedChunks.push(trackData.currentChunk);\n trackData.currentChunk = null;\n }\n if (flushWriter) {\n await this.writer.flush();\n }\n }\n async registerSampleFastStartReserve(trackData, sample) {\n if (this.allTracksAreKnown()) {\n if (!this.mdat) {\n // We finally know all tracks, let's reserve space for the moov box\n const moovBox = moov(this);\n const moovSize = this.boxWriter.measureBox(moovBox);\n const reservedSize = moovSize\n + this.computeSampleTableSizeUpperBound()\n + 4096; // Just a little extra headroom\n assert(this.ftypSize !== null);\n this.writer.seek(this.ftypSize + reservedSize);\n if (this.format._options.onMdat) {\n this.writer.startTrackingWrites();\n }\n this.mdat = mdat(true);\n this.boxWriter.writeBox(this.mdat);\n // Now write everything that was queued\n for (const trackData of this.trackDatas) {\n for (const sample of trackData.sampleQueue) {\n await this.addSampleToTrack(trackData, sample);\n }\n trackData.sampleQueue.length = 0;\n }\n }\n await this.addSampleToTrack(trackData, sample);\n }\n else {\n // Queue it for when we know all tracks\n trackData.sampleQueue.push(sample);\n }\n }\n computeSampleTableSizeUpperBound() {\n assert(this.fastStart === 'reserve');\n let upperBound = 0;\n for (const trackData of this.trackDatas) {\n const n = trackData.track.metadata.maximumPacketCount;\n assert(n !== undefined); // We validated this earlier\n // Given the max allowed packet count, compute the space they'll take up in the Sample Table Box, assuming\n // the worst case for each individual box:\n // stts box - since it is compactly coded, the maximum length of this table will be 2/3n\n upperBound += (4 + 4) * Math.ceil(2 / 3 * n);\n // stss box - 1 entry per sample\n upperBound += 4 * n;\n // ctts box - since it is compactly coded, the maximum length of this table will be 2/3n\n upperBound += (4 + 4) * Math.ceil(2 / 3 * n);\n // stsc box - since it is compactly coded, the maximum length of this table will be 2/3n\n upperBound += (4 + 4 + 4) * Math.ceil(2 / 3 * n);\n // stsz box - 1 entry per sample\n upperBound += 4 * n;\n // co64 box - we assume 1 sample per chunk and 64-bit chunk offsets (co64 instead of stco)\n upperBound += 8 * n;\n }\n return upperBound;\n }\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async onTrackClose(track) {\n const release = await this.mutex.acquire();\n if (track.type === 'subtitle' && track.source._codec === 'webvtt') {\n const trackData = this.trackDatas.find(x => x.track === track);\n if (trackData) {\n await this.processWebVTTCues(trackData, Infinity);\n }\n }\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n if (this.isFragmented) {\n // Since a track is now closed, we may be able to write out chunks that were previously waiting\n await this.interleaveSamples();\n }\n release();\n }\n /** Finalizes the file, making it ready for use. Must be called after all video and audio chunks have been added. */\n async finalize() {\n const release = await this.mutex.acquire();\n this.allTracksKnown.resolve();\n for (const trackData of this.trackDatas) {\n if (trackData.type === 'subtitle' && trackData.track.source._codec === 'webvtt') {\n await this.processWebVTTCues(trackData, Infinity);\n }\n }\n if (this.isFragmented) {\n await this.interleaveSamples(true);\n for (const trackData of this.trackDatas) {\n this.processTimestamps(trackData);\n }\n await this.finalizeFragment(false); // Don't flush the last fragment as we will flush it with the mfra box\n }\n else {\n for (const trackData of this.trackDatas) {\n this.processTimestamps(trackData);\n await this.finalizeCurrentChunk(trackData);\n }\n }\n if (this.fastStart === 'in-memory') {\n this.mdat = mdat(false);\n let mdatSize;\n // We know how many chunks there are, but computing the chunk positions requires an iterative approach:\n // In order to know where the first chunk should go, we first need to know the size of the moov box. But we\n // cannot write a proper moov box without first knowing all chunk positions. So, we generate a tentative\n // moov box with placeholder values (0) for the chunk offsets to be able to compute its size. If it then\n // turns out that appending all chunks exceeds 4 GiB, we need to repeat this process, now with the co64 box\n // being used in the moov box instead, which will make it larger. After that, we definitely know the final\n // size of the moov box and can compute the proper chunk positions.\n for (let i = 0; i < 2; i++) {\n const movieBox = moov(this);\n const movieBoxSize = this.boxWriter.measureBox(movieBox);\n mdatSize = this.boxWriter.measureBox(this.mdat);\n let currentChunkPos = this.writer.getPos() + movieBoxSize + mdatSize;\n for (const chunk of this.finalizedChunks) {\n chunk.offset = currentChunkPos;\n for (const { data } of chunk.samples) {\n assert(data);\n currentChunkPos += data.byteLength;\n mdatSize += data.byteLength;\n }\n }\n if (currentChunkPos < 2 ** 32)\n break;\n if (mdatSize >= 2 ** 32)\n this.mdat.largeSize = true;\n }\n if (this.format._options.onMoov) {\n this.writer.startTrackingWrites();\n }\n const movieBox = moov(this);\n this.boxWriter.writeBox(movieBox);\n if (this.format._options.onMoov) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onMoov(data, start);\n }\n if (this.format._options.onMdat) {\n this.writer.startTrackingWrites();\n }\n this.mdat.size = mdatSize;\n this.boxWriter.writeBox(this.mdat);\n for (const chunk of this.finalizedChunks) {\n for (const sample of chunk.samples) {\n assert(sample.data);\n this.writer.write(sample.data);\n sample.data = null;\n }\n }\n if (this.format._options.onMdat) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onMdat(data, start);\n }\n }\n else if (this.isFragmented) {\n // Append the mfra box to the end of the file for better random access\n const startPos = this.writer.getPos();\n const mfraBox = mfra(this.trackDatas);\n this.boxWriter.writeBox(mfraBox);\n // Patch the 'size' field of the mfro box at the end of the mfra box now that we know its actual size\n const mfraBoxSize = this.writer.getPos() - startPos;\n this.writer.seek(this.writer.getPos() - 4);\n this.boxWriter.writeU32(mfraBoxSize);\n }\n else {\n assert(this.mdat);\n const mdatPos = this.boxWriter.offsets.get(this.mdat);\n assert(mdatPos !== undefined);\n const mdatSize = this.writer.getPos() - mdatPos;\n this.mdat.size = mdatSize;\n this.mdat.largeSize = mdatSize >= 2 ** 32; // Only use the large size if we need it\n this.boxWriter.patchBox(this.mdat);\n if (this.format._options.onMdat) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onMdat(data, start);\n }\n const movieBox = moov(this);\n if (this.fastStart === 'reserve') {\n assert(this.ftypSize !== null);\n this.writer.seek(this.ftypSize);\n if (this.format._options.onMoov) {\n this.writer.startTrackingWrites();\n }\n this.boxWriter.writeBox(movieBox);\n // Fill the remaining space with a free box. If there are less than 8 bytes left, sucks I guess\n const remainingSpace = this.boxWriter.offsets.get(this.mdat) - this.writer.getPos();\n this.boxWriter.writeBox(free(remainingSpace));\n }\n else {\n if (this.format._options.onMoov) {\n this.writer.startTrackingWrites();\n }\n this.boxWriter.writeBox(movieBox);\n }\n if (this.format._options.onMoov) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onMoov(data, start);\n }\n }\n release();\n }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nexport const buildIsobmffMimeType = (info) => {\n const base = info.hasVideo\n ? 'video/'\n : info.hasAudio\n ? 'audio/'\n : 'application/';\n let string = base + (info.isQuickTime ? 'quicktime' : 'mp4');\n if (info.codecStrings.length > 0) {\n const uniqueCodecMimeTypes = [...new Set(info.codecStrings)];\n string += `; codecs=\"${uniqueCodecMimeTypes.join(', ')}\"`;\n }\n return string;\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { RichImageData } from '../metadata.js';\nimport { textDecoder } from '../misc.js';\nimport { readAscii, readBytes, readI32Be, readU16Be, readU32Be, readU64Be, readU8 } from '../reader.js';\nexport const MIN_BOX_HEADER_SIZE = 8;\nexport const MAX_BOX_HEADER_SIZE = 16;\nexport const readBoxHeader = (slice) => {\n let totalSize = readU32Be(slice);\n const name = readAscii(slice, 4);\n let headerSize = 8;\n const hasLargeSize = totalSize === 1;\n if (hasLargeSize) {\n totalSize = readU64Be(slice);\n headerSize = 16;\n }\n const contentSize = totalSize - headerSize;\n if (contentSize < 0) {\n return null; // Hardly a box is it\n }\n return { name, totalSize, headerSize, contentSize };\n};\nexport const readFixed_16_16 = (slice) => {\n return readI32Be(slice) / 0x10000;\n};\nexport const readFixed_2_30 = (slice) => {\n return readI32Be(slice) / 0x40000000;\n};\nexport const readIsomVariableInteger = (slice) => {\n let result = 0;\n for (let i = 0; i < 4; i++) {\n result <<= 7;\n const nextByte = readU8(slice);\n result |= nextByte & 0x7f;\n if ((nextByte & 0x80) === 0) {\n break;\n }\n }\n return result;\n};\nexport const readMetadataStringShort = (slice) => {\n let stringLength = readU16Be(slice);\n slice.skip(2); // Language\n stringLength = Math.min(stringLength, slice.remainingLength);\n return textDecoder.decode(readBytes(slice, stringLength));\n};\nexport const readDataBox = (slice) => {\n const header = readBoxHeader(slice);\n if (!header || header.name !== 'data') {\n return null;\n }\n if (slice.remainingLength < 8) {\n // Box is too small\n return null;\n }\n const typeIndicator = readU32Be(slice);\n slice.skip(4); // Locale indicator\n const data = readBytes(slice, header.contentSize - 8);\n switch (typeIndicator) {\n case 1: return textDecoder.decode(data); // UTF-8\n case 2: return new TextDecoder('utf-16be').decode(data); // UTF-16-BE\n case 13: return new RichImageData(data, 'image/jpeg');\n case 14: return new RichImageData(data, 'image/png');\n case 27: return new RichImageData(data, 'image/bmp');\n default: return data;\n }\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { Bitstream, COLOR_PRIMARIES_MAP, MATRIX_COEFFICIENTS_MAP, TRANSFER_CHARACTERISTICS_MAP, UNDETERMINED_LANGUAGE, assert, assertNever, colorSpaceIsComplete, imageMimeTypeToExtension, keyValueIterator, normalizeRotation, promiseWithResolvers, roundToMultiple, textEncoder, toUint8Array, uint8ArraysAreEqual, writeBits, } from '../misc.js';\nimport { CODEC_STRING_MAP, EBMLFloat32, EBMLFloat64, EBMLId, EBMLSignedInt, EBMLUnicodeString, EBMLWriter, } from './ebml.js';\nimport { buildMatroskaMimeType } from './matroska-misc.js';\nimport { WebMOutputFormat } from '../output-format.js';\nimport { formatSubtitleTimestamp, inlineTimestampRegex, parseSubtitleTimestamp, } from '../subtitles.js';\nimport { OPUS_SAMPLE_RATE, PCM_AUDIO_CODECS, generateAv1CodecConfigurationFromCodecString, generateVp9CodecConfigurationFromCodecString, parsePcmCodec, validateAudioChunkMetadata, validateSubtitleMetadata, validateVideoChunkMetadata, } from '../codec.js';\nimport { Muxer } from '../muxer.js';\nimport { parseOpusIdentificationHeader } from '../codec-data.js';\nimport { AttachedFile } from '../metadata.js';\nconst MIN_CLUSTER_TIMESTAMP_MS = -(2 ** 15);\nconst MAX_CLUSTER_TIMESTAMP_MS = 2 ** 15 - 1;\nconst APP_NAME = 'Mediabunny';\nconst SEGMENT_SIZE_BYTES = 6;\nconst CLUSTER_SIZE_BYTES = 5;\nconst TRACK_TYPE_MAP = {\n video: 1,\n audio: 2,\n subtitle: 17,\n};\nexport class MatroskaMuxer extends Muxer {\n constructor(output, format) {\n super(output);\n this.trackDatas = [];\n this.allTracksKnown = promiseWithResolvers();\n this.segment = null;\n this.segmentInfo = null;\n this.seekHead = null;\n this.tracksElement = null;\n this.tagsElement = null;\n this.attachmentsElement = null;\n this.segmentDuration = null;\n this.cues = null;\n this.currentCluster = null;\n this.currentClusterStartMsTimestamp = null;\n this.currentClusterMaxMsTimestamp = null;\n this.trackDatasInCurrentCluster = new Map();\n this.duration = 0;\n this.writer = output._writer;\n this.format = format;\n this.ebmlWriter = new EBMLWriter(this.writer);\n if (this.format._options.appendOnly) {\n this.writer.ensureMonotonicity = true;\n }\n }\n async start() {\n const release = await this.mutex.acquire();\n this.writeEBMLHeader();\n this.createSegmentInfo();\n this.createCues();\n await this.writer.flush();\n release();\n }\n writeEBMLHeader() {\n if (this.format._options.onEbmlHeader) {\n this.writer.startTrackingWrites();\n }\n const ebmlHeader = { id: EBMLId.EBML, data: [\n { id: EBMLId.EBMLVersion, data: 1 },\n { id: EBMLId.EBMLReadVersion, data: 1 },\n { id: EBMLId.EBMLMaxIDLength, data: 4 },\n { id: EBMLId.EBMLMaxSizeLength, data: 8 },\n { id: EBMLId.DocType, data: this.format instanceof WebMOutputFormat ? 'webm' : 'matroska' },\n { id: EBMLId.DocTypeVersion, data: 2 },\n { id: EBMLId.DocTypeReadVersion, data: 2 },\n ] };\n this.ebmlWriter.writeEBML(ebmlHeader);\n if (this.format._options.onEbmlHeader) {\n const { data, start } = this.writer.stopTrackingWrites(); // start should be 0\n this.format._options.onEbmlHeader(data, start);\n }\n }\n /**\n * Creates a SeekHead element which is positioned near the start of the file and allows the media player to seek to\n * relevant sections more easily. Since we don't know the positions of those sections yet, we'll set them later.\n */\n maybeCreateSeekHead(writeOffsets) {\n if (this.format._options.appendOnly) {\n return;\n }\n const kaxCues = new Uint8Array([0x1c, 0x53, 0xbb, 0x6b]);\n const kaxInfo = new Uint8Array([0x15, 0x49, 0xa9, 0x66]);\n const kaxTracks = new Uint8Array([0x16, 0x54, 0xae, 0x6b]);\n const kaxAttachments = new Uint8Array([0x19, 0x41, 0xa4, 0x69]);\n const kaxTags = new Uint8Array([0x12, 0x54, 0xc3, 0x67]);\n const seekHead = { id: EBMLId.SeekHead, data: [\n { id: EBMLId.Seek, data: [\n { id: EBMLId.SeekID, data: kaxCues },\n {\n id: EBMLId.SeekPosition,\n size: 5,\n data: writeOffsets\n ? this.ebmlWriter.offsets.get(this.cues) - this.segmentDataOffset\n : 0,\n },\n ] },\n { id: EBMLId.Seek, data: [\n { id: EBMLId.SeekID, data: kaxInfo },\n {\n id: EBMLId.SeekPosition,\n size: 5,\n data: writeOffsets\n ? this.ebmlWriter.offsets.get(this.segmentInfo) - this.segmentDataOffset\n : 0,\n },\n ] },\n { id: EBMLId.Seek, data: [\n { id: EBMLId.SeekID, data: kaxTracks },\n {\n id: EBMLId.SeekPosition,\n size: 5,\n data: writeOffsets\n ? this.ebmlWriter.offsets.get(this.tracksElement) - this.segmentDataOffset\n : 0,\n },\n ] },\n this.attachmentsElement\n ? { id: EBMLId.Seek, data: [\n { id: EBMLId.SeekID, data: kaxAttachments },\n {\n id: EBMLId.SeekPosition,\n size: 5,\n data: writeOffsets\n ? this.ebmlWriter.offsets.get(this.attachmentsElement) - this.segmentDataOffset\n : 0,\n },\n ] }\n : null,\n this.tagsElement\n ? { id: EBMLId.Seek, data: [\n { id: EBMLId.SeekID, data: kaxTags },\n {\n id: EBMLId.SeekPosition,\n size: 5,\n data: writeOffsets\n ? this.ebmlWriter.offsets.get(this.tagsElement) - this.segmentDataOffset\n : 0,\n },\n ] }\n : null,\n ] };\n this.seekHead = seekHead;\n }\n createSegmentInfo() {\n const segmentDuration = { id: EBMLId.Duration, data: new EBMLFloat64(0) };\n this.segmentDuration = segmentDuration;\n const segmentInfo = { id: EBMLId.Info, data: [\n { id: EBMLId.TimestampScale, data: 1e6 },\n { id: EBMLId.MuxingApp, data: APP_NAME },\n { id: EBMLId.WritingApp, data: APP_NAME },\n !this.format._options.appendOnly ? segmentDuration : null,\n ] };\n this.segmentInfo = segmentInfo;\n }\n createTracks() {\n const tracksElement = { id: EBMLId.Tracks, data: [] };\n this.tracksElement = tracksElement;\n for (const trackData of this.trackDatas) {\n const codecId = CODEC_STRING_MAP[trackData.track.source._codec];\n assert(codecId);\n let seekPreRollNs = 0;\n if (trackData.type === 'audio' && trackData.track.source._codec === 'opus') {\n seekPreRollNs = 1e6 * 80; // In \"Matroska ticks\" (nanoseconds)\n const description = trackData.info.decoderConfig.description;\n if (description) {\n const bytes = toUint8Array(description);\n const header = parseOpusIdentificationHeader(bytes);\n // Use the preSkip value from the header\n seekPreRollNs = Math.round(1e9 * (header.preSkip / OPUS_SAMPLE_RATE));\n }\n }\n tracksElement.data.push({ id: EBMLId.TrackEntry, data: [\n { id: EBMLId.TrackNumber, data: trackData.track.id },\n { id: EBMLId.TrackUID, data: trackData.track.id },\n { id: EBMLId.TrackType, data: TRACK_TYPE_MAP[trackData.type] },\n trackData.track.metadata.disposition?.default === false\n ? { id: EBMLId.FlagDefault, data: 0 }\n : null,\n trackData.track.metadata.disposition?.forced\n ? { id: EBMLId.FlagForced, data: 1 }\n : null,\n trackData.track.metadata.disposition?.hearingImpaired\n ? { id: EBMLId.FlagHearingImpaired, data: 1 }\n : null,\n trackData.track.metadata.disposition?.visuallyImpaired\n ? { id: EBMLId.FlagVisualImpaired, data: 1 }\n : null,\n trackData.track.metadata.disposition?.original\n ? { id: EBMLId.FlagOriginal, data: 1 }\n : null,\n trackData.track.metadata.disposition?.commentary\n ? { id: EBMLId.FlagCommentary, data: 1 }\n : null,\n { id: EBMLId.FlagLacing, data: 0 },\n { id: EBMLId.Language, data: trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE },\n { id: EBMLId.CodecID, data: codecId },\n { id: EBMLId.CodecDelay, data: 0 },\n { id: EBMLId.SeekPreRoll, data: seekPreRollNs },\n trackData.track.metadata.name !== undefined\n ? { id: EBMLId.Name, data: new EBMLUnicodeString(trackData.track.metadata.name) }\n : null,\n (trackData.type === 'video' ? this.videoSpecificTrackInfo(trackData) : null),\n (trackData.type === 'audio' ? this.audioSpecificTrackInfo(trackData) : null),\n (trackData.type === 'subtitle' ? this.subtitleSpecificTrackInfo(trackData) : null),\n ] });\n }\n }\n videoSpecificTrackInfo(trackData) {\n const { frameRate, rotation } = trackData.track.metadata;\n const elements = [\n (trackData.info.decoderConfig.description\n ? {\n id: EBMLId.CodecPrivate,\n data: toUint8Array(trackData.info.decoderConfig.description),\n }\n : null),\n (frameRate\n ? {\n id: EBMLId.DefaultDuration,\n data: 1e9 / frameRate,\n }\n : null),\n ];\n // Convert from clockwise to counter-clockwise\n const flippedRotation = rotation ? normalizeRotation(-rotation) : 0;\n const colorSpace = trackData.info.decoderConfig.colorSpace;\n const videoElement = { id: EBMLId.Video, data: [\n { id: EBMLId.PixelWidth, data: trackData.info.width },\n { id: EBMLId.PixelHeight, data: trackData.info.height },\n trackData.info.alphaMode ? { id: EBMLId.AlphaMode, data: 1 } : null,\n (colorSpaceIsComplete(colorSpace)\n ? {\n id: EBMLId.Colour,\n data: [\n {\n id: EBMLId.MatrixCoefficients,\n data: MATRIX_COEFFICIENTS_MAP[colorSpace.matrix],\n },\n {\n id: EBMLId.TransferCharacteristics,\n data: TRANSFER_CHARACTERISTICS_MAP[colorSpace.transfer],\n },\n {\n id: EBMLId.Primaries,\n data: COLOR_PRIMARIES_MAP[colorSpace.primaries],\n },\n {\n id: EBMLId.Range,\n data: colorSpace.fullRange ? 2 : 1,\n },\n ],\n }\n : null),\n (flippedRotation\n ? {\n id: EBMLId.Projection,\n data: [\n {\n id: EBMLId.ProjectionType,\n data: 0, // rectangular\n },\n {\n id: EBMLId.ProjectionPoseRoll,\n data: new EBMLFloat32((flippedRotation + 180) % 360 - 180), // [0, 270] -> [-180, 90]\n },\n ],\n }\n : null),\n ] };\n elements.push(videoElement);\n return elements;\n }\n audioSpecificTrackInfo(trackData) {\n const pcmInfo = PCM_AUDIO_CODECS.includes(trackData.track.source._codec)\n ? parsePcmCodec(trackData.track.source._codec)\n : null;\n return [\n (trackData.info.decoderConfig.description\n ? {\n id: EBMLId.CodecPrivate,\n data: toUint8Array(trackData.info.decoderConfig.description),\n }\n : null),\n { id: EBMLId.Audio, data: [\n { id: EBMLId.SamplingFrequency, data: new EBMLFloat32(trackData.info.sampleRate) },\n { id: EBMLId.Channels, data: trackData.info.numberOfChannels },\n pcmInfo ? { id: EBMLId.BitDepth, data: 8 * pcmInfo.sampleSize } : null,\n ] },\n ];\n }\n subtitleSpecificTrackInfo(trackData) {\n return [\n { id: EBMLId.CodecPrivate, data: textEncoder.encode(trackData.info.config.description) },\n ];\n }\n maybeCreateTags() {\n const simpleTags = [];\n const addSimpleTag = (key, value) => {\n simpleTags.push({ id: EBMLId.SimpleTag, data: [\n { id: EBMLId.TagName, data: new EBMLUnicodeString(key) },\n typeof value === 'string'\n ? { id: EBMLId.TagString, data: new EBMLUnicodeString(value) }\n : { id: EBMLId.TagBinary, data: value },\n ] });\n };\n const metadataTags = this.output._metadataTags;\n const writtenTags = new Set();\n for (const { key, value } of keyValueIterator(metadataTags)) {\n switch (key) {\n case 'title':\n {\n addSimpleTag('TITLE', value);\n writtenTags.add('TITLE');\n }\n ;\n break;\n case 'description':\n {\n addSimpleTag('DESCRIPTION', value);\n writtenTags.add('DESCRIPTION');\n }\n ;\n break;\n case 'artist':\n {\n addSimpleTag('ARTIST', value);\n writtenTags.add('ARTIST');\n }\n ;\n break;\n case 'album':\n {\n addSimpleTag('ALBUM', value);\n writtenTags.add('ALBUM');\n }\n ;\n break;\n case 'albumArtist':\n {\n addSimpleTag('ALBUM_ARTIST', value);\n writtenTags.add('ALBUM_ARTIST');\n }\n ;\n break;\n case 'genre':\n {\n addSimpleTag('GENRE', value);\n writtenTags.add('GENRE');\n }\n ;\n break;\n case 'comment':\n {\n addSimpleTag('COMMENT', value);\n writtenTags.add('COMMENT');\n }\n ;\n break;\n case 'lyrics':\n {\n addSimpleTag('LYRICS', value);\n writtenTags.add('LYRICS');\n }\n ;\n break;\n case 'date':\n {\n addSimpleTag('DATE', value.toISOString().slice(0, 10));\n writtenTags.add('DATE');\n }\n ;\n break;\n case 'trackNumber':\n {\n const string = metadataTags.tracksTotal !== undefined\n ? `${value}/${metadataTags.tracksTotal}`\n : value.toString();\n addSimpleTag('PART_NUMBER', string);\n writtenTags.add('PART_NUMBER');\n }\n ;\n break;\n case 'discNumber':\n {\n const string = metadataTags.discsTotal !== undefined\n ? `${value}/${metadataTags.discsTotal}`\n : value.toString();\n addSimpleTag('DISC', string);\n writtenTags.add('DISC');\n }\n ;\n break;\n case 'tracksTotal':\n case 'discsTotal':\n {\n // Handled with trackNumber and discNumber respectively\n }\n ;\n break;\n case 'images':\n case 'raw':\n {\n // Handled elsewhere\n }\n ;\n break;\n default: assertNever(key);\n }\n }\n if (metadataTags.raw) {\n for (const key in metadataTags.raw) {\n const value = metadataTags.raw[key];\n if (value == null || writtenTags.has(key)) {\n continue;\n }\n if (typeof value === 'string' || value instanceof Uint8Array) {\n addSimpleTag(key, value);\n }\n }\n }\n if (simpleTags.length === 0) {\n return;\n }\n this.tagsElement = {\n id: EBMLId.Tags,\n data: [{ id: EBMLId.Tag, data: [\n { id: EBMLId.Targets, data: [\n { id: EBMLId.TargetTypeValue, data: 50 },\n { id: EBMLId.TargetType, data: 'MOVIE' },\n ] },\n ...simpleTags,\n ] }],\n };\n }\n maybeCreateAttachments() {\n const metadataTags = this.output._metadataTags;\n const elements = [];\n const existingFileUids = new Set();\n const images = metadataTags.images ?? [];\n for (const image of images) {\n let imageName = image.name;\n if (imageName === undefined) {\n const baseName = image.kind === 'coverFront' ? 'cover' : image.kind === 'coverBack' ? 'back' : 'image';\n imageName = baseName + (imageMimeTypeToExtension(image.mimeType) ?? '');\n }\n let fileUid;\n while (true) {\n // Generate a random 64-bit unsigned integer\n fileUid = 0n;\n for (let i = 0; i < 8; i++) {\n fileUid <<= 8n;\n fileUid |= BigInt(Math.floor(Math.random() * 256));\n }\n if (fileUid !== 0n && !existingFileUids.has(fileUid)) {\n break;\n }\n }\n existingFileUids.add(fileUid);\n elements.push({\n id: EBMLId.AttachedFile,\n data: [\n image.description !== undefined\n ? { id: EBMLId.FileDescription, data: new EBMLUnicodeString(image.description) }\n : null,\n { id: EBMLId.FileName, data: new EBMLUnicodeString(imageName) },\n { id: EBMLId.FileMediaType, data: image.mimeType },\n { id: EBMLId.FileData, data: image.data },\n { id: EBMLId.FileUID, data: fileUid },\n ],\n });\n }\n // Add all AttachedFiles from the raw metadata\n for (const [key, value] of Object.entries(metadataTags.raw ?? {})) {\n if (!(value instanceof AttachedFile)) {\n continue;\n }\n const keyIsNumeric = /^\\d+$/.test(key);\n if (!keyIsNumeric) {\n continue;\n }\n if (images.find(x => x.mimeType === value.mimeType && uint8ArraysAreEqual(x.data, value.data))) {\n // This attached file has very likely already been added as an image above\n // (happens when remuxing Matroska)\n continue;\n }\n elements.push({\n id: EBMLId.AttachedFile,\n data: [\n value.description !== undefined\n ? { id: EBMLId.FileDescription, data: new EBMLUnicodeString(value.description) }\n : null,\n { id: EBMLId.FileName, data: new EBMLUnicodeString(value.name ?? '') },\n { id: EBMLId.FileMediaType, data: value.mimeType ?? '' },\n { id: EBMLId.FileData, data: value.data },\n { id: EBMLId.FileUID, data: BigInt(key) },\n ],\n });\n }\n if (elements.length === 0) {\n return;\n }\n this.attachmentsElement = { id: EBMLId.Attachments, data: elements };\n }\n createSegment() {\n this.createTracks();\n this.maybeCreateTags();\n this.maybeCreateAttachments();\n this.maybeCreateSeekHead(false);\n const segment = {\n id: EBMLId.Segment,\n size: this.format._options.appendOnly ? -1 : SEGMENT_SIZE_BYTES,\n data: [\n this.seekHead, // null if append-only\n this.segmentInfo,\n this.tracksElement,\n // Matroska spec says put this at the end of the file, but I think placing it before the first cluster\n // makes more sense, and FFmpeg agrees (argumentum ad ffmpegum fallacy)\n this.attachmentsElement,\n this.tagsElement,\n ],\n };\n this.segment = segment;\n if (this.format._options.onSegmentHeader) {\n this.writer.startTrackingWrites();\n }\n this.ebmlWriter.writeEBML(segment);\n if (this.format._options.onSegmentHeader) {\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onSegmentHeader(data, start);\n }\n }\n createCues() {\n this.cues = { id: EBMLId.Cues, data: [] };\n }\n get segmentDataOffset() {\n assert(this.segment);\n return this.ebmlWriter.dataOffsets.get(this.segment);\n }\n allTracksAreKnown() {\n for (const track of this.output._tracks) {\n if (!track.source._closed && !this.trackDatas.some(x => x.track === track)) {\n return false; // We haven't seen a sample from this open track yet\n }\n }\n return true;\n }\n async getMimeType() {\n await this.allTracksKnown.promise;\n const codecStrings = this.trackDatas.map((trackData) => {\n if (trackData.type === 'video') {\n return trackData.info.decoderConfig.codec;\n }\n else if (trackData.type === 'audio') {\n return trackData.info.decoderConfig.codec;\n }\n else {\n const map = {\n webvtt: 'wvtt',\n };\n return map[trackData.track.source._codec];\n }\n });\n return buildMatroskaMimeType({\n isWebM: this.format instanceof WebMOutputFormat,\n hasVideo: this.trackDatas.some(x => x.type === 'video'),\n hasAudio: this.trackDatas.some(x => x.type === 'audio'),\n codecStrings,\n });\n }\n getVideoTrackData(track, packet, meta) {\n const existingTrackData = this.trackDatas.find(x => x.track === track);\n if (existingTrackData) {\n return existingTrackData;\n }\n validateVideoChunkMetadata(meta);\n assert(meta);\n assert(meta.decoderConfig);\n assert(meta.decoderConfig.codedWidth !== undefined);\n assert(meta.decoderConfig.codedHeight !== undefined);\n const newTrackData = {\n track,\n type: 'video',\n info: {\n width: meta.decoderConfig.codedWidth,\n height: meta.decoderConfig.codedHeight,\n decoderConfig: meta.decoderConfig,\n alphaMode: !!packet.sideData.alpha, // The first packet determines if this track has alpha or not\n },\n chunkQueue: [],\n lastWrittenMsTimestamp: null,\n };\n if (track.source._codec === 'vp9') {\n // https://www.webmproject.org/docs/container specifies that VP9 \"SHOULD\" make use of the CodecPrivate\n // field. Since WebCodecs makes no use of the description field for VP9, we need to derive it ourselves:\n newTrackData.info.decoderConfig = {\n ...newTrackData.info.decoderConfig,\n description: new Uint8Array(generateVp9CodecConfigurationFromCodecString(newTrackData.info.decoderConfig.codec)),\n };\n }\n else if (track.source._codec === 'av1') {\n // Per https://github.com/ietf-wg-cellar/matroska-specification/blob/master/codec/av1.md, AV1 requires\n // CodecPrivate to be set, but WebCodecs makes no use of the description field for AV1. Thus, let's derive\n // it ourselves:\n newTrackData.info.decoderConfig = {\n ...newTrackData.info.decoderConfig,\n description: new Uint8Array(generateAv1CodecConfigurationFromCodecString(newTrackData.info.decoderConfig.codec)),\n };\n }\n this.trackDatas.push(newTrackData);\n this.trackDatas.sort((a, b) => a.track.id - b.track.id);\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n return newTrackData;\n }\n getAudioTrackData(track, meta) {\n const existingTrackData = this.trackDatas.find(x => x.track === track);\n if (existingTrackData) {\n return existingTrackData;\n }\n validateAudioChunkMetadata(meta);\n assert(meta);\n assert(meta.decoderConfig);\n const newTrackData = {\n track,\n type: 'audio',\n info: {\n numberOfChannels: meta.decoderConfig.numberOfChannels,\n sampleRate: meta.decoderConfig.sampleRate,\n decoderConfig: meta.decoderConfig,\n },\n chunkQueue: [],\n lastWrittenMsTimestamp: null,\n };\n this.trackDatas.push(newTrackData);\n this.trackDatas.sort((a, b) => a.track.id - b.track.id);\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n return newTrackData;\n }\n getSubtitleTrackData(track, meta) {\n const existingTrackData = this.trackDatas.find(x => x.track === track);\n if (existingTrackData) {\n return existingTrackData;\n }\n validateSubtitleMetadata(meta);\n assert(meta);\n assert(meta.config);\n const newTrackData = {\n track,\n type: 'subtitle',\n info: {\n config: meta.config,\n },\n chunkQueue: [],\n lastWrittenMsTimestamp: null,\n };\n this.trackDatas.push(newTrackData);\n this.trackDatas.sort((a, b) => a.track.id - b.track.id);\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n return newTrackData;\n }\n async addEncodedVideoPacket(track, packet, meta) {\n const release = await this.mutex.acquire();\n try {\n const trackData = this.getVideoTrackData(track, packet, meta);\n const isKeyFrame = packet.type === 'key';\n let timestamp = this.validateAndNormalizeTimestamp(trackData.track, packet.timestamp, isKeyFrame);\n let duration = packet.duration;\n if (track.metadata.frameRate !== undefined) {\n // Constrain the time values to the frame rate\n timestamp = roundToMultiple(timestamp, 1 / track.metadata.frameRate);\n duration = roundToMultiple(duration, 1 / track.metadata.frameRate);\n }\n const additions = trackData.info.alphaMode\n ? packet.sideData.alpha ?? null\n : null;\n const videoChunk = this.createInternalChunk(packet.data, timestamp, duration, packet.type, additions);\n if (track.source._codec === 'vp9')\n this.fixVP9ColorSpace(trackData, videoChunk);\n trackData.chunkQueue.push(videoChunk);\n await this.interleaveChunks();\n }\n finally {\n release();\n }\n }\n async addEncodedAudioPacket(track, packet, meta) {\n const release = await this.mutex.acquire();\n try {\n const trackData = this.getAudioTrackData(track, meta);\n const isKeyFrame = packet.type === 'key';\n const timestamp = this.validateAndNormalizeTimestamp(trackData.track, packet.timestamp, isKeyFrame);\n const audioChunk = this.createInternalChunk(packet.data, timestamp, packet.duration, packet.type);\n trackData.chunkQueue.push(audioChunk);\n await this.interleaveChunks();\n }\n finally {\n release();\n }\n }\n async addSubtitleCue(track, cue, meta) {\n const release = await this.mutex.acquire();\n try {\n const trackData = this.getSubtitleTrackData(track, meta);\n const timestamp = this.validateAndNormalizeTimestamp(trackData.track, cue.timestamp, true);\n let bodyText = cue.text;\n const timestampMs = Math.round(timestamp * 1000);\n // Replace in-body timestamps so that they're relative to the cue start time\n inlineTimestampRegex.lastIndex = 0;\n bodyText = bodyText.replace(inlineTimestampRegex, (match) => {\n const time = parseSubtitleTimestamp(match.slice(1, -1));\n const offsetTime = time - timestampMs;\n return `<${formatSubtitleTimestamp(offsetTime)}>`;\n });\n const body = textEncoder.encode(bodyText);\n const additions = `${cue.settings ?? ''}\\n${cue.identifier ?? ''}\\n${cue.notes ?? ''}`;\n const subtitleChunk = this.createInternalChunk(body, timestamp, cue.duration, 'key', additions.trim() ? textEncoder.encode(additions) : null);\n trackData.chunkQueue.push(subtitleChunk);\n await this.interleaveChunks();\n }\n finally {\n release();\n }\n }\n async interleaveChunks(isFinalCall = false) {\n if (!isFinalCall && !this.allTracksAreKnown()) {\n return; // We can't interleave yet as we don't yet know how many tracks we'll truly have\n }\n outer: while (true) {\n let trackWithMinTimestamp = null;\n let minTimestamp = Infinity;\n for (const trackData of this.trackDatas) {\n if (!isFinalCall && trackData.chunkQueue.length === 0 && !trackData.track.source._closed) {\n break outer;\n }\n if (trackData.chunkQueue.length > 0 && trackData.chunkQueue[0].timestamp < minTimestamp) {\n trackWithMinTimestamp = trackData;\n minTimestamp = trackData.chunkQueue[0].timestamp;\n }\n }\n if (!trackWithMinTimestamp) {\n break;\n }\n const chunk = trackWithMinTimestamp.chunkQueue.shift();\n this.writeBlock(trackWithMinTimestamp, chunk);\n }\n if (!isFinalCall) {\n await this.writer.flush();\n }\n }\n /**\n * Due to [a bug in Chromium](https://bugs.chromium.org/p/chromium/issues/detail?id=1377842), VP9 streams often\n * lack color space information. This method patches in that information.\n */\n fixVP9ColorSpace(trackData, chunk) {\n // http://downloads.webmproject.org/docs/vp9/vp9-bitstream_superframe-and-uncompressed-header_v1.0.pdf\n if (chunk.type !== 'key')\n return;\n if (!trackData.info.decoderConfig.colorSpace || !trackData.info.decoderConfig.colorSpace.matrix)\n return;\n const bitstream = new Bitstream(chunk.data);\n bitstream.skipBits(2);\n const profileLowBit = bitstream.readBits(1);\n const profileHighBit = bitstream.readBits(1);\n const profile = (profileHighBit << 1) + profileLowBit;\n if (profile === 3)\n bitstream.skipBits(1);\n const showExistingFrame = bitstream.readBits(1);\n if (showExistingFrame)\n return;\n const frameType = bitstream.readBits(1);\n if (frameType !== 0)\n return; // Just to be sure\n bitstream.skipBits(2);\n const syncCode = bitstream.readBits(24);\n if (syncCode !== 0x498342)\n return;\n if (profile >= 2)\n bitstream.skipBits(1);\n const colorSpaceID = {\n rgb: 7,\n bt709: 2,\n bt470bg: 1,\n smpte170m: 3,\n }[trackData.info.decoderConfig.colorSpace.matrix];\n // The bitstream position is now at the start of the color space bits.\n // We can use the global writeBits function here as requested.\n writeBits(chunk.data, bitstream.pos, bitstream.pos + 3, colorSpaceID);\n }\n /** Converts a read-only external chunk into an internal one for easier use. */\n createInternalChunk(data, timestamp, duration, type, additions = null) {\n const internalChunk = {\n data,\n type,\n timestamp,\n duration,\n additions,\n };\n return internalChunk;\n }\n /** Writes a block containing media data to the file. */\n writeBlock(trackData, chunk) {\n // Due to the interlacing algorithm, this code will be run once we've seen one chunk from every media track.\n if (!this.segment) {\n this.createSegment();\n }\n const msTimestamp = Math.round(1000 * chunk.timestamp);\n // We wanna only finalize this cluster (and begin a new one) if we know that each track will be able to\n // start the new one with a key frame.\n const keyFrameQueuedEverywhere = this.trackDatas.every((otherTrackData) => {\n if (trackData === otherTrackData) {\n return chunk.type === 'key';\n }\n const firstQueuedSample = otherTrackData.chunkQueue[0];\n if (firstQueuedSample) {\n return firstQueuedSample.type === 'key';\n }\n return otherTrackData.track.source._closed;\n });\n let shouldCreateNewCluster = false;\n if (!this.currentCluster) {\n shouldCreateNewCluster = true;\n }\n else {\n assert(this.currentClusterStartMsTimestamp !== null);\n assert(this.currentClusterMaxMsTimestamp !== null);\n const relativeTimestamp = msTimestamp - this.currentClusterStartMsTimestamp;\n shouldCreateNewCluster = (keyFrameQueuedEverywhere\n // This check is required because that means there is already a block with this timestamp in the\n // CURRENT chunk, meaning that starting the next cluster at the same timestamp is forbidden (since\n // the already-written block would belong into it instead).\n && msTimestamp > this.currentClusterMaxMsTimestamp\n && relativeTimestamp >= 1000 * (this.format._options.minimumClusterDuration ?? 1))\n // The cluster would exceed its maximum allowed length. This puts us in an unfortunate position and forces\n // us to begin the next cluster with a delta frame. Although this is undesirable, it is not forbidden by the\n // spec and is supported by players.\n || relativeTimestamp > MAX_CLUSTER_TIMESTAMP_MS;\n }\n if (shouldCreateNewCluster) {\n this.createNewCluster(msTimestamp);\n }\n const relativeTimestamp = msTimestamp - this.currentClusterStartMsTimestamp;\n if (relativeTimestamp < MIN_CLUSTER_TIMESTAMP_MS) {\n // The block lies too far in the past, it's not representable within this cluster\n return;\n }\n const prelude = new Uint8Array(4);\n const view = new DataView(prelude.buffer);\n // 0x80 to indicate it's the last byte of a multi-byte number\n view.setUint8(0, 0x80 | trackData.track.id);\n view.setInt16(1, relativeTimestamp, false);\n const msDuration = Math.round(1000 * chunk.duration);\n if (!chunk.additions) {\n // No additions, we can write out a SimpleBlock\n view.setUint8(3, Number(chunk.type === 'key') << 7); // Flags (keyframe flag only present for SimpleBlock)\n const simpleBlock = { id: EBMLId.SimpleBlock, data: [\n prelude,\n chunk.data,\n ] };\n this.ebmlWriter.writeEBML(simpleBlock);\n }\n else {\n const blockGroup = { id: EBMLId.BlockGroup, data: [\n { id: EBMLId.Block, data: [\n prelude,\n chunk.data,\n ] },\n chunk.type === 'delta'\n ? {\n id: EBMLId.ReferenceBlock,\n data: new EBMLSignedInt(trackData.lastWrittenMsTimestamp - msTimestamp),\n }\n : null,\n chunk.additions\n ? { id: EBMLId.BlockAdditions, data: [\n { id: EBMLId.BlockMore, data: [\n { id: EBMLId.BlockAddID, data: 1 }, // Some players expect BlockAddID to come first\n { id: EBMLId.BlockAdditional, data: chunk.additions },\n ] },\n ] }\n : null,\n msDuration > 0 ? { id: EBMLId.BlockDuration, data: msDuration } : null,\n ] };\n this.ebmlWriter.writeEBML(blockGroup);\n }\n this.duration = Math.max(this.duration, msTimestamp + msDuration);\n trackData.lastWrittenMsTimestamp = msTimestamp;\n if (!this.trackDatasInCurrentCluster.has(trackData)) {\n this.trackDatasInCurrentCluster.set(trackData, {\n firstMsTimestamp: msTimestamp,\n });\n }\n this.currentClusterMaxMsTimestamp = Math.max(this.currentClusterMaxMsTimestamp, msTimestamp);\n }\n /** Creates a new Cluster element to contain media chunks. */\n createNewCluster(msTimestamp) {\n if (this.currentCluster) {\n this.finalizeCurrentCluster();\n }\n if (this.format._options.onCluster) {\n this.writer.startTrackingWrites();\n }\n this.currentCluster = {\n id: EBMLId.Cluster,\n size: this.format._options.appendOnly ? -1 : CLUSTER_SIZE_BYTES,\n data: [\n { id: EBMLId.Timestamp, data: msTimestamp },\n ],\n };\n this.ebmlWriter.writeEBML(this.currentCluster);\n this.currentClusterStartMsTimestamp = msTimestamp;\n this.currentClusterMaxMsTimestamp = msTimestamp;\n this.trackDatasInCurrentCluster.clear();\n }\n finalizeCurrentCluster() {\n assert(this.currentCluster);\n if (!this.format._options.appendOnly) {\n const clusterSize = this.writer.getPos() - this.ebmlWriter.dataOffsets.get(this.currentCluster);\n const endPos = this.writer.getPos();\n // Write the size now that we know it\n this.writer.seek(this.ebmlWriter.offsets.get(this.currentCluster) + 4);\n this.ebmlWriter.writeVarInt(clusterSize, CLUSTER_SIZE_BYTES);\n this.writer.seek(endPos);\n }\n if (this.format._options.onCluster) {\n assert(this.currentClusterStartMsTimestamp !== null);\n const { data, start } = this.writer.stopTrackingWrites();\n this.format._options.onCluster(data, start, this.currentClusterStartMsTimestamp / 1000);\n }\n const clusterOffsetFromSegment = this.ebmlWriter.offsets.get(this.currentCluster) - this.segmentDataOffset;\n // Group tracks by their first timestamp and create a CuePoint for each unique timestamp\n const groupedByTimestamp = new Map();\n for (const [trackData, { firstMsTimestamp }] of this.trackDatasInCurrentCluster) {\n if (!groupedByTimestamp.has(firstMsTimestamp)) {\n groupedByTimestamp.set(firstMsTimestamp, []);\n }\n groupedByTimestamp.get(firstMsTimestamp).push(trackData);\n }\n const groupedAndSortedByTimestamp = [...groupedByTimestamp.entries()].sort((a, b) => a[0] - b[0]);\n // Add CuePoints to the Cues element for better seeking\n for (const [msTimestamp, trackDatas] of groupedAndSortedByTimestamp) {\n assert(this.cues);\n this.cues.data.push({ id: EBMLId.CuePoint, data: [\n { id: EBMLId.CueTime, data: msTimestamp },\n // Create CueTrackPositions for each track that starts at this timestamp\n ...trackDatas.map((trackData) => {\n return { id: EBMLId.CueTrackPositions, data: [\n { id: EBMLId.CueTrack, data: trackData.track.id },\n { id: EBMLId.CueClusterPosition, data: clusterOffsetFromSegment },\n ] };\n }),\n ] });\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async onTrackClose() {\n const release = await this.mutex.acquire();\n if (this.allTracksAreKnown()) {\n this.allTracksKnown.resolve();\n }\n // Since a track is now closed, we may be able to write out chunks that were previously waiting\n await this.interleaveChunks();\n release();\n }\n /** Finalizes the file, making it ready for use. Must be called after all media chunks have been added. */\n async finalize() {\n const release = await this.mutex.acquire();\n this.allTracksKnown.resolve();\n if (!this.segment) {\n this.createSegment();\n }\n // Flush any remaining queued chunks to the file\n await this.interleaveChunks(true);\n if (this.currentCluster) {\n this.finalizeCurrentCluster();\n }\n assert(this.cues);\n this.ebmlWriter.writeEBML(this.cues);\n if (!this.format._options.appendOnly) {\n const endPos = this.writer.getPos();\n // Write the Segment size\n const segmentSize = this.writer.getPos() - this.segmentDataOffset;\n this.writer.seek(this.ebmlWriter.offsets.get(this.segment) + 4);\n this.ebmlWriter.writeVarInt(segmentSize, SEGMENT_SIZE_BYTES);\n // Write the duration of the media to the Segment\n this.segmentDuration.data = new EBMLFloat64(this.duration);\n this.writer.seek(this.ebmlWriter.offsets.get(this.segmentDuration));\n this.ebmlWriter.writeEBML(this.segmentDuration);\n // Fill in SeekHead position data and write it again\n assert(this.seekHead);\n this.writer.seek(this.ebmlWriter.offsets.get(this.seekHead));\n this.maybeCreateSeekHead(true);\n this.ebmlWriter.writeEBML(this.seekHead);\n this.writer.seek(endPos);\n }\n release();\n }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nexport const buildMatroskaMimeType = (info) => {\n const base = info.hasVideo\n ? 'video/'\n : info.hasAudio\n ? 'audio/'\n : 'application/';\n let string = base + (info.isWebM ? 'webm' : 'x-matroska');\n if (info.codecStrings.length > 0) {\n const uniqueCodecMimeTypes = [...new Set(info.codecStrings.filter(Boolean))];\n string += `; codecs=\"${uniqueCodecMimeTypes.join(', ')}\"`;\n }\n return string;\n};\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { AdtsMuxer } from './adts/adts-muxer.js';\nimport { AUDIO_CODECS, NON_PCM_AUDIO_CODECS, PCM_AUDIO_CODECS, SUBTITLE_CODECS, VIDEO_CODECS, } from './codec.js';\nimport { FlacMuxer } from './flac/flac-muxer.js';\nimport { IsobmffMuxer } from './isobmff/isobmff-muxer.js';\nimport { MatroskaMuxer } from './matroska/matroska-muxer.js';\nimport { Mp3Muxer } from './mp3/mp3-muxer.js';\nimport { OggMuxer } from './ogg/ogg-muxer.js';\nimport { WaveMuxer } from './wave/wave-muxer.js';\n/**\n * Base class representing an output media file format.\n * @group Output formats\n * @public\n */\nexport class OutputFormat {\n /** Returns a list of video codecs that this output format can contain. */\n getSupportedVideoCodecs() {\n return this.getSupportedCodecs()\n .filter(codec => VIDEO_CODECS.includes(codec));\n }\n /** Returns a list of audio codecs that this output format can contain. */\n getSupportedAudioCodecs() {\n return this.getSupportedCodecs()\n .filter(codec => AUDIO_CODECS.includes(codec));\n }\n /** Returns a list of subtitle codecs that this output format can contain. */\n getSupportedSubtitleCodecs() {\n return this.getSupportedCodecs()\n .filter(codec => SUBTITLE_CODECS.includes(codec));\n }\n /** @internal */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _codecUnsupportedHint(codec) {\n return '';\n }\n}\n/**\n * Format representing files compatible with the ISO base media file format (ISOBMFF), like MP4 or MOV files.\n * @group Output formats\n * @public\n */\nexport class IsobmffOutputFormat extends OutputFormat {\n /** Internal constructor. */\n constructor(options = {}) {\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n if (options.fastStart !== undefined\n && ![false, 'in-memory', 'reserve', 'fragmented'].includes(options.fastStart)) {\n throw new TypeError('options.fastStart, when provided, must be false, \\'in-memory\\', \\'reserve\\', or \\'fragmented\\'.');\n }\n if (options.minimumFragmentDuration !== undefined\n && (!Number.isFinite(options.minimumFragmentDuration) || options.minimumFragmentDuration < 0)) {\n throw new TypeError('options.minimumFragmentDuration, when provided, must be a non-negative number.');\n }\n if (options.onFtyp !== undefined && typeof options.onFtyp !== 'function') {\n throw new TypeError('options.onFtyp, when provided, must be a function.');\n }\n if (options.onMoov !== undefined && typeof options.onMoov !== 'function') {\n throw new TypeError('options.onMoov, when provided, must be a function.');\n }\n if (options.onMdat !== undefined && typeof options.onMdat !== 'function') {\n throw new TypeError('options.onMdat, when provided, must be a function.');\n }\n if (options.onMoof !== undefined && typeof options.onMoof !== 'function') {\n throw new TypeError('options.onMoof, when provided, must be a function.');\n }\n if (options.metadataFormat !== undefined\n && !['mdir', 'mdta', 'udta', 'auto'].includes(options.metadataFormat)) {\n throw new TypeError('options.metadataFormat, when provided, must be either \\'auto\\', \\'mdir\\', \\'mdta\\', or \\'udta\\'.');\n }\n super();\n this._options = options;\n }\n getSupportedTrackCounts() {\n return {\n video: { min: 0, max: Infinity },\n audio: { min: 0, max: Infinity },\n subtitle: { min: 0, max: Infinity },\n total: { min: 1, max: 2 ** 32 - 1 }, // Have fun reaching this one\n };\n }\n get supportsVideoRotationMetadata() {\n return true;\n }\n /** @internal */\n _createMuxer(output) {\n return new IsobmffMuxer(output, this);\n }\n}\n/**\n * MPEG-4 Part 14 (MP4) file format. Supports most codecs.\n * @group Output formats\n * @public\n */\nexport class Mp4OutputFormat extends IsobmffOutputFormat {\n /** Creates a new {@link Mp4OutputFormat} configured with the specified `options`. */\n constructor(options) {\n super(options);\n }\n /** @internal */\n get _name() {\n return 'MP4';\n }\n get fileExtension() {\n return '.mp4';\n }\n get mimeType() {\n return 'video/mp4';\n }\n getSupportedCodecs() {\n return [\n ...VIDEO_CODECS,\n ...NON_PCM_AUDIO_CODECS,\n // These are supported via ISO/IEC 23003-5\n 'pcm-s16',\n 'pcm-s16be',\n 'pcm-s24',\n 'pcm-s24be',\n 'pcm-s32',\n 'pcm-s32be',\n 'pcm-f32',\n 'pcm-f32be',\n 'pcm-f64',\n 'pcm-f64be',\n ...SUBTITLE_CODECS,\n ];\n }\n /** @internal */\n _codecUnsupportedHint(codec) {\n if (new MovOutputFormat().getSupportedCodecs().includes(codec)) {\n return ' Switching to MOV will grant support for this codec.';\n }\n return '';\n }\n}\n/**\n * QuickTime File Format (QTFF), often called MOV. Supports all video and audio codecs, but not subtitle codecs.\n * @group Output formats\n * @public\n */\nexport class MovOutputFormat extends IsobmffOutputFormat {\n /** Creates a new {@link MovOutputFormat} configured with the specified `options`. */\n constructor(options) {\n super(options);\n }\n /** @internal */\n get _name() {\n return 'MOV';\n }\n get fileExtension() {\n return '.mov';\n }\n get mimeType() {\n return 'video/quicktime';\n }\n getSupportedCodecs() {\n return [\n ...VIDEO_CODECS,\n ...AUDIO_CODECS,\n ];\n }\n /** @internal */\n _codecUnsupportedHint(codec) {\n if (new Mp4OutputFormat().getSupportedCodecs().includes(codec)) {\n return ' Switching to MP4 will grant support for this codec.';\n }\n return '';\n }\n}\n/**\n * Matroska file format.\n *\n * Supports writing transparent video. For a video track to be marked as transparent, the first packet added must\n * contain alpha side data.\n *\n * @group Output formats\n * @public\n */\nexport class MkvOutputFormat extends OutputFormat {\n /** Creates a new {@link MkvOutputFormat} configured with the specified `options`. */\n constructor(options = {}) {\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n if (options.appendOnly !== undefined && typeof options.appendOnly !== 'boolean') {\n throw new TypeError('options.appendOnly, when provided, must be a boolean.');\n }\n if (options.minimumClusterDuration !== undefined\n && (!Number.isFinite(options.minimumClusterDuration) || options.minimumClusterDuration < 0)) {\n throw new TypeError('options.minimumClusterDuration, when provided, must be a non-negative number.');\n }\n if (options.onEbmlHeader !== undefined && typeof options.onEbmlHeader !== 'function') {\n throw new TypeError('options.onEbmlHeader, when provided, must be a function.');\n }\n if (options.onSegmentHeader !== undefined && typeof options.onSegmentHeader !== 'function') {\n throw new TypeError('options.onHeader, when provided, must be a function.');\n }\n if (options.onCluster !== undefined && typeof options.onCluster !== 'function') {\n throw new TypeError('options.onCluster, when provided, must be a function.');\n }\n super();\n this._options = options;\n }\n /** @internal */\n _createMuxer(output) {\n return new MatroskaMuxer(output, this);\n }\n /** @internal */\n get _name() {\n return 'Matroska';\n }\n getSupportedTrackCounts() {\n return {\n video: { min: 0, max: Infinity },\n audio: { min: 0, max: Infinity },\n subtitle: { min: 0, max: Infinity },\n total: { min: 1, max: 127 },\n };\n }\n get fileExtension() {\n return '.mkv';\n }\n get mimeType() {\n return 'video/x-matroska';\n }\n getSupportedCodecs() {\n return [\n ...VIDEO_CODECS,\n ...NON_PCM_AUDIO_CODECS,\n ...PCM_AUDIO_CODECS.filter(codec => !['pcm-s8', 'pcm-f32be', 'pcm-f64be', 'ulaw', 'alaw'].includes(codec)),\n ...SUBTITLE_CODECS,\n ];\n }\n get supportsVideoRotationMetadata() {\n // While it technically does support it with ProjectionPoseRoll, many players appear to ignore this value\n return false;\n }\n}\n/**\n * WebM file format, based on Matroska.\n *\n * Supports writing transparent video. For a video track to be marked as transparent, the first packet added must\n * contain alpha side data.\n *\n * @group Output formats\n * @public\n */\nexport class WebMOutputFormat extends MkvOutputFormat {\n /** Creates a new {@link WebMOutputFormat} configured with the specified `options`. */\n constructor(options) {\n super(options);\n }\n getSupportedCodecs() {\n return [\n ...VIDEO_CODECS.filter(codec => ['vp8', 'vp9', 'av1'].includes(codec)),\n ...AUDIO_CODECS.filter(codec => ['opus', 'vorbis'].includes(codec)),\n ...SUBTITLE_CODECS,\n ];\n }\n /** @internal */\n get _name() {\n return 'WebM';\n }\n get fileExtension() {\n return '.webm';\n }\n get mimeType() {\n return 'video/webm';\n }\n /** @internal */\n _codecUnsupportedHint(codec) {\n if (new MkvOutputFormat().getSupportedCodecs().includes(codec)) {\n return ' Switching to MKV will grant support for this codec.';\n }\n return '';\n }\n}\n/**\n * MP3 file format.\n * @group Output formats\n * @public\n */\nexport class Mp3OutputFormat extends OutputFormat {\n /** Creates a new {@link Mp3OutputFormat} configured with the specified `options`. */\n constructor(options = {}) {\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n if (options.xingHeader !== undefined && typeof options.xingHeader !== 'boolean') {\n throw new TypeError('options.xingHeader, when provided, must be a boolean.');\n }\n if (options.onXingFrame !== undefined && typeof options.onXingFrame !== 'function') {\n throw new TypeError('options.onXingFrame, when provided, must be a function.');\n }\n super();\n this._options = options;\n }\n /** @internal */\n _createMuxer(output) {\n return new Mp3Muxer(output, this);\n }\n /** @internal */\n get _name() {\n return 'MP3';\n }\n getSupportedTrackCounts() {\n return {\n video: { min: 0, max: 0 },\n audio: { min: 1, max: 1 },\n subtitle: { min: 0, max: 0 },\n total: { min: 1, max: 1 },\n };\n }\n get fileExtension() {\n return '.mp3';\n }\n get mimeType() {\n return 'audio/mpeg';\n }\n getSupportedCodecs() {\n return ['mp3'];\n }\n get supportsVideoRotationMetadata() {\n return false;\n }\n}\n/**\n * WAVE file format, based on RIFF.\n * @group Output formats\n * @public\n */\nexport class WavOutputFormat extends OutputFormat {\n /** Creates a new {@link WavOutputFormat} configured with the specified `options`. */\n constructor(options = {}) {\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n if (options.large !== undefined && typeof options.large !== 'boolean') {\n throw new TypeError('options.large, when provided, must be a boolean.');\n }\n if (options.metadataFormat !== undefined && !['info', 'id3'].includes(options.metadataFormat)) {\n throw new TypeError('options.metadataFormat, when provided, must be either \\'info\\' or \\'id3\\'.');\n }\n if (options.onHeader !== undefined && typeof options.onHeader !== 'function') {\n throw new TypeError('options.onHeader, when provided, must be a function.');\n }\n super();\n this._options = options;\n }\n /** @internal */\n _createMuxer(output) {\n return new WaveMuxer(output, this);\n }\n /** @internal */\n get _name() {\n return 'WAVE';\n }\n getSupportedTrackCounts() {\n return {\n video: { min: 0, max: 0 },\n audio: { min: 1, max: 1 },\n subtitle: { min: 0, max: 0 },\n total: { min: 1, max: 1 },\n };\n }\n get fileExtension() {\n return '.wav';\n }\n get mimeType() {\n return 'audio/wav';\n }\n getSupportedCodecs() {\n return [\n ...PCM_AUDIO_CODECS.filter(codec => ['pcm-s16', 'pcm-s24', 'pcm-s32', 'pcm-f32', 'pcm-u8', 'ulaw', 'alaw'].includes(codec)),\n ];\n }\n get supportsVideoRotationMetadata() {\n return false;\n }\n}\n/**\n * Ogg file format.\n * @group Output formats\n * @public\n */\nexport class OggOutputFormat extends OutputFormat {\n /** Creates a new {@link OggOutputFormat} configured with the specified `options`. */\n constructor(options = {}) {\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n if (options.onPage !== undefined && typeof options.onPage !== 'function') {\n throw new TypeError('options.onPage, when provided, must be a function.');\n }\n super();\n this._options = options;\n }\n /** @internal */\n _createMuxer(output) {\n return new OggMuxer(output, this);\n }\n /** @internal */\n get _name() {\n return 'Ogg';\n }\n getSupportedTrackCounts() {\n return {\n video: { min: 0, max: 0 },\n audio: { min: 0, max: Infinity },\n subtitle: { min: 0, max: 0 },\n total: { min: 1, max: 2 ** 32 },\n };\n }\n get fileExtension() {\n return '.ogg';\n }\n get mimeType() {\n return 'application/ogg';\n }\n getSupportedCodecs() {\n return [\n ...AUDIO_CODECS.filter(codec => ['vorbis', 'opus'].includes(codec)),\n ];\n }\n get supportsVideoRotationMetadata() {\n return false;\n }\n}\n/**\n * ADTS file format.\n * @group Output formats\n * @public\n */\nexport class AdtsOutputFormat extends OutputFormat {\n /** Creates a new {@link AdtsOutputFormat} configured with the specified `options`. */\n constructor(options = {}) {\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n if (options.onFrame !== undefined && typeof options.onFrame !== 'function') {\n throw new TypeError('options.onFrame, when provided, must be a function.');\n }\n super();\n this._options = options;\n }\n /** @internal */\n _createMuxer(output) {\n return new AdtsMuxer(output, this);\n }\n /** @internal */\n get _name() {\n return 'ADTS';\n }\n getSupportedTrackCounts() {\n return {\n video: { min: 0, max: 0 },\n audio: { min: 1, max: 1 },\n subtitle: { min: 0, max: 0 },\n total: { min: 1, max: 1 },\n };\n }\n get fileExtension() {\n return '.aac';\n }\n get mimeType() {\n return 'audio/aac';\n }\n getSupportedCodecs() {\n return ['aac'];\n }\n get supportsVideoRotationMetadata() {\n return false;\n }\n}\n/**\n * FLAC file format.\n * @group Output formats\n * @public\n */\nexport class FlacOutputFormat extends OutputFormat {\n /** Creates a new {@link FlacOutputFormat} configured with the specified `options`. */\n constructor(options = {}) {\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n super();\n this._options = options;\n }\n /** @internal */\n _createMuxer(output) {\n return new FlacMuxer(output, this);\n }\n /** @internal */\n get _name() {\n return 'FLAC';\n }\n getSupportedTrackCounts() {\n return {\n video: { min: 0, max: 0 },\n audio: { min: 1, max: 1 },\n subtitle: { min: 0, max: 0 },\n total: { min: 1, max: 1 },\n };\n }\n get fileExtension() {\n return '.flac';\n }\n get mimeType() {\n return 'audio/flac';\n }\n getSupportedCodecs() {\n return ['flac'];\n }\n get supportsVideoRotationMetadata() {\n return false;\n }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { AUDIO_CODECS, buildAacAudioSpecificConfig, parseAacAudioSpecificConfig, parsePcmCodec, PCM_AUDIO_CODECS, SUBTITLE_CODECS, VIDEO_CODECS, } from './codec.js';\nimport { assert, assertNever, CallSerializer, clamp, isFirefox, last, promiseWithResolvers, setInt24, setUint24, toUint8Array, } from './misc.js';\nimport { SubtitleParser } from './subtitles.js';\nimport { toAlaw, toUlaw } from './pcm.js';\nimport { customVideoEncoders, customAudioEncoders, } from './custom-coder.js';\nimport { EncodedPacket } from './packet.js';\nimport { AudioSample, VideoSample } from './sample.js';\nimport { buildAudioEncoderConfig, buildVideoEncoderConfig, validateAudioEncodingConfig, validateVideoEncodingConfig, } from './encode.js';\n/**\n * Base class for media sources. Media sources are used to add media samples to an output file.\n * @group Media sources\n * @public\n */\nexport class MediaSource {\n constructor() {\n /** @internal */\n this._connectedTrack = null;\n /** @internal */\n this._closingPromise = null;\n /** @internal */\n this._closed = false;\n /**\n * @internal\n * A time offset in seconds that is added to all timestamps generated by this source.\n */\n this._timestampOffset = 0;\n }\n /** @internal */\n _ensureValidAdd() {\n if (!this._connectedTrack) {\n throw new Error('Source is not connected to an output track.');\n }\n if (this._connectedTrack.output.state === 'canceled') {\n throw new Error('Output has been canceled.');\n }\n if (this._connectedTrack.output.state === 'finalizing' || this._connectedTrack.output.state === 'finalized') {\n throw new Error('Output has been finalized.');\n }\n if (this._connectedTrack.output.state === 'pending') {\n throw new Error('Output has not started.');\n }\n if (this._closed) {\n throw new Error('Source is closed.');\n }\n }\n /** @internal */\n async _start() { }\n /** @internal */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async _flushAndClose(forceClose) { }\n /**\n * Closes this source. This prevents future samples from being added and signals to the output file that no further\n * samples will come in for this track. Calling `.close()` is optional but recommended after adding the\n * last sample - for improved performance and reduced memory usage.\n */\n close() {\n if (this._closingPromise) {\n return;\n }\n const connectedTrack = this._connectedTrack;\n if (!connectedTrack) {\n throw new Error('Cannot call close without connecting the source to an output track.');\n }\n if (connectedTrack.output.state === 'pending') {\n throw new Error('Cannot call close before output has been started.');\n }\n this._closingPromise = (async () => {\n await this._flushAndClose(false);\n this._closed = true;\n if (connectedTrack.output.state === 'finalizing' || connectedTrack.output.state === 'finalized') {\n return;\n }\n connectedTrack.output._muxer.onTrackClose(connectedTrack);\n })();\n }\n /** @internal */\n async _flushOrWaitForOngoingClose(forceClose) {\n if (this._closingPromise) {\n // Since closing also flushes, we don't want to do it twice\n return this._closingPromise;\n }\n else {\n return this._flushAndClose(forceClose);\n }\n }\n}\n/**\n * Base class for video sources - sources for video tracks.\n * @group Media sources\n * @public\n */\nexport class VideoSource extends MediaSource {\n /** Internal constructor. */\n constructor(codec) {\n super();\n /** @internal */\n this._connectedTrack = null;\n if (!VIDEO_CODECS.includes(codec)) {\n throw new TypeError(`Invalid video codec '${codec}'. Must be one of: ${VIDEO_CODECS.join(', ')}.`);\n }\n this._codec = codec;\n }\n}\n/**\n * The most basic video source; can be used to directly pipe encoded packets into the output file.\n * @group Media sources\n * @public\n */\nexport class EncodedVideoPacketSource extends VideoSource {\n /** Creates a new {@link EncodedVideoPacketSource} whose packets are encoded using `codec`. */\n constructor(codec) {\n super(codec);\n }\n /**\n * Adds an encoded packet to the output video track. Packets must be added in *decode order*, while a packet's\n * timestamp must be its *presentation timestamp*. B-frames are handled automatically.\n *\n * @param meta - Additional metadata from the encoder. You should pass this for the first call, including a valid\n * decoder config.\n *\n * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise\n * to respect writer and encoder backpressure.\n */\n add(packet, meta) {\n if (!(packet instanceof EncodedPacket)) {\n throw new TypeError('packet must be an EncodedPacket.');\n }\n if (packet.isMetadataOnly) {\n throw new TypeError('Metadata-only packets cannot be added.');\n }\n if (meta !== undefined && (!meta || typeof meta !== 'object')) {\n throw new TypeError('meta, when provided, must be an object.');\n }\n this._ensureValidAdd();\n return this._connectedTrack.output._muxer.addEncodedVideoPacket(this._connectedTrack, packet, meta);\n }\n}\nclass VideoEncoderWrapper {\n constructor(source, encodingConfig) {\n this.source = source;\n this.encodingConfig = encodingConfig;\n this.ensureEncoderPromise = null;\n this.encoderInitialized = false;\n this.encoder = null;\n this.muxer = null;\n this.lastMultipleOfKeyFrameInterval = -1;\n this.codedWidth = null;\n this.codedHeight = null;\n this.resizeCanvas = null;\n this.customEncoder = null;\n this.customEncoderCallSerializer = new CallSerializer();\n this.customEncoderQueueSize = 0;\n // Alpha stuff\n this.alphaEncoder = null;\n this.splitter = null;\n this.splitterCreationFailed = false;\n this.alphaFrameQueue = [];\n /**\n * Encoders typically throw their errors \"out of band\", meaning asynchronously in some other execution context.\n * However, we want to surface these errors to the user within the normal control flow, so they don't go uncaught.\n * So, we keep track of the encoder error and throw it as soon as we get the chance.\n */\n this.error = null;\n this.errorNeedsNewStack = true;\n }\n async add(videoSample, shouldClose, encodeOptions) {\n try {\n this.checkForEncoderError();\n this.source._ensureValidAdd();\n // Ensure video sample size remains constant\n if (this.codedWidth !== null && this.codedHeight !== null) {\n if (videoSample.codedWidth !== this.codedWidth || videoSample.codedHeight !== this.codedHeight) {\n const sizeChangeBehavior = this.encodingConfig.sizeChangeBehavior ?? 'deny';\n if (sizeChangeBehavior === 'passThrough') {\n // Do nada\n }\n else if (sizeChangeBehavior === 'deny') {\n throw new Error(`Video sample size must remain constant. Expected ${this.codedWidth}x${this.codedHeight},`\n + ` got ${videoSample.codedWidth}x${videoSample.codedHeight}. To allow the sample size to`\n + ` change over time, set \\`sizeChangeBehavior\\` to a value other than 'strict' in the`\n + ` encoding options.`);\n }\n else {\n let canvasIsNew = false;\n if (!this.resizeCanvas) {\n if (typeof document !== 'undefined') {\n // Prefer an HTMLCanvasElement\n this.resizeCanvas = document.createElement('canvas');\n this.resizeCanvas.width = this.codedWidth;\n this.resizeCanvas.height = this.codedHeight;\n }\n else {\n this.resizeCanvas = new OffscreenCanvas(this.codedWidth, this.codedHeight);\n }\n canvasIsNew = true;\n }\n const context = this.resizeCanvas.getContext('2d', {\n alpha: isFirefox(), // Firefox has VideoFrame glitches with opaque canvases\n });\n assert(context);\n if (!canvasIsNew) {\n if (isFirefox()) {\n context.fillStyle = 'black';\n context.fillRect(0, 0, this.codedWidth, this.codedHeight);\n }\n else {\n context.clearRect(0, 0, this.codedWidth, this.codedHeight);\n }\n }\n videoSample.drawWithFit(context, { fit: sizeChangeBehavior });\n if (shouldClose) {\n videoSample.close();\n }\n videoSample = new VideoSample(this.resizeCanvas, {\n timestamp: videoSample.timestamp,\n duration: videoSample.duration,\n rotation: videoSample.rotation,\n });\n shouldClose = true;\n }\n }\n }\n else {\n this.codedWidth = videoSample.codedWidth;\n this.codedHeight = videoSample.codedHeight;\n }\n if (!this.encoderInitialized) {\n if (!this.ensureEncoderPromise) {\n this.ensureEncoder(videoSample);\n }\n // No, this \"if\" statement is not useless. Sometimes, the above call to `ensureEncoder` might have\n // synchronously completed and the encoder is already initialized. In this case, we don't need to await\n // the promise anymore. This also fixes nasty async race condition bugs when multiple code paths are\n // calling this method: It's important that the call that initialized the encoder go through this\n // code first.\n if (!this.encoderInitialized) {\n await this.ensureEncoderPromise;\n }\n }\n assert(this.encoderInitialized);\n const keyFrameInterval = this.encodingConfig.keyFrameInterval ?? 5;\n const multipleOfKeyFrameInterval = Math.floor(videoSample.timestamp / keyFrameInterval);\n // Ensure a key frame every keyFrameInterval seconds. It is important that all video tracks follow the same\n // \"key frame\" rhythm, because aligned key frames are required to start new fragments in ISOBMFF or clusters\n // in Matroska (or at least desirable).\n const finalEncodeOptions = {\n ...encodeOptions,\n keyFrame: encodeOptions?.keyFrame\n || keyFrameInterval === 0\n || multipleOfKeyFrameInterval !== this.lastMultipleOfKeyFrameInterval,\n };\n this.lastMultipleOfKeyFrameInterval = multipleOfKeyFrameInterval;\n if (this.customEncoder) {\n this.customEncoderQueueSize++;\n // We clone the sample so it cannot be closed on us from the outside before it reaches the encoder\n const clonedSample = videoSample.clone();\n const promise = this.customEncoderCallSerializer\n .call(() => this.customEncoder.encode(clonedSample, finalEncodeOptions))\n .then(() => this.customEncoderQueueSize--)\n .catch((error) => this.error ??= error)\n .finally(() => {\n clonedSample.close();\n // `videoSample` gets closed in the finally block at the end of the method\n });\n if (this.customEncoderQueueSize >= 4) {\n await promise;\n }\n }\n else {\n assert(this.encoder);\n const videoFrame = videoSample.toVideoFrame();\n if (!this.alphaEncoder) {\n // No alpha encoder, simple case\n this.encoder.encode(videoFrame, finalEncodeOptions);\n videoFrame.close();\n }\n else {\n // We're expected to encode alpha as well\n const frameDefinitelyHasNoAlpha = !!videoFrame.format && !videoFrame.format.includes('A');\n if (frameDefinitelyHasNoAlpha || this.splitterCreationFailed) {\n this.alphaFrameQueue.push(null);\n this.encoder.encode(videoFrame, finalEncodeOptions);\n videoFrame.close();\n }\n else {\n const width = videoFrame.displayWidth;\n const height = videoFrame.displayHeight;\n if (!this.splitter) {\n try {\n this.splitter = new ColorAlphaSplitter(width, height);\n }\n catch (error) {\n console.error('Due to an error, only color data will be encoded.', error);\n this.splitterCreationFailed = true;\n this.alphaFrameQueue.push(null);\n this.encoder.encode(videoFrame, finalEncodeOptions);\n videoFrame.close();\n }\n }\n if (this.splitter) {\n const colorFrame = this.splitter.extractColor(videoFrame);\n const alphaFrame = this.splitter.extractAlpha(videoFrame);\n this.alphaFrameQueue.push(alphaFrame);\n this.encoder.encode(colorFrame, finalEncodeOptions);\n colorFrame.close();\n videoFrame.close();\n }\n }\n }\n if (shouldClose) {\n videoSample.close();\n }\n // We need to do this after sending the frame to the encoder as the frame otherwise might be closed\n if (this.encoder.encodeQueueSize >= 4) {\n await new Promise(resolve => this.encoder.addEventListener('dequeue', resolve, { once: true }));\n }\n }\n await this.muxer.mutex.currentPromise; // Allow the writer to apply backpressure\n }\n finally {\n if (shouldClose) {\n // Make sure it's always closed, even if there was an error\n videoSample.close();\n }\n }\n }\n ensureEncoder(videoSample) {\n const encoderError = new Error();\n this.ensureEncoderPromise = (async () => {\n const encoderConfig = buildVideoEncoderConfig({\n width: videoSample.codedWidth,\n height: videoSample.codedHeight,\n ...this.encodingConfig,\n framerate: this.source._connectedTrack?.metadata.frameRate,\n });\n this.encodingConfig.onEncoderConfig?.(encoderConfig);\n const MatchingCustomEncoder = customVideoEncoders.find(x => x.supports(this.encodingConfig.codec, encoderConfig));\n if (MatchingCustomEncoder) {\n // @ts-expect-error \"Can't create instance of abstract class 🤓\"\n this.customEncoder = new MatchingCustomEncoder();\n // @ts-expect-error It's technically readonly\n this.customEncoder.codec = this.encodingConfig.codec;\n // @ts-expect-error It's technically readonly\n this.customEncoder.config = encoderConfig;\n // @ts-expect-error It's technically readonly\n this.customEncoder.onPacket = (packet, meta) => {\n if (!(packet instanceof EncodedPacket)) {\n throw new TypeError('The first argument passed to onPacket must be an EncodedPacket.');\n }\n if (meta !== undefined && (!meta || typeof meta !== 'object')) {\n throw new TypeError('The second argument passed to onPacket must be an object or undefined.');\n }\n this.encodingConfig.onEncodedPacket?.(packet, meta);\n void this.muxer.addEncodedVideoPacket(this.source._connectedTrack, packet, meta)\n .catch((error) => {\n this.error ??= error;\n this.errorNeedsNewStack = false;\n });\n };\n await this.customEncoder.init();\n }\n else {\n if (typeof VideoEncoder === 'undefined') {\n throw new Error('VideoEncoder is not supported by this browser.');\n }\n encoderConfig.alpha = 'discard'; // Since we handle alpha ourselves\n if (this.encodingConfig.alpha === 'keep') {\n // Encoding alpha requires using two parallel encoders, so we need to make sure they stay in sync\n // and that neither of them drops frames. Setting latencyMode to 'quality' achieves this, because\n // \"User Agents MUST not drop frames to achieve the target bitrate and/or framerate.\"\n encoderConfig.latencyMode = 'quality';\n }\n const hasOddDimension = encoderConfig.width % 2 === 1 || encoderConfig.height % 2 === 1;\n if (hasOddDimension\n && (this.encodingConfig.codec === 'avc' || this.encodingConfig.codec === 'hevc')) {\n // Throw a special error for this case as it gets hit often\n throw new Error(`The dimensions ${encoderConfig.width}x${encoderConfig.height} are not supported for codec`\n + ` '${this.encodingConfig.codec}'; both width and height must be even numbers. Make sure to`\n + ` round your dimensions to the nearest even number.`);\n }\n const support = await VideoEncoder.isConfigSupported(encoderConfig);\n if (!support.supported) {\n throw new Error(`This specific encoder configuration (${encoderConfig.codec}, ${encoderConfig.bitrate} bps,`\n + ` ${encoderConfig.width}x${encoderConfig.height}, hardware acceleration:`\n + ` ${encoderConfig.hardwareAcceleration ?? 'no-preference'}) is not supported by this browser.`\n + ` Consider using another codec or changing your video parameters.`);\n }\n /** Queue of color chunks waiting for their alpha counterpart. */\n const colorChunkQueue = [];\n /** Each value is the number of encoded alpha chunks at which a null alpha chunk should be added. */\n const nullAlphaChunkQueue = [];\n let encodedAlphaChunkCount = 0;\n let alphaEncoderQueue = 0;\n const addPacket = (colorChunk, alphaChunk, meta) => {\n const sideData = {};\n if (alphaChunk) {\n const alphaData = new Uint8Array(alphaChunk.byteLength);\n alphaChunk.copyTo(alphaData);\n sideData.alpha = alphaData;\n }\n const packet = EncodedPacket.fromEncodedChunk(colorChunk, sideData);\n this.encodingConfig.onEncodedPacket?.(packet, meta);\n void this.muxer.addEncodedVideoPacket(this.source._connectedTrack, packet, meta)\n .catch((error) => {\n this.error ??= error;\n this.errorNeedsNewStack = false;\n });\n };\n this.encoder = new VideoEncoder({\n output: (chunk, meta) => {\n if (!this.alphaEncoder) {\n // We're done\n addPacket(chunk, null, meta);\n return;\n }\n const alphaFrame = this.alphaFrameQueue.shift();\n assert(alphaFrame !== undefined);\n if (alphaFrame) {\n this.alphaEncoder.encode(alphaFrame, {\n // Crucial: The alpha frame is forced to be a key frame whenever the color frame\n // also is. Without this, playback can glitch and even crash in some browsers.\n // This is the reason why the two encoders are wired in series and not in parallel.\n keyFrame: chunk.type === 'key',\n });\n alphaEncoderQueue++;\n alphaFrame.close();\n colorChunkQueue.push({ chunk, meta });\n }\n else {\n // There was no alpha component for this frame\n if (alphaEncoderQueue === 0) {\n // No pending alpha encodes either, so we're done\n addPacket(chunk, null, meta);\n }\n else {\n // There are still alpha encodes pending, so we can't add the packet immediately since\n // we'd end up with out-of-order packets. Instead, let's queue a null alpha chunk to be\n // added in the future, after the current encoder workload has completed:\n nullAlphaChunkQueue.push(encodedAlphaChunkCount + alphaEncoderQueue);\n colorChunkQueue.push({ chunk, meta });\n }\n }\n },\n error: (error) => {\n error.stack = encoderError.stack; // Provide a more useful stack trace\n this.error ??= error;\n },\n });\n this.encoder.configure(encoderConfig);\n if (this.encodingConfig.alpha === 'keep') {\n // We need to encode alpha as well, which we do with a separate encoder\n this.alphaEncoder = new VideoEncoder({\n // We ignore the alpha chunk's metadata\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n output: (chunk, meta) => {\n alphaEncoderQueue--;\n // There has to be a color chunk because the encoders are wired in series\n const colorChunk = colorChunkQueue.shift();\n assert(colorChunk !== undefined);\n addPacket(colorChunk.chunk, chunk, colorChunk.meta);\n // See if there are any null alpha chunks queued up\n encodedAlphaChunkCount++;\n while (nullAlphaChunkQueue.length > 0\n && nullAlphaChunkQueue[0] === encodedAlphaChunkCount) {\n nullAlphaChunkQueue.shift();\n const colorChunk = colorChunkQueue.shift();\n assert(colorChunk !== undefined);\n addPacket(colorChunk.chunk, null, colorChunk.meta);\n }\n },\n error: (error) => {\n error.stack = encoderError.stack; // Provide a more useful stack trace\n this.error ??= error;\n },\n });\n this.alphaEncoder.configure(encoderConfig);\n }\n }\n assert(this.source._connectedTrack);\n this.muxer = this.source._connectedTrack.output._muxer;\n this.encoderInitialized = true;\n })();\n }\n async flushAndClose(forceClose) {\n if (!forceClose)\n this.checkForEncoderError();\n if (this.customEncoder) {\n if (!forceClose) {\n void this.customEncoderCallSerializer.call(() => this.customEncoder.flush());\n }\n await this.customEncoderCallSerializer.call(() => this.customEncoder.close());\n }\n else if (this.encoder) {\n if (!forceClose) {\n // These are wired in series, therefore they must also be flushed in series\n await this.encoder.flush();\n await this.alphaEncoder?.flush();\n }\n if (this.encoder.state !== 'closed') {\n this.encoder.close();\n }\n if (this.alphaEncoder && this.alphaEncoder.state !== 'closed') {\n this.alphaEncoder.close();\n }\n this.alphaFrameQueue.forEach(x => x?.close());\n this.splitter?.close();\n }\n if (!forceClose)\n this.checkForEncoderError();\n }\n getQueueSize() {\n if (this.customEncoder) {\n return this.customEncoderQueueSize;\n }\n else {\n // Because the color and alpha encoders are wired in series, there's no need to also include the alpha\n // encoder's queue size here\n return this.encoder?.encodeQueueSize ?? 0;\n }\n }\n checkForEncoderError() {\n if (this.error) {\n if (this.errorNeedsNewStack) {\n this.error.stack = new Error().stack; // Provide an even more useful stack trace\n }\n throw this.error;\n }\n }\n}\n/** Utility class for splitting a composite frame into separate color and alpha components. */\nclass ColorAlphaSplitter {\n constructor(initialWidth, initialHeight) {\n this.lastFrame = null;\n if (typeof OffscreenCanvas !== 'undefined') {\n this.canvas = new OffscreenCanvas(initialWidth, initialHeight);\n }\n else {\n this.canvas = document.createElement('canvas');\n this.canvas.width = initialWidth;\n this.canvas.height = initialHeight;\n }\n const gl = this.canvas.getContext('webgl2', {\n alpha: true, // Needed due to the YUV thing we do for alpha\n }); // Casting because of some TypeScript weirdness\n if (!gl) {\n throw new Error('Couldn\\'t acquire WebGL 2 context.');\n }\n this.gl = gl;\n this.colorProgram = this.createColorProgram();\n this.alphaProgram = this.createAlphaProgram();\n this.vao = this.createVAO();\n this.sourceTexture = this.createTexture();\n this.alphaResolutionLocation = this.gl.getUniformLocation(this.alphaProgram, 'u_resolution');\n this.gl.useProgram(this.colorProgram);\n this.gl.uniform1i(this.gl.getUniformLocation(this.colorProgram, 'u_sourceTexture'), 0);\n this.gl.useProgram(this.alphaProgram);\n this.gl.uniform1i(this.gl.getUniformLocation(this.alphaProgram, 'u_sourceTexture'), 0);\n }\n createVertexShader() {\n return this.createShader(this.gl.VERTEX_SHADER, `#version 300 es\n\t\t\tin vec2 a_position;\n\t\t\tin vec2 a_texCoord;\n\t\t\tout vec2 v_texCoord;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tgl_Position = vec4(a_position, 0.0, 1.0);\n\t\t\t\tv_texCoord = a_texCoord;\n\t\t\t}\n\t\t`);\n }\n createColorProgram() {\n const vertexShader = this.createVertexShader();\n // This shader is simple, simply copy the color information while setting alpha to 1\n const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, `#version 300 es\n\t\t\tprecision highp float;\n\t\t\t\n\t\t\tuniform sampler2D u_sourceTexture;\n\t\t\tin vec2 v_texCoord;\n\t\t\tout vec4 fragColor;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec4 source = texture(u_sourceTexture, v_texCoord);\n\t\t\t\tfragColor = vec4(source.rgb, 1.0);\n\t\t\t}\n\t\t`);\n const program = this.gl.createProgram();\n this.gl.attachShader(program, vertexShader);\n this.gl.attachShader(program, fragmentShader);\n this.gl.linkProgram(program);\n return program;\n }\n createAlphaProgram() {\n const vertexShader = this.createVertexShader();\n // This shader's more complex. The main reason is that this shader writes data in I420 (yuv420) pixel format\n // instead of regular RGBA. In other words, we use the shader to write out I420 data into an RGBA canvas, which\n // we then later read out with JavaScript. The reason being that browsers weirdly encode canvases and mess up\n // the color spaces, and the only way to have full control over the color space is by outputting YUV data\n // directly (avoiding the RGB conversion). Doing this conversion in JS is painfully slow, so let's utlize the\n // GPU since we're already calling it anyway.\n const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, `#version 300 es\n\t\t\tprecision highp float;\n\t\t\t\n\t\t\tuniform sampler2D u_sourceTexture;\n\t\t\tuniform vec2 u_resolution; // The width and height of the canvas\n\t\t\tin vec2 v_texCoord;\n\t\t\tout vec4 fragColor;\n\n\t\t\t// This function determines the value for a single byte in the YUV stream\n\t\t\tfloat getByteValue(float byteOffset) {\n\t\t\t\tfloat width = u_resolution.x;\n\t\t\t\tfloat height = u_resolution.y;\n\n\t\t\t\tfloat yPlaneSize = width * height;\n\n\t\t\t\tif (byteOffset < yPlaneSize) {\n\t\t\t\t\t// This byte is in the luma plane. Find the corresponding pixel coordinates to sample from\n\t\t\t\t\tfloat y = floor(byteOffset / width);\n\t\t\t\t\tfloat x = mod(byteOffset, width);\n\t\t\t\t\t\n\t\t\t\t\t// Add 0.5 to sample the center of the texel\n\t\t\t\t\tvec2 sampleCoord = (vec2(x, y) + 0.5) / u_resolution;\n\t\t\t\t\t\n\t\t\t\t\t// The luma value is the alpha from the source texture\n\t\t\t\t\treturn texture(u_sourceTexture, sampleCoord).a;\n\t\t\t\t} else {\n\t\t\t\t\t// Write a fixed value for chroma and beyond\n\t\t\t\t\treturn 128.0 / 255.0;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\t// Each fragment writes 4 bytes (R, G, B, A)\n\t\t\t\tfloat pixelIndex = floor(gl_FragCoord.y) * u_resolution.x + floor(gl_FragCoord.x);\n\t\t\t\tfloat baseByteOffset = pixelIndex * 4.0;\n\n\t\t\t\tvec4 result;\n\t\t\t\tfor (int i = 0; i < 4; i++) {\n\t\t\t\t\tfloat currentByteOffset = baseByteOffset + float(i);\n\t\t\t\t\tresult[i] = getByteValue(currentByteOffset);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfragColor = result;\n\t\t\t}\n\t\t`);\n const program = this.gl.createProgram();\n this.gl.attachShader(program, vertexShader);\n this.gl.attachShader(program, fragmentShader);\n this.gl.linkProgram(program);\n return program;\n }\n createShader(type, source) {\n const shader = this.gl.createShader(type);\n this.gl.shaderSource(shader, source);\n this.gl.compileShader(shader);\n if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n console.error('Shader compile error:', this.gl.getShaderInfoLog(shader));\n }\n return shader;\n }\n createVAO() {\n const vao = this.gl.createVertexArray();\n this.gl.bindVertexArray(vao);\n const vertices = new Float32Array([\n -1, -1, 0, 1,\n 1, -1, 1, 1,\n -1, 1, 0, 0,\n 1, 1, 1, 0,\n ]);\n const buffer = this.gl.createBuffer();\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);\n this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);\n const positionLocation = this.gl.getAttribLocation(this.colorProgram, 'a_position');\n const texCoordLocation = this.gl.getAttribLocation(this.colorProgram, 'a_texCoord');\n this.gl.enableVertexAttribArray(positionLocation);\n this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 16, 0);\n this.gl.enableVertexAttribArray(texCoordLocation);\n this.gl.vertexAttribPointer(texCoordLocation, 2, this.gl.FLOAT, false, 16, 8);\n return vao;\n }\n createTexture() {\n const texture = this.gl.createTexture();\n this.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n return texture;\n }\n updateTexture(sourceFrame) {\n if (this.lastFrame === sourceFrame) {\n return;\n }\n if (sourceFrame.displayWidth !== this.canvas.width || sourceFrame.displayHeight !== this.canvas.height) {\n this.canvas.width = sourceFrame.displayWidth;\n this.canvas.height = sourceFrame.displayHeight;\n }\n this.gl.activeTexture(this.gl.TEXTURE0);\n this.gl.bindTexture(this.gl.TEXTURE_2D, this.sourceTexture);\n this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, sourceFrame);\n this.lastFrame = sourceFrame;\n }\n extractColor(sourceFrame) {\n this.updateTexture(sourceFrame);\n this.gl.useProgram(this.colorProgram);\n this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n this.gl.clear(this.gl.COLOR_BUFFER_BIT);\n this.gl.bindVertexArray(this.vao);\n this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n return new VideoFrame(this.canvas, {\n timestamp: sourceFrame.timestamp,\n duration: sourceFrame.duration ?? undefined,\n alpha: 'discard',\n });\n }\n extractAlpha(sourceFrame) {\n this.updateTexture(sourceFrame);\n this.gl.useProgram(this.alphaProgram);\n this.gl.uniform2f(this.alphaResolutionLocation, this.canvas.width, this.canvas.height);\n this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n this.gl.clear(this.gl.COLOR_BUFFER_BIT);\n this.gl.bindVertexArray(this.vao);\n this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n const { width, height } = this.canvas;\n const chromaSamples = Math.ceil(width / 2) * Math.ceil(height / 2);\n const yuvSize = width * height + chromaSamples * 2;\n const requiredHeight = Math.ceil(yuvSize / (width * 4));\n let yuv = new Uint8Array(4 * width * requiredHeight);\n this.gl.readPixels(0, 0, width, requiredHeight, this.gl.RGBA, this.gl.UNSIGNED_BYTE, yuv);\n yuv = yuv.subarray(0, yuvSize);\n assert(yuv[width * height] === 128); // Where chroma data starts\n assert(yuv[yuv.length - 1] === 128); // Assert the YUV data has been fully written\n // Defining this separately because TypeScript doesn't know `transfer` and I can't be bothered to do declaration\n // merging right now\n const init = {\n format: 'I420',\n codedWidth: width,\n codedHeight: height,\n timestamp: sourceFrame.timestamp,\n duration: sourceFrame.duration ?? undefined,\n transfer: [yuv.buffer],\n };\n return new VideoFrame(yuv, init);\n }\n close() {\n this.gl.getExtension('WEBGL_lose_context')?.loseContext();\n this.gl = null;\n }\n}\n/**\n * This source can be used to add raw, unencoded video samples (frames) to an output video track. These frames will\n * automatically be encoded and then piped into the output.\n * @group Media sources\n * @public\n */\nexport class VideoSampleSource extends VideoSource {\n /**\n * Creates a new {@link VideoSampleSource} whose samples are encoded according to the specified\n * {@link VideoEncodingConfig}.\n */\n constructor(encodingConfig) {\n validateVideoEncodingConfig(encodingConfig);\n super(encodingConfig.codec);\n this._encoder = new VideoEncoderWrapper(this, encodingConfig);\n }\n /**\n * Encodes a video sample (frame) and then adds it to the output.\n *\n * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise\n * to respect writer and encoder backpressure.\n */\n add(videoSample, encodeOptions) {\n if (!(videoSample instanceof VideoSample)) {\n throw new TypeError('videoSample must be a VideoSample.');\n }\n return this._encoder.add(videoSample, false, encodeOptions);\n }\n /** @internal */\n _flushAndClose(forceClose) {\n return this._encoder.flushAndClose(forceClose);\n }\n}\n/**\n * This source can be used to add video frames to the output track from a fixed canvas element. Since canvases are often\n * used for rendering, this source provides a convenient wrapper around {@link VideoSampleSource}.\n * @group Media sources\n * @public\n */\nexport class CanvasSource extends VideoSource {\n /**\n * Creates a new {@link CanvasSource} from a canvas element or `OffscreenCanvas` whose samples are encoded\n * according to the specified {@link VideoEncodingConfig}.\n */\n constructor(canvas, encodingConfig) {\n if (!(typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement)\n && !(typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas)) {\n throw new TypeError('canvas must be an HTMLCanvasElement or OffscreenCanvas.');\n }\n validateVideoEncodingConfig(encodingConfig);\n super(encodingConfig.codec);\n this._encoder = new VideoEncoderWrapper(this, encodingConfig);\n this._canvas = canvas;\n }\n /**\n * Captures the current canvas state as a video sample (frame), encodes it and adds it to the output.\n *\n * @param timestamp - The timestamp of the sample, in seconds.\n * @param duration - The duration of the sample, in seconds.\n *\n * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise\n * to respect writer and encoder backpressure.\n */\n add(timestamp, duration = 0, encodeOptions) {\n if (!Number.isFinite(timestamp) || timestamp < 0) {\n throw new TypeError('timestamp must be a non-negative number.');\n }\n if (!Number.isFinite(duration) || duration < 0) {\n throw new TypeError('duration must be a non-negative number.');\n }\n const sample = new VideoSample(this._canvas, { timestamp, duration });\n return this._encoder.add(sample, true, encodeOptions);\n }\n /** @internal */\n _flushAndClose(forceClose) {\n return this._encoder.flushAndClose(forceClose);\n }\n}\n/**\n * Video source that encodes the frames of a\n * [`MediaStreamVideoTrack`](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack) and pipes them into the\n * output. This is useful for capturing live or real-time data such as webcams or screen captures. Frames will\n * automatically start being captured once the connected {@link Output} is started, and will keep being captured until\n * the {@link Output} is finalized or this source is closed.\n * @group Media sources\n * @public\n */\nexport class MediaStreamVideoTrackSource extends VideoSource {\n /** A promise that rejects upon any error within this source. This promise never resolves. */\n get errorPromise() {\n this._errorPromiseAccessed = true;\n return this._promiseWithResolvers.promise;\n }\n /**\n * Creates a new {@link MediaStreamVideoTrackSource} from a\n * [`MediaStreamVideoTrack`](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack), which will pull\n * video samples from the stream in real time and encode them according to {@link VideoEncodingConfig}.\n */\n constructor(track, encodingConfig) {\n if (!(track instanceof MediaStreamTrack) || track.kind !== 'video') {\n throw new TypeError('track must be a video MediaStreamTrack.');\n }\n validateVideoEncodingConfig(encodingConfig);\n encodingConfig = {\n ...encodingConfig,\n latencyMode: 'realtime',\n };\n super(encodingConfig.codec);\n /** @internal */\n this._abortController = null;\n /** @internal */\n this._workerTrackId = null;\n /** @internal */\n this._workerListener = null;\n /** @internal */\n this._promiseWithResolvers = promiseWithResolvers();\n /** @internal */\n this._errorPromiseAccessed = false;\n this._encoder = new VideoEncoderWrapper(this, encodingConfig);\n this._track = track;\n }\n /** @internal */\n async _start() {\n if (!this._errorPromiseAccessed) {\n console.warn('Make sure not to ignore the `errorPromise` field on MediaStreamVideoTrackSource, so that any internal'\n + ' errors get bubbled up properly.');\n }\n this._abortController = new AbortController();\n let firstVideoFrameTimestamp = null;\n let errored = false;\n const onVideoFrame = (videoFrame) => {\n if (errored) {\n videoFrame.close();\n return;\n }\n if (firstVideoFrameTimestamp === null) {\n firstVideoFrameTimestamp = videoFrame.timestamp / 1e6;\n const muxer = this._connectedTrack.output._muxer;\n if (muxer.firstMediaStreamTimestamp === null) {\n muxer.firstMediaStreamTimestamp = performance.now() / 1000;\n this._timestampOffset = -firstVideoFrameTimestamp;\n }\n else {\n this._timestampOffset = (performance.now() / 1000 - muxer.firstMediaStreamTimestamp)\n - firstVideoFrameTimestamp;\n }\n }\n if (this._encoder.getQueueSize() >= 4) {\n // Drop frames if the encoder is overloaded\n videoFrame.close();\n return;\n }\n void this._encoder.add(new VideoSample(videoFrame), true)\n .catch((error) => {\n errored = true;\n this._abortController?.abort();\n this._promiseWithResolvers.reject(error);\n if (this._workerTrackId !== null) {\n // Tell the worker to stop the track\n sendMessageToMediaStreamTrackProcessorWorker({\n type: 'stopTrack',\n trackId: this._workerTrackId,\n });\n }\n });\n };\n if (typeof MediaStreamTrackProcessor !== 'undefined') {\n // We can do it here directly, perfect\n const processor = new MediaStreamTrackProcessor({ track: this._track });\n const consumer = new WritableStream({ write: onVideoFrame });\n processor.readable.pipeTo(consumer, {\n signal: this._abortController.signal,\n }).catch((error) => {\n // Handle AbortError silently\n if (error instanceof DOMException && error.name === 'AbortError')\n return;\n this._promiseWithResolvers.reject(error);\n });\n }\n else {\n // It might still be supported in a worker, so let's check that\n const supportedInWorker = await mediaStreamTrackProcessorIsSupportedInWorker();\n if (supportedInWorker) {\n this._workerTrackId = nextMediaStreamTrackProcessorWorkerId++;\n sendMessageToMediaStreamTrackProcessorWorker({\n type: 'videoTrack',\n trackId: this._workerTrackId,\n track: this._track,\n });\n this._workerListener = (event) => {\n const message = event.data;\n if (message.type === 'videoFrame' && message.trackId === this._workerTrackId) {\n onVideoFrame(message.videoFrame);\n }\n else if (message.type === 'error' && message.trackId === this._workerTrackId) {\n this._promiseWithResolvers.reject(message.error);\n }\n };\n mediaStreamTrackProcessorWorker.addEventListener('message', this._workerListener);\n }\n else {\n throw new Error('MediaStreamTrackProcessor is required but not supported by this browser.');\n }\n }\n }\n /** @internal */\n async _flushAndClose(forceClose) {\n if (this._abortController) {\n this._abortController.abort();\n this._abortController = null;\n }\n if (this._workerTrackId !== null) {\n assert(this._workerListener);\n sendMessageToMediaStreamTrackProcessorWorker({\n type: 'stopTrack',\n trackId: this._workerTrackId,\n });\n // Wait for the worker to stop the track\n await new Promise((resolve) => {\n const listener = (event) => {\n const message = event.data;\n if (message.type === 'trackStopped' && message.trackId === this._workerTrackId) {\n assert(this._workerListener);\n mediaStreamTrackProcessorWorker.removeEventListener('message', this._workerListener);\n mediaStreamTrackProcessorWorker.removeEventListener('message', listener);\n resolve();\n }\n };\n mediaStreamTrackProcessorWorker.addEventListener('message', listener);\n });\n }\n await this._encoder.flushAndClose(forceClose);\n }\n}\n/**\n * Base class for audio sources - sources for audio tracks.\n * @group Media sources\n * @public\n */\nexport class AudioSource extends MediaSource {\n /** Internal constructor. */\n constructor(codec) {\n super();\n /** @internal */\n this._connectedTrack = null;\n if (!AUDIO_CODECS.includes(codec)) {\n throw new TypeError(`Invalid audio codec '${codec}'. Must be one of: ${AUDIO_CODECS.join(', ')}.`);\n }\n this._codec = codec;\n }\n}\n/**\n * The most basic audio source; can be used to directly pipe encoded packets into the output file.\n * @group Media sources\n * @public\n */\nexport class EncodedAudioPacketSource extends AudioSource {\n /** Creates a new {@link EncodedAudioPacketSource} whose packets are encoded using `codec`. */\n constructor(codec) {\n super(codec);\n }\n /**\n * Adds an encoded packet to the output audio track. Packets must be added in *decode order*.\n *\n * @param meta - Additional metadata from the encoder. You should pass this for the first call, including a valid\n * decoder config.\n *\n * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise\n * to respect writer and encoder backpressure.\n */\n add(packet, meta) {\n if (!(packet instanceof EncodedPacket)) {\n throw new TypeError('packet must be an EncodedPacket.');\n }\n if (packet.isMetadataOnly) {\n throw new TypeError('Metadata-only packets cannot be added.');\n }\n if (meta !== undefined && (!meta || typeof meta !== 'object')) {\n throw new TypeError('meta, when provided, must be an object.');\n }\n this._ensureValidAdd();\n return this._connectedTrack.output._muxer.addEncodedAudioPacket(this._connectedTrack, packet, meta);\n }\n}\nclass AudioEncoderWrapper {\n constructor(source, encodingConfig) {\n this.source = source;\n this.encodingConfig = encodingConfig;\n this.ensureEncoderPromise = null;\n this.encoderInitialized = false;\n this.encoder = null;\n this.muxer = null;\n this.lastNumberOfChannels = null;\n this.lastSampleRate = null;\n this.isPcmEncoder = false;\n this.outputSampleSize = null;\n this.writeOutputValue = null;\n this.customEncoder = null;\n this.customEncoderCallSerializer = new CallSerializer();\n this.customEncoderQueueSize = 0;\n this.lastEndSampleIndex = null;\n /**\n * Encoders typically throw their errors \"out of band\", meaning asynchronously in some other execution context.\n * However, we want to surface these errors to the user within the normal control flow, so they don't go uncaught.\n * So, we keep track of the encoder error and throw it as soon as we get the chance.\n */\n this.error = null;\n this.errorNeedsNewStack = true;\n }\n async add(audioSample, shouldClose) {\n try {\n this.checkForEncoderError();\n this.source._ensureValidAdd();\n // Ensure audio parameters remain constant\n if (this.lastNumberOfChannels !== null && this.lastSampleRate !== null) {\n if (audioSample.numberOfChannels !== this.lastNumberOfChannels\n || audioSample.sampleRate !== this.lastSampleRate) {\n throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at`\n + ` ${this.lastSampleRate} Hz, got ${audioSample.numberOfChannels} channels at`\n + ` ${audioSample.sampleRate} Hz.`);\n }\n }\n else {\n this.lastNumberOfChannels = audioSample.numberOfChannels;\n this.lastSampleRate = audioSample.sampleRate;\n }\n if (!this.encoderInitialized) {\n if (!this.ensureEncoderPromise) {\n this.ensureEncoder(audioSample);\n }\n // No, this \"if\" statement is not useless. Sometimes, the above call to `ensureEncoder` might have\n // synchronously completed and the encoder is already initialized. In this case, we don't need to await\n // the promise anymore. This also fixes nasty async race condition bugs when multiple code paths are\n // calling this method: It's important that the call that initialized the encoder go through this\n // code first.\n if (!this.encoderInitialized) {\n await this.ensureEncoderPromise;\n }\n }\n assert(this.encoderInitialized);\n // Handle padding of gaps with silence to avoid audio drift over time, like in\n // https://github.com/Vanilagy/mediabunny/issues/176\n // TODO An open question is how encoders deal with the first AudioData having a non-zero timestamp, and with\n // AudioDatas that have an overlapping timestamp range.\n {\n const startSampleIndex = Math.round(audioSample.timestamp * audioSample.sampleRate);\n const endSampleIndex = Math.round((audioSample.timestamp + audioSample.duration) * audioSample.sampleRate);\n if (this.lastEndSampleIndex !== null && startSampleIndex > this.lastEndSampleIndex) {\n const sampleCount = startSampleIndex - this.lastEndSampleIndex;\n const fillSample = new AudioSample({\n data: new Float32Array(sampleCount * audioSample.numberOfChannels),\n format: 'f32-planar',\n sampleRate: audioSample.sampleRate,\n numberOfChannels: audioSample.numberOfChannels,\n numberOfFrames: sampleCount,\n timestamp: this.lastEndSampleIndex / audioSample.sampleRate,\n });\n await this.add(fillSample, true); // Recursive call\n }\n this.lastEndSampleIndex = endSampleIndex;\n }\n if (this.customEncoder) {\n this.customEncoderQueueSize++;\n // We clone the sample so it cannot be closed on us from the outside before it reaches the encoder\n const clonedSample = audioSample.clone();\n const promise = this.customEncoderCallSerializer\n .call(() => this.customEncoder.encode(clonedSample))\n .then(() => this.customEncoderQueueSize--)\n .catch((error) => this.error ??= error)\n .finally(() => {\n clonedSample.close();\n // `audioSample` gets closed in the finally block at the end of the method\n });\n if (this.customEncoderQueueSize >= 4) {\n await promise;\n }\n await this.muxer.mutex.currentPromise; // Allow the writer to apply backpressure\n }\n else if (this.isPcmEncoder) {\n await this.doPcmEncoding(audioSample, shouldClose);\n }\n else {\n assert(this.encoder);\n const audioData = audioSample.toAudioData();\n this.encoder.encode(audioData);\n audioData.close();\n if (shouldClose) {\n audioSample.close();\n }\n if (this.encoder.encodeQueueSize >= 4) {\n await new Promise(resolve => this.encoder.addEventListener('dequeue', resolve, { once: true }));\n }\n await this.muxer.mutex.currentPromise; // Allow the writer to apply backpressure\n }\n }\n finally {\n if (shouldClose) {\n // Make sure it's always closed, even if there was an error\n audioSample.close();\n }\n }\n }\n async doPcmEncoding(audioSample, shouldClose) {\n assert(this.outputSampleSize);\n assert(this.writeOutputValue);\n // Need to extract data from the audio data before we close it\n const { numberOfChannels, numberOfFrames, sampleRate, timestamp } = audioSample;\n const CHUNK_SIZE = 2048;\n const outputs = [];\n // Prepare all of the output buffers, each being bounded by CHUNK_SIZE so we don't generate huge packets\n for (let frame = 0; frame < numberOfFrames; frame += CHUNK_SIZE) {\n const frameCount = Math.min(CHUNK_SIZE, audioSample.numberOfFrames - frame);\n const outputSize = frameCount * numberOfChannels * this.outputSampleSize;\n const outputBuffer = new ArrayBuffer(outputSize);\n const outputView = new DataView(outputBuffer);\n outputs.push({ frameCount, view: outputView });\n }\n const allocationSize = audioSample.allocationSize(({ planeIndex: 0, format: 'f32-planar' }));\n const floats = new Float32Array(allocationSize / Float32Array.BYTES_PER_ELEMENT);\n for (let i = 0; i < numberOfChannels; i++) {\n audioSample.copyTo(floats, { planeIndex: i, format: 'f32-planar' });\n for (let j = 0; j < outputs.length; j++) {\n const { frameCount, view } = outputs[j];\n for (let k = 0; k < frameCount; k++) {\n this.writeOutputValue(view, (k * numberOfChannels + i) * this.outputSampleSize, floats[j * CHUNK_SIZE + k]);\n }\n }\n }\n if (shouldClose) {\n audioSample.close();\n }\n const meta = {\n decoderConfig: {\n codec: this.encodingConfig.codec,\n numberOfChannels,\n sampleRate,\n },\n };\n for (let i = 0; i < outputs.length; i++) {\n const { frameCount, view } = outputs[i];\n const outputBuffer = view.buffer;\n const startFrame = i * CHUNK_SIZE;\n const packet = new EncodedPacket(new Uint8Array(outputBuffer), 'key', timestamp + startFrame / sampleRate, frameCount / sampleRate);\n this.encodingConfig.onEncodedPacket?.(packet, meta);\n await this.muxer.addEncodedAudioPacket(this.source._connectedTrack, packet, meta); // With backpressure\n }\n }\n ensureEncoder(audioSample) {\n const encoderError = new Error();\n this.ensureEncoderPromise = (async () => {\n const { numberOfChannels, sampleRate } = audioSample;\n const encoderConfig = buildAudioEncoderConfig({\n numberOfChannels,\n sampleRate,\n ...this.encodingConfig,\n });\n this.encodingConfig.onEncoderConfig?.(encoderConfig);\n const MatchingCustomEncoder = customAudioEncoders.find(x => x.supports(this.encodingConfig.codec, encoderConfig));\n if (MatchingCustomEncoder) {\n // @ts-expect-error \"Can't create instance of abstract class 🤓\"\n this.customEncoder = new MatchingCustomEncoder();\n // @ts-expect-error It's technically readonly\n this.customEncoder.codec = this.encodingConfig.codec;\n // @ts-expect-error It's technically readonly\n this.customEncoder.config = encoderConfig;\n // @ts-expect-error It's technically readonly\n this.customEncoder.onPacket = (packet, meta) => {\n if (!(packet instanceof EncodedPacket)) {\n throw new TypeError('The first argument passed to onPacket must be an EncodedPacket.');\n }\n if (meta !== undefined && (!meta || typeof meta !== 'object')) {\n throw new TypeError('The second argument passed to onPacket must be an object or undefined.');\n }\n this.encodingConfig.onEncodedPacket?.(packet, meta);\n void this.muxer.addEncodedAudioPacket(this.source._connectedTrack, packet, meta)\n .catch((error) => {\n this.error ??= error;\n this.errorNeedsNewStack = false;\n });\n };\n await this.customEncoder.init();\n }\n else if (PCM_AUDIO_CODECS.includes(this.encodingConfig.codec)) {\n this.initPcmEncoder();\n }\n else {\n if (typeof AudioEncoder === 'undefined') {\n throw new Error('AudioEncoder is not supported by this browser.');\n }\n const support = await AudioEncoder.isConfigSupported(encoderConfig);\n if (!support.supported) {\n throw new Error(`This specific encoder configuration (${encoderConfig.codec}, ${encoderConfig.bitrate} bps,`\n + ` ${encoderConfig.numberOfChannels} channels, ${encoderConfig.sampleRate} Hz) is not`\n + ` supported by this browser. Consider using another codec or changing your audio parameters.`);\n }\n this.encoder = new AudioEncoder({\n output: (chunk, meta) => {\n // WebKit emits an invalid description for AAC (https://bugs.webkit.org/show_bug.cgi?id=302253),\n // which we try to detect here. If detected, we'll provide our own description instead, derived\n // from the codec string and audio parameters.\n if (this.encodingConfig.codec === 'aac' && meta?.decoderConfig) {\n let needsDescriptionOverwrite = false;\n if (!meta.decoderConfig.description || meta.decoderConfig.description.byteLength < 2) {\n needsDescriptionOverwrite = true;\n }\n else {\n const audioSpecificConfig = parseAacAudioSpecificConfig(toUint8Array(meta.decoderConfig.description));\n needsDescriptionOverwrite = audioSpecificConfig.objectType === 0;\n }\n if (needsDescriptionOverwrite) {\n const objectType = Number(last(encoderConfig.codec.split('.')));\n meta.decoderConfig.description = buildAacAudioSpecificConfig({\n objectType,\n numberOfChannels: meta.decoderConfig.numberOfChannels,\n sampleRate: meta.decoderConfig.sampleRate,\n });\n }\n }\n const packet = EncodedPacket.fromEncodedChunk(chunk);\n this.encodingConfig.onEncodedPacket?.(packet, meta);\n void this.muxer.addEncodedAudioPacket(this.source._connectedTrack, packet, meta)\n .catch((error) => {\n this.error ??= error;\n this.errorNeedsNewStack = false;\n });\n },\n error: (error) => {\n error.stack = encoderError.stack; // Provide a more useful stack trace\n this.error ??= error;\n },\n });\n this.encoder.configure(encoderConfig);\n }\n assert(this.source._connectedTrack);\n this.muxer = this.source._connectedTrack.output._muxer;\n this.encoderInitialized = true;\n })();\n }\n initPcmEncoder() {\n this.isPcmEncoder = true;\n const codec = this.encodingConfig.codec;\n const { dataType, sampleSize, littleEndian } = parsePcmCodec(codec);\n this.outputSampleSize = sampleSize;\n // All these functions receive a float sample as input and map it into the desired format\n switch (sampleSize) {\n case 1:\n {\n if (dataType === 'unsigned') {\n this.writeOutputValue = (view, byteOffset, value) => view.setUint8(byteOffset, clamp((value + 1) * 127.5, 0, 255));\n }\n else if (dataType === 'signed') {\n this.writeOutputValue = (view, byteOffset, value) => {\n view.setInt8(byteOffset, clamp(Math.round(value * 128), -128, 127));\n };\n }\n else if (dataType === 'ulaw') {\n this.writeOutputValue = (view, byteOffset, value) => {\n const int16 = clamp(Math.floor(value * 32767), -32768, 32767);\n view.setUint8(byteOffset, toUlaw(int16));\n };\n }\n else if (dataType === 'alaw') {\n this.writeOutputValue = (view, byteOffset, value) => {\n const int16 = clamp(Math.floor(value * 32767), -32768, 32767);\n view.setUint8(byteOffset, toAlaw(int16));\n };\n }\n else {\n assert(false);\n }\n }\n ;\n break;\n case 2:\n {\n if (dataType === 'unsigned') {\n this.writeOutputValue = (view, byteOffset, value) => view.setUint16(byteOffset, clamp((value + 1) * 32767.5, 0, 65535), littleEndian);\n }\n else if (dataType === 'signed') {\n this.writeOutputValue = (view, byteOffset, value) => view.setInt16(byteOffset, clamp(Math.round(value * 32767), -32768, 32767), littleEndian);\n }\n else {\n assert(false);\n }\n }\n ;\n break;\n case 3:\n {\n if (dataType === 'unsigned') {\n this.writeOutputValue = (view, byteOffset, value) => setUint24(view, byteOffset, clamp((value + 1) * 8388607.5, 0, 16777215), littleEndian);\n }\n else if (dataType === 'signed') {\n this.writeOutputValue = (view, byteOffset, value) => setInt24(view, byteOffset, clamp(Math.round(value * 8388607), -8388608, 8388607), littleEndian);\n }\n else {\n assert(false);\n }\n }\n ;\n break;\n case 4:\n {\n if (dataType === 'unsigned') {\n this.writeOutputValue = (view, byteOffset, value) => view.setUint32(byteOffset, clamp((value + 1) * 2147483647.5, 0, 4294967295), littleEndian);\n }\n else if (dataType === 'signed') {\n this.writeOutputValue = (view, byteOffset, value) => view.setInt32(byteOffset, clamp(Math.round(value * 2147483647), -2147483648, 2147483647), littleEndian);\n }\n else if (dataType === 'float') {\n this.writeOutputValue = (view, byteOffset, value) => view.setFloat32(byteOffset, value, littleEndian);\n }\n else {\n assert(false);\n }\n }\n ;\n break;\n case 8:\n {\n if (dataType === 'float') {\n this.writeOutputValue = (view, byteOffset, value) => view.setFloat64(byteOffset, value, littleEndian);\n }\n else {\n assert(false);\n }\n }\n ;\n break;\n default:\n {\n assertNever(sampleSize);\n assert(false);\n }\n ;\n }\n }\n async flushAndClose(forceClose) {\n if (!forceClose)\n this.checkForEncoderError();\n if (this.customEncoder) {\n if (!forceClose) {\n void this.customEncoderCallSerializer.call(() => this.customEncoder.flush());\n }\n await this.customEncoderCallSerializer.call(() => this.customEncoder.close());\n }\n else if (this.encoder) {\n if (!forceClose) {\n await this.encoder.flush();\n }\n if (this.encoder.state !== 'closed') {\n this.encoder.close();\n }\n }\n if (!forceClose)\n this.checkForEncoderError();\n }\n getQueueSize() {\n if (this.customEncoder) {\n return this.customEncoderQueueSize;\n }\n else if (this.isPcmEncoder) {\n return 0;\n }\n else {\n return this.encoder?.encodeQueueSize ?? 0;\n }\n }\n checkForEncoderError() {\n if (this.error) {\n if (this.errorNeedsNewStack) {\n this.error.stack = new Error().stack; // Provide an even more useful stack trace\n }\n throw this.error;\n }\n }\n}\n/**\n * This source can be used to add raw, unencoded audio samples to an output audio track. These samples will\n * automatically be encoded and then piped into the output.\n * @group Media sources\n * @public\n */\nexport class AudioSampleSource extends AudioSource {\n /**\n * Creates a new {@link AudioSampleSource} whose samples are encoded according to the specified\n * {@link AudioEncodingConfig}.\n */\n constructor(encodingConfig) {\n validateAudioEncodingConfig(encodingConfig);\n super(encodingConfig.codec);\n this._encoder = new AudioEncoderWrapper(this, encodingConfig);\n }\n /**\n * Encodes an audio sample and then adds it to the output.\n *\n * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise\n * to respect writer and encoder backpressure.\n */\n add(audioSample) {\n if (!(audioSample instanceof AudioSample)) {\n throw new TypeError('audioSample must be an AudioSample.');\n }\n return this._encoder.add(audioSample, false);\n }\n /** @internal */\n _flushAndClose(forceClose) {\n return this._encoder.flushAndClose(forceClose);\n }\n}\n/**\n * This source can be used to add audio data from an AudioBuffer to the output track. This is useful when working with\n * the Web Audio API.\n * @group Media sources\n * @public\n */\nexport class AudioBufferSource extends AudioSource {\n /**\n * Creates a new {@link AudioBufferSource} whose `AudioBuffer` instances are encoded according to the specified\n * {@link AudioEncodingConfig}.\n */\n constructor(encodingConfig) {\n validateAudioEncodingConfig(encodingConfig);\n super(encodingConfig.codec);\n /** @internal */\n this._accumulatedTime = 0;\n this._encoder = new AudioEncoderWrapper(this, encodingConfig);\n }\n /**\n * Converts an AudioBuffer to audio samples, encodes them and adds them to the output. The first AudioBuffer will\n * be played at timestamp 0, and any subsequent AudioBuffer will have a timestamp equal to the total duration of\n * all previous AudioBuffers.\n *\n * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise\n * to respect writer and encoder backpressure.\n */\n async add(audioBuffer) {\n if (!(audioBuffer instanceof AudioBuffer)) {\n throw new TypeError('audioBuffer must be an AudioBuffer.');\n }\n const iterator = AudioSample._fromAudioBuffer(audioBuffer, this._accumulatedTime);\n this._accumulatedTime += audioBuffer.duration;\n for (const audioSample of iterator) {\n await this._encoder.add(audioSample, true);\n }\n }\n /** @internal */\n _flushAndClose(forceClose) {\n return this._encoder.flushAndClose(forceClose);\n }\n}\n/**\n * Audio source that encodes the data of a\n * [`MediaStreamAudioTrack`](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack) and pipes it into the\n * output. This is useful for capturing live or real-time audio such as microphones or audio from other media elements.\n * Audio will automatically start being captured once the connected {@link Output} is started, and will keep being\n * captured until the {@link Output} is finalized or this source is closed.\n * @group Media sources\n * @public\n */\nexport class MediaStreamAudioTrackSource extends AudioSource {\n /** A promise that rejects upon any error within this source. This promise never resolves. */\n get errorPromise() {\n this._errorPromiseAccessed = true;\n return this._promiseWithResolvers.promise;\n }\n /**\n * Creates a new {@link MediaStreamAudioTrackSource} from a `MediaStreamAudioTrack`, which will pull audio samples\n * from the stream in real time and encode them according to {@link AudioEncodingConfig}.\n */\n constructor(track, encodingConfig) {\n if (!(track instanceof MediaStreamTrack) || track.kind !== 'audio') {\n throw new TypeError('track must be an audio MediaStreamTrack.');\n }\n validateAudioEncodingConfig(encodingConfig);\n super(encodingConfig.codec);\n /** @internal */\n this._abortController = null;\n /** @internal */\n this._audioContext = null;\n /** @internal */\n this._scriptProcessorNode = null; // Deprecated but goated\n /** @internal */\n this._promiseWithResolvers = promiseWithResolvers();\n /** @internal */\n this._errorPromiseAccessed = false;\n this._encoder = new AudioEncoderWrapper(this, encodingConfig);\n this._track = track;\n }\n /** @internal */\n async _start() {\n if (!this._errorPromiseAccessed) {\n console.warn('Make sure not to ignore the `errorPromise` field on MediaStreamVideoTrackSource, so that any internal'\n + ' errors get bubbled up properly.');\n }\n this._abortController = new AbortController();\n if (typeof MediaStreamTrackProcessor !== 'undefined') {\n // Great, MediaStreamTrackProcessor is supported, this is the preferred way of doing things\n let firstAudioDataTimestamp = null;\n const processor = new MediaStreamTrackProcessor({ track: this._track });\n const consumer = new WritableStream({\n write: (audioData) => {\n if (firstAudioDataTimestamp === null) {\n firstAudioDataTimestamp = audioData.timestamp / 1e6;\n const muxer = this._connectedTrack.output._muxer;\n if (muxer.firstMediaStreamTimestamp === null) {\n muxer.firstMediaStreamTimestamp = performance.now() / 1000;\n this._timestampOffset = -firstAudioDataTimestamp;\n }\n else {\n this._timestampOffset = (performance.now() / 1000 - muxer.firstMediaStreamTimestamp)\n - firstAudioDataTimestamp;\n }\n }\n if (this._encoder.getQueueSize() >= 4) {\n // Drop data if the encoder is overloaded\n audioData.close();\n return;\n }\n void this._encoder.add(new AudioSample(audioData), true)\n .catch((error) => {\n this._abortController?.abort();\n this._promiseWithResolvers.reject(error);\n });\n },\n });\n processor.readable.pipeTo(consumer, {\n signal: this._abortController.signal,\n }).catch((error) => {\n // Handle AbortError silently\n if (error instanceof DOMException && error.name === 'AbortError')\n return;\n this._promiseWithResolvers.reject(error);\n });\n }\n else {\n // Let's fall back to an AudioContext approach\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n const AudioContext = window.AudioContext || window.webkitAudioContext;\n this._audioContext = new AudioContext({ sampleRate: this._track.getSettings().sampleRate });\n const sourceNode = this._audioContext.createMediaStreamSource(new MediaStream([this._track]));\n this._scriptProcessorNode = this._audioContext.createScriptProcessor(4096);\n if (this._audioContext.state === 'suspended') {\n await this._audioContext.resume();\n }\n sourceNode.connect(this._scriptProcessorNode);\n this._scriptProcessorNode.connect(this._audioContext.destination);\n let audioReceived = false;\n let totalDuration = 0;\n this._scriptProcessorNode.onaudioprocess = (event) => {\n const iterator = AudioSample._fromAudioBuffer(event.inputBuffer, totalDuration);\n totalDuration += event.inputBuffer.duration;\n for (const audioSample of iterator) {\n if (!audioReceived) {\n audioReceived = true;\n const muxer = this._connectedTrack.output._muxer;\n if (muxer.firstMediaStreamTimestamp === null) {\n muxer.firstMediaStreamTimestamp = performance.now() / 1000;\n }\n else {\n this._timestampOffset = performance.now() / 1000 - muxer.firstMediaStreamTimestamp;\n }\n }\n if (this._encoder.getQueueSize() >= 4) {\n // Drop data if the encoder is overloaded\n audioSample.close();\n continue;\n }\n void this._encoder.add(audioSample, true)\n .catch((error) => {\n void this._audioContext.suspend();\n this._promiseWithResolvers.reject(error);\n });\n }\n };\n }\n }\n /** @internal */\n async _flushAndClose(forceClose) {\n if (this._abortController) {\n this._abortController.abort();\n this._abortController = null;\n }\n if (this._audioContext) {\n assert(this._scriptProcessorNode);\n this._scriptProcessorNode.disconnect();\n await this._audioContext.suspend();\n }\n await this._encoder.flushAndClose(forceClose);\n }\n}\nconst mediaStreamTrackProcessorWorkerCode = () => {\n const sendMessage = (message, transfer) => {\n if (transfer) {\n self.postMessage(message, { transfer });\n }\n else {\n self.postMessage(message);\n }\n };\n // Immediately send a message to the main thread, letting them know of the support\n sendMessage({\n type: 'support',\n supported: typeof MediaStreamTrackProcessor !== 'undefined',\n });\n const abortControllers = new Map();\n const activeTracks = new Map();\n self.addEventListener('message', (event) => {\n const message = event.data;\n switch (message.type) {\n case 'videoTrack':\n {\n activeTracks.set(message.trackId, message.track);\n const processor = new MediaStreamTrackProcessor({ track: message.track });\n const consumer = new WritableStream({\n write: (videoFrame) => {\n if (!activeTracks.has(message.trackId)) {\n videoFrame.close();\n return;\n }\n // Send it to the main thread\n sendMessage({\n type: 'videoFrame',\n trackId: message.trackId,\n videoFrame,\n }, [videoFrame]);\n },\n });\n const abortController = new AbortController();\n abortControllers.set(message.trackId, abortController);\n processor.readable.pipeTo(consumer, {\n signal: abortController.signal,\n }).catch((error) => {\n // Handle AbortError silently\n if (error instanceof DOMException && error.name === 'AbortError')\n return;\n sendMessage({\n type: 'error',\n trackId: message.trackId,\n error,\n });\n });\n }\n ;\n break;\n case 'stopTrack':\n {\n const abortController = abortControllers.get(message.trackId);\n if (abortController) {\n abortController.abort();\n abortControllers.delete(message.trackId);\n }\n const track = activeTracks.get(message.trackId);\n track?.stop();\n activeTracks.delete(message.trackId);\n sendMessage({\n type: 'trackStopped',\n trackId: message.trackId,\n });\n }\n ;\n break;\n default: assertNever(message);\n }\n });\n};\nlet nextMediaStreamTrackProcessorWorkerId = 0;\nlet mediaStreamTrackProcessorWorker = null;\nconst initMediaStreamTrackProcessorWorker = () => {\n const blob = new Blob([`(${mediaStreamTrackProcessorWorkerCode.toString()})()`], { type: 'application/javascript' });\n const url = URL.createObjectURL(blob);\n mediaStreamTrackProcessorWorker = new Worker(url);\n};\nlet mediaStreamTrackProcessorIsSupportedInWorkerCache = null;\nconst mediaStreamTrackProcessorIsSupportedInWorker = async () => {\n if (mediaStreamTrackProcessorIsSupportedInWorkerCache !== null) {\n return mediaStreamTrackProcessorIsSupportedInWorkerCache;\n }\n if (!mediaStreamTrackProcessorWorker) {\n initMediaStreamTrackProcessorWorker();\n }\n return new Promise((resolve) => {\n assert(mediaStreamTrackProcessorWorker);\n const listener = (event) => {\n const message = event.data;\n if (message.type === 'support') {\n mediaStreamTrackProcessorIsSupportedInWorkerCache = message.supported;\n mediaStreamTrackProcessorWorker.removeEventListener('message', listener);\n resolve(message.supported);\n }\n };\n mediaStreamTrackProcessorWorker.addEventListener('message', listener);\n });\n};\nconst sendMessageToMediaStreamTrackProcessorWorker = (message, transfer) => {\n assert(mediaStreamTrackProcessorWorker);\n if (transfer) {\n mediaStreamTrackProcessorWorker.postMessage(message, transfer);\n }\n else {\n mediaStreamTrackProcessorWorker.postMessage(message);\n }\n};\n/**\n * Base class for subtitle sources - sources for subtitle tracks.\n * @group Media sources\n * @public\n */\nexport class SubtitleSource extends MediaSource {\n /** Internal constructor. */\n constructor(codec) {\n super();\n /** @internal */\n this._connectedTrack = null;\n if (!SUBTITLE_CODECS.includes(codec)) {\n throw new TypeError(`Invalid subtitle codec '${codec}'. Must be one of: ${SUBTITLE_CODECS.join(', ')}.`);\n }\n this._codec = codec;\n }\n}\n/**\n * This source can be used to add subtitles from a subtitle text file.\n * @group Media sources\n * @public\n */\nexport class TextSubtitleSource extends SubtitleSource {\n /** Creates a new {@link TextSubtitleSource} where added text chunks are in the specified `codec`. */\n constructor(codec) {\n super(codec);\n /** @internal */\n this._error = null;\n this._parser = new SubtitleParser({\n codec,\n output: (cue, metadata) => {\n void this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack, cue, metadata)\n .catch((error) => {\n this._error ??= error;\n });\n },\n });\n }\n /**\n * Parses the subtitle text according to the specified codec and adds it to the output track. You don't have to\n * add the entire subtitle file at once here; you can provide it in chunks.\n *\n * @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise\n * to respect writer and encoder backpressure.\n */\n add(text) {\n if (typeof text !== 'string') {\n throw new TypeError('text must be a string.');\n }\n this._checkForError();\n this._ensureValidAdd();\n this._parser.parse(text);\n return this._connectedTrack.output._muxer.mutex.currentPromise;\n }\n /** @internal */\n _checkForError() {\n if (this._error) {\n throw this._error;\n }\n }\n /** @internal */\n async _flushAndClose(forceClose) {\n if (!forceClose) {\n this._checkForError();\n }\n }\n}\n","/*!\n * Copyright (c) 2025-present, Vanilagy and contributors\n *\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport { AsyncMutex, isIso639Dash2LanguageCode } from './misc.js';\nimport { validateMetadataTags, validateTrackDisposition } from './metadata.js';\nimport { OutputFormat } from './output-format.js';\nimport { AudioSource, SubtitleSource, VideoSource } from './media-source.js';\nimport { Target } from './target.js';\n/**\n * List of all track types.\n * @group Miscellaneous\n * @public\n */\nexport const ALL_TRACK_TYPES = ['video', 'audio', 'subtitle'];\nconst validateBaseTrackMetadata = (metadata) => {\n if (!metadata || typeof metadata !== 'object') {\n throw new TypeError('metadata must be an object.');\n }\n if (metadata.languageCode !== undefined && !isIso639Dash2LanguageCode(metadata.languageCode)) {\n throw new TypeError('metadata.languageCode, when provided, must be a three-letter, ISO 639-2/T language code.');\n }\n if (metadata.name !== undefined && typeof metadata.name !== 'string') {\n throw new TypeError('metadata.name, when provided, must be a string.');\n }\n if (metadata.disposition !== undefined) {\n validateTrackDisposition(metadata.disposition);\n }\n if (metadata.maximumPacketCount !== undefined\n && (!Number.isInteger(metadata.maximumPacketCount) || metadata.maximumPacketCount < 0)) {\n throw new TypeError('metadata.maximumPacketCount, when provided, must be a non-negative integer.');\n }\n};\n/**\n * Main class orchestrating the creation of a new media file.\n * @group Output files\n * @public\n */\nexport class Output {\n /**\n * Creates a new instance of {@link Output} which can then be used to create a new media file according to the\n * specified {@link OutputOptions}.\n */\n constructor(options) {\n /** The current state of the output. */\n this.state = 'pending';\n /** @internal */\n this._tracks = [];\n /** @internal */\n this._startPromise = null;\n /** @internal */\n this._cancelPromise = null;\n /** @internal */\n this._finalizePromise = null;\n /** @internal */\n this._mutex = new AsyncMutex();\n /** @internal */\n this._metadataTags = {};\n if (!options || typeof options !== 'object') {\n throw new TypeError('options must be an object.');\n }\n if (!(options.format instanceof OutputFormat)) {\n throw new TypeError('options.format must be an OutputFormat.');\n }\n if (!(options.target instanceof Target)) {\n throw new TypeError('options.target must be a Target.');\n }\n if (options.target._output) {\n throw new Error('Target is already used for another output.');\n }\n options.target._output = this;\n this.format = options.format;\n this.target = options.target;\n this._writer = options.target._createWriter();\n this._muxer = options.format._createMuxer(this);\n }\n /** Adds a video track to the output with the given source. Can only be called before the output is started. */\n addVideoTrack(source, metadata = {}) {\n if (!(source instanceof VideoSource)) {\n throw new TypeError('source must be a VideoSource.');\n }\n validateBaseTrackMetadata(metadata);\n if (metadata.rotation !== undefined && ![0, 90, 180, 270].includes(metadata.rotation)) {\n throw new TypeError(`Invalid video rotation: ${metadata.rotation}. Has to be 0, 90, 180 or 270.`);\n }\n if (!this.format.supportsVideoRotationMetadata && metadata.rotation) {\n throw new Error(`${this.format._name} does not support video rotation metadata.`);\n }\n if (metadata.frameRate !== undefined\n && (!Number.isFinite(metadata.frameRate) || metadata.frameRate <= 0)) {\n throw new TypeError(`Invalid video frame rate: ${metadata.frameRate}. Must be a positive number.`);\n }\n this._addTrack('video', source, metadata);\n }\n /** Adds an audio track to the output with the given source. Can only be called before the output is started. */\n addAudioTrack(source, metadata = {}) {\n if (!(source instanceof AudioSource)) {\n throw new TypeError('source must be an AudioSource.');\n }\n validateBaseTrackMetadata(metadata);\n this._addTrack('audio', source, metadata);\n }\n /** Adds a subtitle track to the output with the given source. Can only be called before the output is started. */\n addSubtitleTrack(source, metadata = {}) {\n if (!(source instanceof SubtitleSource)) {\n throw new TypeError('source must be a SubtitleSource.');\n }\n validateBaseTrackMetadata(metadata);\n this._addTrack('subtitle', source, metadata);\n }\n /**\n * Sets descriptive metadata tags about the media file, such as title, author, date, or cover art. When called\n * multiple times, only the metadata from the last call will be used.\n *\n * Can only be called before the output is started.\n */\n setMetadataTags(tags) {\n validateMetadataTags(tags);\n if (this.state !== 'pending') {\n throw new Error('Cannot set metadata tags after output has been started or canceled.');\n }\n this._metadataTags = tags;\n }\n /** @internal */\n _addTrack(type, source, metadata) {\n if (this.state !== 'pending') {\n throw new Error('Cannot add track after output has been started or canceled.');\n }\n if (source._connectedTrack) {\n throw new Error('Source is already used for a track.');\n }\n // Verify maximum track count constraints\n const supportedTrackCounts = this.format.getSupportedTrackCounts();\n const presentTracksOfThisType = this._tracks.reduce((count, track) => count + (track.type === type ? 1 : 0), 0);\n const maxCount = supportedTrackCounts[type].max;\n if (presentTracksOfThisType === maxCount) {\n throw new Error(maxCount === 0\n ? `${this.format._name} does not support ${type} tracks.`\n : (`${this.format._name} does not support more than ${maxCount} ${type} track`\n + `${maxCount === 1 ? '' : 's'}.`));\n }\n const maxTotalCount = supportedTrackCounts.total.max;\n if (this._tracks.length === maxTotalCount) {\n throw new Error(`${this.format._name} does not support more than ${maxTotalCount} tracks`\n + `${maxTotalCount === 1 ? '' : 's'} in total.`);\n }\n const track = {\n id: this._tracks.length + 1,\n output: this,\n type,\n source: source,\n metadata,\n };\n if (track.type === 'video') {\n const supportedVideoCodecs = this.format.getSupportedVideoCodecs();\n if (supportedVideoCodecs.length === 0) {\n throw new Error(`${this.format._name} does not support video tracks.`\n + this.format._codecUnsupportedHint(track.source._codec));\n }\n else if (!supportedVideoCodecs.includes(track.source._codec)) {\n throw new Error(`Codec '${track.source._codec}' cannot be contained within ${this.format._name}. Supported`\n + ` video codecs are: ${supportedVideoCodecs.map(codec => `'${codec}'`).join(', ')}.`\n + this.format._codecUnsupportedHint(track.source._codec));\n }\n }\n else if (track.type === 'audio') {\n const supportedAudioCodecs = this.format.getSupportedAudioCodecs();\n if (supportedAudioCodecs.length === 0) {\n throw new Error(`${this.format._name} does not support audio tracks.`\n + this.format._codecUnsupportedHint(track.source._codec));\n }\n else if (!supportedAudioCodecs.includes(track.source._codec)) {\n throw new Error(`Codec '${track.source._codec}' cannot be contained within ${this.format._name}. Supported`\n + ` audio codecs are: ${supportedAudioCodecs.map(codec => `'${codec}'`).join(', ')}.`\n + this.format._codecUnsupportedHint(track.source._codec));\n }\n }\n else if (track.type === 'subtitle') {\n const supportedSubtitleCodecs = this.format.getSupportedSubtitleCodecs();\n if (supportedSubtitleCodecs.length === 0) {\n throw new Error(`${this.format._name} does not support subtitle tracks.`\n + this.format._codecUnsupportedHint(track.source._codec));\n }\n else if (!supportedSubtitleCodecs.includes(track.source._codec)) {\n throw new Error(`Codec '${track.source._codec}' cannot be contained within ${this.format._name}. Supported`\n + ` subtitle codecs are: ${supportedSubtitleCodecs.map(codec => `'${codec}'`).join(', ')}.`\n + this.format._codecUnsupportedHint(track.source._codec));\n }\n }\n this._tracks.push(track);\n source._connectedTrack = track;\n }\n /**\n * Starts the creation of the output file. This method should be called after all tracks have been added. Only after\n * the output has started can media samples be added to the tracks.\n *\n * @returns A promise that resolves when the output has successfully started and is ready to receive media samples.\n */\n async start() {\n // Verify minimum track count constraints\n const supportedTrackCounts = this.format.getSupportedTrackCounts();\n for (const trackType of ALL_TRACK_TYPES) {\n const presentTracksOfThisType = this._tracks.reduce((count, track) => count + (track.type === trackType ? 1 : 0), 0);\n const minCount = supportedTrackCounts[trackType].min;\n if (presentTracksOfThisType < minCount) {\n throw new Error(minCount === supportedTrackCounts[trackType].max\n ? (`${this.format._name} requires exactly ${minCount} ${trackType}`\n + ` track${minCount === 1 ? '' : 's'}.`)\n : (`${this.format._name} requires at least ${minCount} ${trackType}`\n + ` track${minCount === 1 ? '' : 's'}.`));\n }\n }\n const totalMinCount = supportedTrackCounts.total.min;\n if (this._tracks.length < totalMinCount) {\n throw new Error(totalMinCount === supportedTrackCounts.total.max\n ? (`${this.format._name} requires exactly ${totalMinCount} track`\n + `${totalMinCount === 1 ? '' : 's'}.`)\n : (`${this.format._name} requires at least ${totalMinCount} track`\n + `${totalMinCount === 1 ? '' : 's'}.`));\n }\n if (this.state === 'canceled') {\n throw new Error('Output has been canceled.');\n }\n if (this._startPromise) {\n console.warn('Output has already been started.');\n return this._startPromise;\n }\n return this._startPromise = (async () => {\n this.state = 'started';\n this._writer.start();\n const release = await this._mutex.acquire();\n await this._muxer.start();\n const promises = this._tracks.map(track => track.source._start());\n await Promise.all(promises);\n release();\n })();\n }\n /**\n * Resolves with the full MIME type of the output file, including track codecs.\n *\n * The returned promise will resolve only once the precise codec strings of all tracks are known.\n */\n getMimeType() {\n return this._muxer.getMimeType();\n }\n /**\n * Cancels the creation of the output file, releasing internal resources like encoders and preventing further\n * samples from being added.\n *\n * @returns A promise that resolves once all internal resources have been released.\n */\n async cancel() {\n if (this._cancelPromise) {\n console.warn('Output has already been canceled.');\n return this._cancelPromise;\n }\n else if (this.state === 'finalizing' || this.state === 'finalized') {\n console.warn('Output has already been finalized.');\n return;\n }\n return this._cancelPromise = (async () => {\n this.state = 'canceled';\n const release = await this._mutex.acquire();\n const promises = this._tracks.map(x => x.source._flushOrWaitForOngoingClose(true)); // Force close\n await Promise.all(promises);\n await this._writer.close();\n release();\n })();\n }\n /**\n * Finalizes the output file. This method must be called after all media samples across all tracks have been added.\n * Once the Promise returned by this method completes, the output file is ready.\n */\n async finalize() {\n if (this.state === 'pending') {\n throw new Error('Cannot finalize before starting.');\n }\n if (this.state === 'canceled') {\n throw new Error('Cannot finalize after canceling.');\n }\n if (this._finalizePromise) {\n console.warn('Output has already been finalized.');\n return this._finalizePromise;\n }\n return this._finalizePromise = (async () => {\n this.state = 'finalizing';\n const release = await this._mutex.acquire();\n const promises = this._tracks.map(x => x.source._flushOrWaitForOngoingClose(false));\n await Promise.all(promises);\n await this._muxer.finalize();\n await this._writer.flush();\n await this._writer.finalize();\n this.state = 'finalized';\n release();\n })();\n }\n}\n","import {\n Output,\n Mp4OutputFormat,\n BufferTarget,\n EncodedPacket,\n EncodedVideoPacketSource,\n EncodedAudioPacketSource,\n WebMOutputFormat,\n} from 'mediabunny';\nimport { AudioChunk } from './decoder';\n\nexport enum EncoderType {\n INIT = 0,\n FRAME = 1,\n END = 2, // 数据结束,可以输出视频\n}\n\nexport enum EncoderEvent {\n PROGRESS = 0,\n FINISH = 1,\n ERROR = 2,\n}\n\nlet videoEncoder: VideoEncoder | undefined;\nlet audioEncoder: AudioEncoder | undefined;\nlet output: Output | undefined;\nlet videoSource: EncodedVideoPacketSource | undefined;\nlet audioSource: EncodedAudioPacketSource | undefined;\nlet offlineContext: OfflineAudioContext | undefined;\nlet didVideo = false;\nlet didAudio = false;\nlet onFrame: (value: unknown) => void;\nconst masterChannels: Float32Array[] = []; // 音频混合缓冲区\nlet lastIndex = 0;\nlet lastTimestamp = 0;\nlet masterOffset = 0;\n\nexport const onMessage = async (e: MessageEvent<{\n type: EncoderType,\n messageId: number,\n isWorker: boolean,\n timestamp: number,\n duration: number,\n videoFrame: VideoFrame,\n videoEncoderConfig: VideoEncoderConfig,\n audioList: { audioChunk: AudioChunk, volume: number }[],\n audioEncoderConfig: AudioEncoderConfig,\n mute: boolean,\n}>) => {\n const { type, isWorker } = e.data;\n // console.log('encoder', type, isWorker, e.data.messageId);\n const onError = (e: string) => {\n const res = {\n type: EncoderEvent.ERROR,\n error: e,\n };\n if (isWorker) {\n self.postMessage(res);\n }\n return { data: res };\n };\n const pm = new Promise(resolve => {\n onFrame = resolve;\n });\n if (type === EncoderType.INIT) {\n if (videoEncoder) {\n videoEncoder.close();\n videoEncoder = undefined;\n }\n if (audioEncoder) {\n audioEncoder.close();\n audioEncoder = undefined;\n }\n if (offlineContext) {\n offlineContext = undefined;\n }\n const fin = () => {\n if (didVideo && didAudio) {\n const res = {\n type: EncoderEvent.PROGRESS,\n };\n if (isWorker) {\n self.postMessage(res);\n }\n onFrame({ data: res });\n }\n };\n const vc = e.data.videoEncoderConfig?.codec;\n let format: Mp4OutputFormat | WebMOutputFormat;\n if (/^vp/.test(vc)) {\n format = new WebMOutputFormat();\n }\n else {\n format = new Mp4OutputFormat();\n }\n output = new Output({\n format,\n target: new BufferTarget(),\n });\n if (/^vp8/.test(vc)) {\n videoSource = new EncodedVideoPacketSource('vp8');\n }\n else if (/^vp09\\./.test(vc)) {\n videoSource = new EncodedVideoPacketSource('vp9');\n }\n else if (/^av01\\./.test(vc)) {\n videoSource = new EncodedVideoPacketSource('av1');\n }\n else if (/^hev1\\./.test(vc) || /^hvc1\\./.test(vc)) {\n videoSource = new EncodedVideoPacketSource('hevc');\n }\n else if (/^avc1\\./.test(vc) || /^avc3\\./.test(vc)) {\n videoSource = new EncodedVideoPacketSource('avc');\n }\n if (videoSource) {\n output.addVideoTrack(videoSource);\n videoEncoder = new VideoEncoder({\n output(chunk, metadata) {\n // console.log('v', chunk, metadata);\n const part = EncodedPacket.fromEncodedChunk(chunk);\n videoSource!.add(part, metadata);\n didVideo = true;\n fin();\n },\n error(e) {\n onError(e.message);\n },\n });\n videoEncoder.configure(e.data.videoEncoderConfig);\n }\n const ac = e.data.audioEncoderConfig?.codec;\n if (e.data.mute) {\n // 不合成音频\n audioSource = undefined;\n }\n else if (/^mp3/.test(ac)) {\n audioSource = new EncodedAudioPacketSource('mp3');\n }\n else if (/^flac/.test(ac)) {\n audioSource = new EncodedAudioPacketSource('flac');\n }\n else if (/^opus/.test(ac)) {\n audioSource = new EncodedAudioPacketSource('opus');\n }\n else if (/^vorbis/.test(ac)) {\n audioSource = new EncodedAudioPacketSource('vorbis');\n }\n else if (/^pcm-/.test(ac)) {\n audioSource = new EncodedAudioPacketSource(ac as any);\n }\n else if (/^mp4a\\./.test(ac)) {\n audioSource = new EncodedAudioPacketSource('aac');\n }\n else if (/^ulaw/.test(ac)) {\n audioSource = new EncodedAudioPacketSource('ulaw');\n }\n else if (/^alaw/.test(ac)) {\n audioSource = new EncodedAudioPacketSource('alaw');\n }\n if (audioSource) {\n output.addAudioTrack(audioSource);\n audioEncoder = new AudioEncoder({\n output(chunk, metadata) {\n // console.log('a', chunk, metadata)\n const part = EncodedPacket.fromEncodedChunk(chunk);\n audioSource!.add(part, metadata);\n didAudio = true;\n fin();\n },\n error(e) {\n onError(e.message);\n }\n });\n audioEncoder.configure(e.data.audioEncoderConfig);\n // 初始化10s足够大的arraybuffer存储混音数据,处理过程中一段段处理,然后处理好的扔掉不要\n masterChannels.splice(0);\n const num = e.data.audioEncoderConfig.sampleRate * Math.ceil(e.data.duration * 1e-3);\n for (let i = 0; i < e.data.audioEncoderConfig.numberOfChannels; i++) {\n masterChannels.push(new Float32Array(num));\n }\n lastIndex = 0;\n lastTimestamp = 0;\n masterOffset = 0;\n }\n await output.start();\n }\n else if (type === EncoderType.FRAME) {\n didVideo = false;\n didAudio = false;\n const videoFrame = e.data.videoFrame;\n if (videoEncoder && videoEncoder.state === 'configured' && videoFrame) {\n videoEncoder.encode(videoFrame);\n }\n videoFrame?.close();\n const audioList = e.data.audioList;\n const { numberOfChannels, sampleRate } = e.data.audioEncoderConfig;\n if (audioEncoder && audioEncoder.state === 'configured') {\n if (audioList.length) {\n for (let i = 0, len = audioList.length; i < len; i++) {\n const { audioChunk, volume } = audioList[i];\n // 计算当前时间在整体的偏移frame位置\n const frameOffset = Math.round(audioChunk.timestamp * 1e-3 * sampleRate);\n const length = audioChunk.numberOfFrames;\n for (let i = 0; i < numberOfChannels; i++) {\n const masterChannel = masterChannels[i];\n // 直接获取每个声道的 Float32Array 数据\n const d = audioChunk.channels[i];\n for (let j = 0; j < length; j++) {\n const index = frameOffset + j;\n // 简单的增益控制clamping\n const n = (masterChannel[index] + d[j] * volume);\n masterChannel[index] = Math.max(-1, Math.min(1, n));\n }\n }\n }\n }\n // audioBuffer总是每个gop开头就会给到,所以每帧时把混合结果中当前时间之前的给到audioEncoder\n if (e.data.timestamp) {\n const index = Math.round(e.data.timestamp * 1e-3 * sampleRate);\n if (index > lastIndex) {\n const numberOfFrames = index - lastIndex;\n const data = new Float32Array(numberOfFrames * masterChannels.length);\n for (let i = 0; i < masterChannels.length; i++) {\n const mc = masterChannels[i];\n const sub = mc.subarray(lastIndex, index);\n data.set(sub, i * numberOfFrames);\n }\n const audioData = new AudioData({\n format: 'f32-planar',\n sampleRate,\n numberOfFrames: numberOfFrames,\n numberOfChannels,\n timestamp: lastTimestamp,\n data,\n });\n lastIndex = index;\n lastTimestamp = e.data.timestamp;\n audioEncoder!.encode(audioData);\n }\n }\n didAudio = true;\n }\n else if (e.data.mute) {\n didAudio = true;\n }\n return pm;\n }\n else if (type === EncoderType.END) {\n if (!videoEncoder || !output) {\n return;\n }\n await videoEncoder.flush();\n videoEncoder.close();\n videoEncoder = undefined;\n if (audioEncoder?.state === 'configured') {\n await audioEncoder.flush();\n audioEncoder.close();\n audioEncoder = undefined;\n }\n await output.finalize();\n const buffer = (output.target as BufferTarget).buffer;\n output = undefined;\n const res = {\n type: EncoderEvent.FINISH,\n buffer,\n };\n if (isWorker) {\n (self as DedicatedWorkerGlobalScope).postMessage(res, [buffer] as Transferable[]);\n }\n else {\n return { data: res };\n }\n }\n};\n\nself.onmessage = onMessage;\n"],"names":["__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","value","step","next","e","rejected","result","done","then","apply","__generator","body","f","y","t","_","label","sent","trys","ops","g","Object","create","Iterator","prototype","verb","Symbol","iterator","this","n","v","op","TypeError","call","pop","length","push","assert","x","Error","SuppressedError","last","arr","isU32","Bitstream","constructor","bytes","pos","seekToByte","byteOffset","readBit","byteIndex","Math","floor","byte","bitIndex","bit","readBits","i","writeBits","end","readAlignedByte","skipBits","getBitsLeft","clone","readExpGolomb","bitstream","leadingZeroBits","readSignedExpGolomb","codeNum","toUint8Array","source","Uint8Array","ArrayBuffer","buffer","byteLength","textEncoder","TextEncoder","COLOR_PRIMARIES_MAP","bt709","bt470bg","smpte170m","bt2020","smpte432","TRANSFER_CHARACTERISTICS_MAP","linear","pq","hlg","MATRIX_COEFFICIENTS_MAP","rgb","colorSpaceIsComplete","colorSpace","primaries","transfer","matrix","undefined","fullRange","isAllowSharedBufferSource","SharedArrayBuffer","isView","AsyncMutex","currentPromise","acquire","resolver","nextPromise","currentPromiseAlias","promiseWithResolvers","promise","res","rej","assertNever","roundToMultiple","multiple","round","ISO_639_2_REGEX","SECOND_TO_MICROSECOND_FACTOR","Number","EPSILON","keyValueIterator","object","key","imageMimeTypeToExtension","mimeType","toLowerCase","uint8ArraysAreEqual","a","b","RichImageData","data","AttachedFile","name","description","VIDEO_CODECS","PCM_AUDIO_CODECS","NON_PCM_AUDIO_CODECS","AUDIO_CODECS","SUBTITLE_CODECS","generateVp9CodecConfigurationFromCodecString","codecString","parts","split","generateAv1CodecConfigurationFromCodecString","profile","levelAndTier","slice","PCM_CODEC_REGEX","parsePcmCodec","codec","includes","dataType","sampleSize","littleEndian","silentValue","match","exec","VALID_VIDEO_CODEC_STRING_PREFIXES","AVC_CODEC_STRING_REGEX","HEVC_CODEC_STRING_REGEX","VP9_CODEC_STRING_REGEX","AV1_CODEC_STRING_REGEX","validateVideoChunkMetadata","metadata","decoderConfig","some","prefix","startsWith","isInteger","codedWidth","codedHeight","primariesValues","keys","join","transferValues","matrixValues","test","VALID_AUDIO_CODEC_STRING_PREFIXES","validateAudioChunkMetadata","sampleRate","numberOfChannels","minDescriptionSize","validateSubtitleMetadata","config","Muxer","output","mutex","firstMediaStreamTimestamp","trackTimestampInfo","WeakMap","onTrackClose","track","validateAndNormalizeTimestamp","timestampInSeconds","isKeyPacket","_timestampOffset","timestampInfo","get","maxTimestamp","maxTimestampBeforeLastKeyPacket","set","max","AvcNalUnitType","HevcNalUnitType","findNalUnitsInAnnexB","packetData","nalUnits","startCodePos","startCodeLength","j","nalData","subarray","removeEmulationPreventionBytes","len","extractNalUnitTypeForAvc","parseAvcSps","sps","profileIdc","constraintFlags","levelIdc","chromaFormatIdc","bitDepthLumaMinus8","bitDepthChromaMinus8","sizeOfScalingList","lastScale","nextScale","picOrderCntType","numRefFramesInPicOrderCntCycle","frameMbsOnlyFlag","error","console","extractNalUnitTypeForHevc","parseProfileTierLevel","maxNumSubLayersMinus1","general_profile_space","general_tier_flag","general_profile_idc","general_profile_compatibility_flags","general_constraint_indicator_flags","general_level_idc","sub_layer_profile_present_flag","sub_layer_level_present_flag","skipScalingListData","sizeId","matrixId","coefNum","min","skipAllStRefPicSets","num_short_term_ref_pic_sets","NumDeltaPocs","stRpsIdx","skipStRefPicSet","NumDeltaPocsThis","inter_ref_pic_set_prediction_flag","RefRpsIdx","numDelta","num_negative_pics","num_positive_pics","parseVuiForMinSpatialSegmentationIdc","sps_max_sub_layers_minus1","skipHrdParameters","min_spatial_segmentation_idc","commonInfPresentFlag","nal_hrd_parameters_present_flag","vcl_hrd_parameters_present_flag","sub_pic_hrd_params_present_flag","fixed_pic_rate_within_cvs_flag","low_delay_hrd_flag","CpbCnt","skipSubLayerHrdParameters","parseOpusIdentificationHeader","view","DataView","outputChannelCount","getUint8","preSkip","getUint16","inputSampleRate","getUint32","outputGain","getInt16","channelMappingFamily","channelMappingTable","FlacBlockType","PLACEHOLDER_DATA","EncodedPacket","type","timestamp","duration","sequenceNumber","sideData","isFinite","alpha","alphaByteLength","isMetadataOnly","microsecondTimestamp","trunc","microsecondDuration","toEncodedVideoChunk","EncodedVideoChunk","alphaToEncodedVideoChunk","toEncodedAudioChunk","EncodedAudioChunk","fromEncodedChunk","chunk","copyTo","options","EBMLFloat32","EBMLFloat64","EBMLSignedInt","EBMLUnicodeString","EBMLId","EBML","Segment","SeekHead","Info","Cluster","Tracks","Cues","Attachments","Chapters","Tags","measureUnsignedInt","measureUnsignedBigInt","measureSignedInt","EBMLWriter","writer","helper","helperView","offsets","dataOffsets","writeByte","setUint8","write","writeFloat32","setFloat32","writeFloat64","setFloat64","writeUnsignedInt","width","writeUnsignedBigInt","BigInt","writeSignedInt","writeVarInt","measureVarInt","writeAsciiString","str","map","charCodeAt","writeEBML","Array","isArray","elem","getPos","id","sizePos","sizeSize","size","seek","startPos","endPos","encode","CODEC_STRING_MAP","avc","hevc","vp8","vp9","av1","aac","mp3","opus","vorbis","flac","webvtt","inlineTimestampRegex","timestampRegex","formatSubtitleTimestamp","hours","minutes","seconds","milliseconds","toString","padStart","IsobmffBoxWriter","writeU32","setUint32","writeU64","writeAscii","text","writeBox","box","contents","children","writeBoxHeader","child","largeSize","measureBoxHeader","patchBox","boxOffset","measureBox","u8","u16","setUint16","i16","setInt16","u24","u32","i32","setInt32","u64","fixed_8_8","fixed_16_16","fixed_2_30","variableUnsignedInt","remaining","reverse","ascii","nullTerminated","fill","lastPresentedSample","samples","sample","rotationMatrix","rotationInDegrees","theta","PI","cosTheta","cos","sinTheta","sin","IDENTITY_MATRIX","matrixToBytes","flat","fullBox","version","flags","mdat","reserveLargeSize","moov","muxer","mvhd","creationTime","trackDatas","trak","isFragmented","mvex","udta","intoTimescale","filter","lastSample","GLOBAL_TIMESCALE","nextTrackId","needsU64","u32OrU64","trackData","trackMetadata","getTrackMetadata","tkhd","mdia","durationInGlobalTimescale","rotation","disposition","default","info","height","mdhd","hdlr","TRACK_TYPE_TO_COMPONENT_SUBTYPE","TRACK_TYPE_TO_HANDLER_NAME","minf","localDuration","timescale","getLanguageCodeInt","languageCode","video","audio","subtitle","hasComponentType","handlerType","manufacturer","TRACK_TYPE_TO_HEADER_BOX","dinf","stbl","dref","url","needsCtts","compositionTimeOffsetTable","sampleCompositionTimeOffset","stsd","stts","ctts","cslg","stsc","stsz","stco","stss","sampleDescription","videoSampleDescription","videoCodecToBoxName","_codec","boxName","audioCodecToBoxName","isQuickTime","soundSampleDescription","subtitleSampleDescription","SUBTITLE_CODEC_TO_BOX_NAME","compressionType","VIDEO_CODEC_TO_CONFIGURATION_BOX","colr","vpcC","level","thirdByte","colourPrimaries","transferCharacteristics","matrixCoefficients","sampleSizeInBits","audioCodecToConfigurationBox","esds","objectTypeIndication","wave","frma","enda","dOps","header","dfLa","pcmC","SUBTITLE_CODEC_TO_CONFIGURATION_BOX","timeToSampleTable","sampleCount","sampleDelta","every","keySamples","entries","index","compactlyCodedChunkTable","firstChunk","samplesPerChunk","requiresPcmTransformation","reduce","acc","finalizedChunks","offset","leastDecodeToDisplayDelta","Infinity","greatestDecodeToDisplayDelta","compositionStartTime","compositionEndTime","entry","compositionToDtsShift","trex","moof","mfhd","traf","fragmentSampleFlags","byte1","byte2","sampleIsDifferenceSample","tfhd","tfdt","trun","currentChunk","tfFlags","referenceSample","referenceSampleInfo","timescaleUnitsToNextSample","startTimestamp","allSampleDurations","allSampleSizes","allSampleFlags","allSampleCompositionTimeOffsets","decodeTimestamp","uniqueSampleDurations","Set","uniqueSampleSizes","uniqueSampleFlags","uniqueSampleCompositionTimeOffsets","firstSampleFlagsPresent","sampleDurationPresent","sampleSizePresent","sampleFlagsPresent","sampleCompositionTimeOffsetsPresent","moofOffset","tfra","trackIndex","mfro","vtte","vttc","payload","identifier","settings","sourceId","vtta","notes","boxes","metadataFormat","format","_options","metadataTags","_metadataTags","metaBox","metaMdir","metaMdta","addQuickTimeMetadataTagBoxes","tags","metadataTagStringBoxShort","toISOString","raw","from","encoded","DATA_BOX_MIME_TYPE_MAP","generateMetadataPairs","isMdta","pairs","dataStringBoxLong","image","kind","string","tracksTotal","discsTotal","pair","String","fromCharCode","fullCodecString","code","language","Writer","ensureMonotonicity","trackedWrites","trackedStart","trackedEnd","start","maybeTrackWrites","neededSize","newLength","copy","startTrackingWrites","stopTrackingWrites","ARRAY_BUFFER_INITIAL_SIZE","ARRAY_BUFFER_MAX_SIZE","BufferTargetWriter","target","super","maxPos","supportsResize","maxByteLength","ensureSize","resize","newBuffer","newBytes","onwrite","newPos","flush","finalize","close","getSlice","Target","_output","BufferTarget","arguments","_createWriter","timeInSeconds","IsobmffMuxer","auxTarget","auxWriter","auxBoxWriter","ftypSize","allTracksKnown","Date","now","nextFragmentNumber","maxWrittenTimestamp","_writer","boxWriter","MovOutputFormat","fastStartDefault","fastStart","minimumFragmentDuration","release","holdsAvc","_tracks","onFtyp","details","fragmented","maximumPacketCount","onMdat","allTracksAreKnown","_closed","getMimeType","codecStrings","hasVideo","hasAudio","buildIsobmffMimeType","getVideoTrackData","packet","meta","existingTrackData","find","requiresAnnexBTransformation","decoderConfigurationRecord","vpsUnits","unit","VPS_NUT","spsUnits","SPS_NUT","ppsUnits","PPS_NUT","seiUnits","PREFIX_SEI_NUT","SUFFIX_SEI_NUT","sps_temporal_id_nesting_flag","chroma_format_idc","bit_depth_luma_minus8","bit_depth_chroma_minus8","num_long_term_ref_pics_sps","parallelismType","pps","ppsBitstream","tiles_enabled_flag","entropy_coding_sync_enabled_flag","configurationVersion","generalProfileSpace","generalTierFlag","generalProfileIdc","generalProfileCompatibilityFlags","generalConstraintIndicatorFlags","generalLevelIdc","minSpatialSegmentationIdc","avgFrameRate","constantFrameRate","numTemporalLayers","temporalIdNested","lengthSizeMinusOne","arrays","arrayCompleteness","nalUnitType","extractHevcDecoderConfigurationRecord","record","nal","serializeHevcDecoderConfigurationRecord","SPS","PPS","spsExtUnits","SPS_EXT","spsData","spsInfo","hasExtendedData","avcProfileIndication","profileCompatibility","avcLevelIndication","sequenceParameterSets","pictureParameterSets","chromaFormat","sequenceParameterSetExt","extractAvcDecoderConfigurationRecord","spsExt","serializeAvcDecoderConfigurationRecord","maxDenominator","sign","prevNumerator","prevDenominator","currNumerator","currDenominator","remainder","abs","integer","nextNumerator","nextDenominator","numerator","denominator","computeRationalApproximation","frameRate","newTrackData","sampleQueue","timestampProcessingQueue","lastTimescaleUnits","sort","getAudioTrackData","getSubtitleTrackData","lastCueEndTimestamp","cueQueue","nextSourceId","cueToSourceId","addEncodedVideoPacket","transformedData","totalSize","nalUnit","avccData","dataView","transformAnnexBToLengthPrefixed","internalSample","createSampleForTrack","registerSample","addEncodedAudioPacket","maybePadWithSilence","untilTimestamp","lastEndTimestamp","delta","deltaInTimescale","samplesNeeded","paddingSample","addSubtitleCue","cue","processWebVTTCues","until","timestamps","add","sortedTimestamps","sampleStart","sampleEnd","lastIndex","containsTimestamp","endTimestamp","splice","processTimestamps","nextSample","totalDuration","durationInTimescale","timescaleUnits","lastTableEntry","entryBefore","lastCompositionTimeOffsetTableEntry","interleaveSamples","registerSampleFastStartReserve","addSampleToTrack","beginNewChunk","currentChunkDuration","keyFrameQueuedEverywhere","otherTrackData","firstQueuedSample","finalizeFragment","finalizeCurrentChunk","isFinalCall","outer","trackWithMinTimestamp","minTimestamp","shift","flushWriter","fragmentNumber","onMoov","movieBox","tracksInFragment","moofBox","mdatStartPos","currentPos","fragmentStartTimestamp","mdatSize","needsLargeMdatSize","MAX_BOX_HEADER_SIZE","onMoof","newMoofBox","mdatBox","moovBox","reservedSize","computeSampleTableSizeUpperBound","upperBound","ceil","movieBoxSize","currentChunkPos","mfraBox","mfraBoxSize","mdatPos","remainingSpace","APP_NAME","TRACK_TYPE_MAP","MatroskaMuxer","segment","segmentInfo","seekHead","tracksElement","tagsElement","attachmentsElement","segmentDuration","cues","currentCluster","currentClusterStartMsTimestamp","currentClusterMaxMsTimestamp","trackDatasInCurrentCluster","Map","ebmlWriter","appendOnly","writeEBMLHeader","createSegmentInfo","createCues","onEbmlHeader","ebmlHeader","EBMLVersion","EBMLReadVersion","EBMLMaxIDLength","EBMLMaxSizeLength","DocType","WebMOutputFormat","DocTypeVersion","DocTypeReadVersion","maybeCreateSeekHead","writeOffsets","kaxCues","kaxInfo","kaxTracks","kaxAttachments","kaxTags","Seek","SeekID","SeekPosition","segmentDataOffset","Duration","TimestampScale","MuxingApp","WritingApp","createTracks","codecId","seekPreRollNs","TrackEntry","TrackNumber","TrackUID","TrackType","FlagDefault","forced","FlagForced","hearingImpaired","FlagHearingImpaired","visuallyImpaired","FlagVisualImpaired","original","FlagOriginal","commentary","FlagCommentary","FlagLacing","Language","CodecID","CodecDelay","SeekPreRoll","Name","videoSpecificTrackInfo","audioSpecificTrackInfo","subtitleSpecificTrackInfo","elements","CodecPrivate","DefaultDuration","flippedRotation","mappedRotation","normalizeRotation","videoElement","Video","PixelWidth","PixelHeight","alphaMode","AlphaMode","Colour","MatrixCoefficients","TransferCharacteristics","Primaries","Range","Projection","ProjectionType","ProjectionPoseRoll","pcmInfo","Audio","SamplingFrequency","Channels","BitDepth","maybeCreateTags","simpleTags","addSimpleTag","SimpleTag","TagName","TagString","TagBinary","writtenTags","has","Tag","Targets","TargetTypeValue","TargetType","maybeCreateAttachments","existingFileUids","images","fileUid","imageName","random","FileDescription","FileName","FileMediaType","FileData","FileUID","createSegment","onSegmentHeader","isWebM","Boolean","buildMatroskaMimeType","chunkQueue","lastWrittenMsTimestamp","isKeyFrame","additions","videoChunk","createInternalChunk","fixVP9ColorSpace","interleaveChunks","audioChunk","bodyText","timestampMs","replace","time","parseSubtitleTimestamp","subtitleChunk","trim","writeBlock","profileLowBit","colorSpaceID","msTimestamp","shouldCreateNewCluster","relativeTimestamp","minimumClusterDuration","createNewCluster","prelude","msDuration","blockGroup","BlockGroup","Block","ReferenceBlock","BlockAdditions","BlockMore","BlockAddID","BlockAdditional","BlockDuration","simpleBlock","SimpleBlock","firstMsTimestamp","finalizeCurrentCluster","onCluster","Timestamp","clear","clusterSize","clusterOffsetFromSegment","groupedByTimestamp","groupedAndSortedByTimestamp","CuePoint","CueTime","CueTrackPositions","CueTrack","CueClusterPosition","segmentSize","OutputFormat","getSupportedVideoCodecs","getSupportedCodecs","getSupportedAudioCodecs","getSupportedSubtitleCodecs","_codecUnsupportedHint","IsobmffOutputFormat","getSupportedTrackCounts","total","supportsVideoRotationMetadata","_createMuxer","Mp4OutputFormat","_name","fileExtension","MkvOutputFormat","MediaSource","_connectedTrack","_closingPromise","_ensureValidAdd","state","_start","_flushAndClose","forceClose","connectedTrack","_muxer","_flushOrWaitForOngoingClose","VideoSource","EncodedVideoPacketSource","AudioSource","EncodedAudioPacketSource","SubtitleSource","ALL_TRACK_TYPES","validateBaseTrackMetadata","validateTrackDisposition","Output","_startPromise","_cancelPromise","_finalizePromise","_mutex","addVideoTrack","_addTrack","addAudioTrack","addSubtitleTrack","setMetadataTags","title","artist","album","albumArtist","trackNumber","discNumber","genre","date","isNaN","getTime","lyrics","comment","values","validateMetadataTags","supportedTrackCounts","presentTracksOfThisType","count","maxCount","maxTotalCount","supportedVideoCodecs","supportedAudioCodecs","supportedSubtitleCodecs","trackType","minCount","totalMinCount","warn","promises","all","cancel","EncoderType","EncoderEvent","videoEncoder","audioEncoder","videoSource","audioSource","onFrame","didVideo","didAudio","masterChannels","lastTimestamp","onMessage","_a","isWorker","onError","ERROR","self","postMessage","pm","INIT","fin_1","PROGRESS","vc","videoEncoderConfig","_d","VideoEncoder","part","message","configure","ac","audioEncoderConfig","_e","mute","AudioEncoder","num","Float32Array","_f","FRAME","videoFrame","audioList","_b","_c","volume","frameOffset","length_1","numberOfFrames","i_1","masterChannel","d","channels","mc","sub","audioData","AudioData","END","FINISH","onmessage"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]}
|