webcodecs-encoder
Version:
A TypeScript library for browser environments to encode video (H.264/AVC, VP9, VP8) and audio (AAC, Opus) using the WebCodecs API and mux them into MP4 or WebM containers with real-time streaming support. New function-first API design.
1,150 lines (1,148 loc) • 134 kB
JavaScript
"use strict";
var EncoderWorkerGlobal = (() => {
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// node_modules/webm-muxer/build/webm-muxer.js
var require_webm_muxer = __commonJS({
"node_modules/webm-muxer/build/webm-muxer.js"(exports, module) {
"use strict";
var WebMMuxer2 = (() => {
var __defProp3 = Object.defineProperty;
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
var __getOwnPropNames2 = Object.getOwnPropertyNames;
var __hasOwnProp3 = Object.prototype.hasOwnProperty;
var __pow2 = Math.pow;
var __export = (target, all) => {
for (var name in all)
__defProp3(target, name, { get: all[name], enumerable: true });
};
var __copyProps2 = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames2(from))
if (!__hasOwnProp3.call(to, key) && key !== except)
__defProp3(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps2(__defProp3({}, "__esModule", { value: true }), mod);
var __accessCheck2 = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet2 = (obj, member, getter) => {
__accessCheck2(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd2 = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet2 = (obj, member, value, setter) => {
__accessCheck2(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var __privateMethod2 = (obj, member, method) => {
__accessCheck2(obj, member, "access private method");
return method;
};
var main_exports = {};
__export(main_exports, {
default: () => main_default
});
var EBMLFloat32 = class {
constructor(value) {
this.value = value;
}
};
var EBMLFloat64 = class {
constructor(value) {
this.value = value;
}
};
var WriteTarget = class {
constructor() {
this.pos = 0;
this.helper = new Uint8Array(8);
this.helperView = new DataView(this.helper.buffer);
this.offsets = /* @__PURE__ */ new WeakMap();
this.dataOffsets = /* @__PURE__ */ new WeakMap();
}
writeFloat32(value) {
this.helperView.setFloat32(0, value, false);
this.write(this.helper.subarray(0, 4));
}
writeFloat64(value) {
this.helperView.setFloat64(0, value, false);
this.write(this.helper);
}
writeUnsignedInt(value, width = measureUnsignedInt(value)) {
let pos = 0;
switch (width) {
case 6:
this.helperView.setUint8(pos++, value / __pow2(2, 40) | 0);
case 5:
this.helperView.setUint8(pos++, value / __pow2(2, 32) | 0);
case 4:
this.helperView.setUint8(pos++, value >> 24);
case 3:
this.helperView.setUint8(pos++, value >> 16);
case 2:
this.helperView.setUint8(pos++, value >> 8);
case 1:
this.helperView.setUint8(pos++, value);
break;
default:
throw new Error("Bad UINT size " + width);
}
this.write(this.helper.subarray(0, pos));
}
writeEBMLVarInt(value, width = measureEBMLVarInt(value)) {
let pos = 0;
switch (width) {
case 1:
this.helperView.setUint8(pos++, 1 << 7 | value);
break;
case 2:
this.helperView.setUint8(pos++, 1 << 6 | value >> 8);
this.helperView.setUint8(pos++, value);
break;
case 3:
this.helperView.setUint8(pos++, 1 << 5 | value >> 16);
this.helperView.setUint8(pos++, value >> 8);
this.helperView.setUint8(pos++, value);
break;
case 4:
this.helperView.setUint8(pos++, 1 << 4 | value >> 24);
this.helperView.setUint8(pos++, value >> 16);
this.helperView.setUint8(pos++, value >> 8);
this.helperView.setUint8(pos++, value);
break;
case 5:
this.helperView.setUint8(pos++, 1 << 3 | value / __pow2(2, 32) & 7);
this.helperView.setUint8(pos++, value >> 24);
this.helperView.setUint8(pos++, value >> 16);
this.helperView.setUint8(pos++, value >> 8);
this.helperView.setUint8(pos++, value);
break;
case 6:
this.helperView.setUint8(pos++, 1 << 2 | value / __pow2(2, 40) & 3);
this.helperView.setUint8(pos++, value / __pow2(2, 32) | 0);
this.helperView.setUint8(pos++, value >> 24);
this.helperView.setUint8(pos++, value >> 16);
this.helperView.setUint8(pos++, value >> 8);
this.helperView.setUint8(pos++, value);
break;
default:
throw new Error("Bad EBML VINT size " + width);
}
this.write(this.helper.subarray(0, pos));
}
writeString(str) {
this.write(new Uint8Array(str.split("").map((x) => x.charCodeAt(0))));
}
writeEBML(data) {
var _a, _b;
if (data instanceof Uint8Array) {
this.write(data);
} else if (Array.isArray(data)) {
for (let elem of data) {
this.writeEBML(elem);
}
} else {
this.offsets.set(data, this.pos);
this.writeUnsignedInt(data.id);
if (Array.isArray(data.data)) {
let sizePos = this.pos;
let sizeSize = (_a = data.size) != null ? _a : 4;
this.seek(this.pos + sizeSize);
let startPos = this.pos;
this.dataOffsets.set(data, startPos);
this.writeEBML(data.data);
let size = this.pos - startPos;
let endPos = this.pos;
this.seek(sizePos);
this.writeEBMLVarInt(size, sizeSize);
this.seek(endPos);
} else if (typeof data.data === "number") {
let size = (_b = data.size) != null ? _b : measureUnsignedInt(data.data);
this.writeEBMLVarInt(size);
this.writeUnsignedInt(data.data, size);
} else if (typeof data.data === "string") {
this.writeEBMLVarInt(data.data.length);
this.writeString(data.data);
} else if (data.data instanceof Uint8Array) {
this.writeEBMLVarInt(data.data.byteLength, data.size);
this.write(data.data);
} else if (data.data instanceof EBMLFloat32) {
this.writeEBMLVarInt(4);
this.writeFloat32(data.data.value);
} else if (data.data instanceof EBMLFloat64) {
this.writeEBMLVarInt(8);
this.writeFloat64(data.data.value);
}
}
}
};
var measureUnsignedInt = (value) => {
if (value < 1 << 8) {
return 1;
} else if (value < 1 << 16) {
return 2;
} else if (value < 1 << 24) {
return 3;
} else if (value < __pow2(2, 32)) {
return 4;
} else if (value < __pow2(2, 40)) {
return 5;
} else {
return 6;
}
};
var measureEBMLVarInt = (value) => {
if (value < (1 << 7) - 1) {
return 1;
} else if (value < (1 << 14) - 1) {
return 2;
} else if (value < (1 << 21) - 1) {
return 3;
} else if (value < (1 << 28) - 1) {
return 4;
} else if (value < __pow2(2, 35) - 1) {
return 5;
} else if (value < __pow2(2, 42) - 1) {
return 6;
} else {
throw new Error("EBML VINT size not supported " + value);
}
};
var ArrayBufferWriteTarget = class extends WriteTarget {
constructor() {
super();
this.buffer = new ArrayBuffer(__pow2(2, 16));
this.bytes = new Uint8Array(this.buffer);
}
ensureSize(size) {
let newLength = this.buffer.byteLength;
while (newLength < size)
newLength *= 2;
if (newLength === this.buffer.byteLength)
return;
let newBuffer = new ArrayBuffer(newLength);
let newBytes = new Uint8Array(newBuffer);
newBytes.set(this.bytes, 0);
this.buffer = newBuffer;
this.bytes = newBytes;
}
write(data) {
this.ensureSize(this.pos + data.byteLength);
this.bytes.set(data, this.pos);
this.pos += data.byteLength;
}
seek(newPos) {
this.pos = newPos;
}
finalize() {
this.ensureSize(this.pos);
return this.buffer.slice(0, this.pos);
}
};
var FILE_CHUNK_SIZE = __pow2(2, 24);
var MAX_CHUNKS_AT_ONCE2 = 2;
var FileSystemWritableFileStreamWriteTarget = class extends WriteTarget {
constructor(stream) {
super();
this.chunks = [];
this.stream = stream;
}
write(data) {
this.writeDataIntoChunks(data, this.pos);
this.flushChunks();
this.pos += data.byteLength;
}
writeDataIntoChunks(data, position) {
let chunkIndex = this.chunks.findIndex((x) => x.start <= position && position < x.start + FILE_CHUNK_SIZE);
if (chunkIndex === -1)
chunkIndex = this.createChunk(position);
let chunk = this.chunks[chunkIndex];
let relativePosition = position - chunk.start;
let toWrite = data.subarray(0, Math.min(FILE_CHUNK_SIZE - relativePosition, data.byteLength));
chunk.data.set(toWrite, relativePosition);
let section = {
start: relativePosition,
end: relativePosition + toWrite.byteLength
};
insertSectionIntoFileChunk(chunk, section);
if (chunk.written[0].start === 0 && chunk.written[0].end === FILE_CHUNK_SIZE) {
chunk.shouldFlush = true;
}
if (this.chunks.length > MAX_CHUNKS_AT_ONCE2) {
for (let i = 0; i < this.chunks.length - 1; i++) {
this.chunks[i].shouldFlush = true;
}
this.flushChunks();
}
if (toWrite.byteLength < data.byteLength) {
this.writeDataIntoChunks(data.subarray(toWrite.byteLength), position + toWrite.byteLength);
}
}
createChunk(includesPosition) {
let start = Math.floor(includesPosition / FILE_CHUNK_SIZE) * FILE_CHUNK_SIZE;
let chunk = {
start,
data: new Uint8Array(FILE_CHUNK_SIZE),
written: [],
shouldFlush: false
};
this.chunks.push(chunk);
this.chunks.sort((a, b) => a.start - b.start);
return this.chunks.indexOf(chunk);
}
flushChunks(force = false) {
for (let i = 0; i < this.chunks.length; i++) {
let chunk = this.chunks[i];
if (!chunk.shouldFlush && !force)
continue;
for (let section of chunk.written) {
this.stream.write({
type: "write",
data: chunk.data.subarray(section.start, section.end),
position: chunk.start + section.start
});
}
this.chunks.splice(i--, 1);
}
}
seek(newPos) {
this.pos = newPos;
}
finalize() {
this.flushChunks(true);
}
};
var insertSectionIntoFileChunk = (chunk, section) => {
let low = 0;
let high = chunk.written.length - 1;
let index = -1;
while (low <= high) {
let mid = Math.floor(low + (high - low + 1) / 2);
if (chunk.written[mid].start <= section.start) {
low = mid + 1;
index = mid;
} else {
high = mid - 1;
}
}
chunk.written.splice(index + 1, 0, section);
if (index === -1 || chunk.written[index].end < section.start)
index++;
while (index < chunk.written.length - 1 && chunk.written[index].end >= chunk.written[index + 1].start) {
chunk.written[index].end = Math.max(chunk.written[index].end, chunk.written[index + 1].end);
chunk.written.splice(index + 1, 1);
}
};
var VIDEO_TRACK_NUMBER = 1;
var AUDIO_TRACK_NUMBER = 2;
var VIDEO_TRACK_TYPE = 1;
var AUDIO_TRACK_TYPE = 2;
var MAX_CHUNK_LENGTH_MS = __pow2(2, 15);
var CODEC_PRIVATE_MAX_SIZE = __pow2(2, 12);
var APP_NAME = "https://github.com/Vanilagy/webm-muxer";
var SEGMENT_SIZE_BYTES = 6;
var CLUSTER_SIZE_BYTES = 5;
var _target4, _options2, _segment, _segmentInfo, _seekHead, _tracksElement, _segmentDuration, _colourElement, _videoCodecPrivate, _audioCodecPrivate, _cues, _currentCluster, _currentClusterTimestamp, _duration, _videoChunkQueue, _audioChunkQueue, _lastVideoTimestamp, _lastAudioTimestamp, _colorSpace, _finalized2, _validateOptions2, validateOptions_fn2, _createFileHeader, createFileHeader_fn, _writeEBMLHeader, writeEBMLHeader_fn, _createSeekHead, createSeekHead_fn, _createSegmentInfo, createSegmentInfo_fn, _createTracks, createTracks_fn, _createSegment, createSegment_fn, _createCues, createCues_fn, _segmentDataOffset, segmentDataOffset_get, _writeVideoDecoderConfig, writeVideoDecoderConfig_fn, _fixVP9ColorSpace, fixVP9ColorSpace_fn, _createInternalChunk, createInternalChunk_fn, _writeSimpleBlock, writeSimpleBlock_fn, _writeCodecPrivate, writeCodecPrivate_fn, _createNewCluster, createNewCluster_fn, _finalizeCurrentCluster, finalizeCurrentCluster_fn, _ensureNotFinalized2, ensureNotFinalized_fn2;
var WebMMuxer3 = class {
constructor(options) {
__privateAdd2(this, _validateOptions2);
__privateAdd2(this, _createFileHeader);
__privateAdd2(this, _writeEBMLHeader);
__privateAdd2(this, _createSeekHead);
__privateAdd2(this, _createSegmentInfo);
__privateAdd2(this, _createTracks);
__privateAdd2(this, _createSegment);
__privateAdd2(this, _createCues);
__privateAdd2(this, _segmentDataOffset);
__privateAdd2(this, _writeVideoDecoderConfig);
__privateAdd2(this, _fixVP9ColorSpace);
__privateAdd2(this, _createInternalChunk);
__privateAdd2(this, _writeSimpleBlock);
__privateAdd2(this, _writeCodecPrivate);
__privateAdd2(this, _createNewCluster);
__privateAdd2(this, _finalizeCurrentCluster);
__privateAdd2(this, _ensureNotFinalized2);
__privateAdd2(this, _target4, void 0);
__privateAdd2(this, _options2, void 0);
__privateAdd2(this, _segment, void 0);
__privateAdd2(this, _segmentInfo, void 0);
__privateAdd2(this, _seekHead, void 0);
__privateAdd2(this, _tracksElement, void 0);
__privateAdd2(this, _segmentDuration, void 0);
__privateAdd2(this, _colourElement, void 0);
__privateAdd2(this, _videoCodecPrivate, void 0);
__privateAdd2(this, _audioCodecPrivate, void 0);
__privateAdd2(this, _cues, void 0);
__privateAdd2(this, _currentCluster, void 0);
__privateAdd2(this, _currentClusterTimestamp, void 0);
__privateAdd2(this, _duration, 0);
__privateAdd2(this, _videoChunkQueue, []);
__privateAdd2(this, _audioChunkQueue, []);
__privateAdd2(this, _lastVideoTimestamp, 0);
__privateAdd2(this, _lastAudioTimestamp, 0);
__privateAdd2(this, _colorSpace, void 0);
__privateAdd2(this, _finalized2, false);
__privateMethod2(this, _validateOptions2, validateOptions_fn2).call(this, options);
__privateSet2(this, _options2, options);
if (options.target === "buffer") {
__privateSet2(this, _target4, new ArrayBufferWriteTarget());
} else {
__privateSet2(this, _target4, new FileSystemWritableFileStreamWriteTarget(options.target));
}
__privateMethod2(this, _createFileHeader, createFileHeader_fn).call(this);
}
addVideoChunk(chunk, meta, timestamp) {
let data = new Uint8Array(chunk.byteLength);
chunk.copyTo(data);
this.addVideoChunkRaw(data, chunk.type, timestamp != null ? timestamp : chunk.timestamp, meta);
}
addVideoChunkRaw(data, type, timestamp, meta) {
__privateMethod2(this, _ensureNotFinalized2, ensureNotFinalized_fn2).call(this);
if (!__privateGet2(this, _options2).video)
throw new Error("No video track declared.");
if (meta)
__privateMethod2(this, _writeVideoDecoderConfig, writeVideoDecoderConfig_fn).call(this, meta);
let internalChunk = __privateMethod2(this, _createInternalChunk, createInternalChunk_fn).call(this, data, type, timestamp, VIDEO_TRACK_NUMBER);
if (__privateGet2(this, _options2).video.codec === "V_VP9")
__privateMethod2(this, _fixVP9ColorSpace, fixVP9ColorSpace_fn).call(this, internalChunk);
__privateSet2(this, _lastVideoTimestamp, internalChunk.timestamp);
while (__privateGet2(this, _audioChunkQueue).length > 0 && __privateGet2(this, _audioChunkQueue)[0].timestamp <= internalChunk.timestamp) {
let audioChunk = __privateGet2(this, _audioChunkQueue).shift();
__privateMethod2(this, _writeSimpleBlock, writeSimpleBlock_fn).call(this, audioChunk);
}
if (!__privateGet2(this, _options2).audio || internalChunk.timestamp <= __privateGet2(this, _lastAudioTimestamp)) {
__privateMethod2(this, _writeSimpleBlock, writeSimpleBlock_fn).call(this, internalChunk);
} else {
__privateGet2(this, _videoChunkQueue).push(internalChunk);
}
}
addAudioChunk(chunk, meta, timestamp) {
let data = new Uint8Array(chunk.byteLength);
chunk.copyTo(data);
this.addAudioChunkRaw(data, chunk.type, timestamp != null ? timestamp : chunk.timestamp, meta);
}
addAudioChunkRaw(data, type, timestamp, meta) {
__privateMethod2(this, _ensureNotFinalized2, ensureNotFinalized_fn2).call(this);
if (!__privateGet2(this, _options2).audio)
throw new Error("No audio track declared.");
let internalChunk = __privateMethod2(this, _createInternalChunk, createInternalChunk_fn).call(this, data, type, timestamp, AUDIO_TRACK_NUMBER);
__privateSet2(this, _lastAudioTimestamp, internalChunk.timestamp);
while (__privateGet2(this, _videoChunkQueue).length > 0 && __privateGet2(this, _videoChunkQueue)[0].timestamp <= internalChunk.timestamp) {
let videoChunk = __privateGet2(this, _videoChunkQueue).shift();
__privateMethod2(this, _writeSimpleBlock, writeSimpleBlock_fn).call(this, videoChunk);
}
if (!__privateGet2(this, _options2).video || internalChunk.timestamp <= __privateGet2(this, _lastVideoTimestamp)) {
__privateMethod2(this, _writeSimpleBlock, writeSimpleBlock_fn).call(this, internalChunk);
} else {
__privateGet2(this, _audioChunkQueue).push(internalChunk);
}
if (meta == null ? void 0 : meta.decoderConfig) {
__privateMethod2(this, _writeCodecPrivate, writeCodecPrivate_fn).call(this, __privateGet2(this, _audioCodecPrivate), meta.decoderConfig.description);
}
}
finalize() {
while (__privateGet2(this, _videoChunkQueue).length > 0)
__privateMethod2(this, _writeSimpleBlock, writeSimpleBlock_fn).call(this, __privateGet2(this, _videoChunkQueue).shift());
while (__privateGet2(this, _audioChunkQueue).length > 0)
__privateMethod2(this, _writeSimpleBlock, writeSimpleBlock_fn).call(this, __privateGet2(this, _audioChunkQueue).shift());
__privateMethod2(this, _finalizeCurrentCluster, finalizeCurrentCluster_fn).call(this);
__privateGet2(this, _target4).writeEBML(__privateGet2(this, _cues));
let endPos = __privateGet2(this, _target4).pos;
let segmentSize = __privateGet2(this, _target4).pos - __privateGet2(this, _segmentDataOffset, segmentDataOffset_get);
__privateGet2(this, _target4).seek(__privateGet2(this, _target4).offsets.get(__privateGet2(this, _segment)) + 4);
__privateGet2(this, _target4).writeEBMLVarInt(segmentSize, SEGMENT_SIZE_BYTES);
__privateGet2(this, _segmentDuration).data = new EBMLFloat64(__privateGet2(this, _duration));
__privateGet2(this, _target4).seek(__privateGet2(this, _target4).offsets.get(__privateGet2(this, _segmentDuration)));
__privateGet2(this, _target4).writeEBML(__privateGet2(this, _segmentDuration));
__privateGet2(this, _seekHead).data[0].data[1].data = __privateGet2(this, _target4).offsets.get(__privateGet2(this, _cues)) - __privateGet2(this, _segmentDataOffset, segmentDataOffset_get);
__privateGet2(this, _seekHead).data[1].data[1].data = __privateGet2(this, _target4).offsets.get(__privateGet2(this, _segmentInfo)) - __privateGet2(this, _segmentDataOffset, segmentDataOffset_get);
__privateGet2(this, _seekHead).data[2].data[1].data = __privateGet2(this, _target4).offsets.get(__privateGet2(this, _tracksElement)) - __privateGet2(this, _segmentDataOffset, segmentDataOffset_get);
__privateGet2(this, _target4).seek(__privateGet2(this, _target4).offsets.get(__privateGet2(this, _seekHead)));
__privateGet2(this, _target4).writeEBML(__privateGet2(this, _seekHead));
__privateGet2(this, _target4).seek(endPos);
__privateSet2(this, _finalized2, true);
if (__privateGet2(this, _target4) instanceof ArrayBufferWriteTarget) {
return __privateGet2(this, _target4).finalize();
} else if (__privateGet2(this, _target4) instanceof FileSystemWritableFileStreamWriteTarget) {
__privateGet2(this, _target4).finalize();
}
return null;
}
};
_target4 = /* @__PURE__ */ new WeakMap();
_options2 = /* @__PURE__ */ new WeakMap();
_segment = /* @__PURE__ */ new WeakMap();
_segmentInfo = /* @__PURE__ */ new WeakMap();
_seekHead = /* @__PURE__ */ new WeakMap();
_tracksElement = /* @__PURE__ */ new WeakMap();
_segmentDuration = /* @__PURE__ */ new WeakMap();
_colourElement = /* @__PURE__ */ new WeakMap();
_videoCodecPrivate = /* @__PURE__ */ new WeakMap();
_audioCodecPrivate = /* @__PURE__ */ new WeakMap();
_cues = /* @__PURE__ */ new WeakMap();
_currentCluster = /* @__PURE__ */ new WeakMap();
_currentClusterTimestamp = /* @__PURE__ */ new WeakMap();
_duration = /* @__PURE__ */ new WeakMap();
_videoChunkQueue = /* @__PURE__ */ new WeakMap();
_audioChunkQueue = /* @__PURE__ */ new WeakMap();
_lastVideoTimestamp = /* @__PURE__ */ new WeakMap();
_lastAudioTimestamp = /* @__PURE__ */ new WeakMap();
_colorSpace = /* @__PURE__ */ new WeakMap();
_finalized2 = /* @__PURE__ */ new WeakMap();
_validateOptions2 = /* @__PURE__ */ new WeakSet();
validateOptions_fn2 = function(options) {
if (options.type && options.type !== "webm" && options.type !== "matroska") {
throw new Error(`Invalid type: ${options.type}`);
}
};
_createFileHeader = /* @__PURE__ */ new WeakSet();
createFileHeader_fn = function() {
__privateMethod2(this, _writeEBMLHeader, writeEBMLHeader_fn).call(this);
__privateMethod2(this, _createSeekHead, createSeekHead_fn).call(this);
__privateMethod2(this, _createSegmentInfo, createSegmentInfo_fn).call(this);
__privateMethod2(this, _createTracks, createTracks_fn).call(this);
__privateMethod2(this, _createSegment, createSegment_fn).call(this);
__privateMethod2(this, _createCues, createCues_fn).call(this);
};
_writeEBMLHeader = /* @__PURE__ */ new WeakSet();
writeEBMLHeader_fn = function() {
var _a;
let ebmlHeader = { id: 440786851, data: [
{ id: 17030, data: 1 },
{ id: 17143, data: 1 },
{ id: 17138, data: 4 },
{ id: 17139, data: 8 },
{ id: 17026, data: (_a = __privateGet2(this, _options2).type) != null ? _a : "webm" },
{ id: 17031, data: 2 },
{ id: 17029, data: 2 }
] };
__privateGet2(this, _target4).writeEBML(ebmlHeader);
};
_createSeekHead = /* @__PURE__ */ new WeakSet();
createSeekHead_fn = function() {
const kaxCues = new Uint8Array([28, 83, 187, 107]);
const kaxInfo = new Uint8Array([21, 73, 169, 102]);
const kaxTracks = new Uint8Array([22, 84, 174, 107]);
let seekHead = { id: 290298740, data: [
{ id: 19899, data: [
{ id: 21419, data: kaxCues },
{ id: 21420, size: 5, data: 0 }
] },
{ id: 19899, data: [
{ id: 21419, data: kaxInfo },
{ id: 21420, size: 5, data: 0 }
] },
{ id: 19899, data: [
{ id: 21419, data: kaxTracks },
{ id: 21420, size: 5, data: 0 }
] }
] };
__privateSet2(this, _seekHead, seekHead);
};
_createSegmentInfo = /* @__PURE__ */ new WeakSet();
createSegmentInfo_fn = function() {
let segmentDuration = { id: 17545, data: new EBMLFloat64(0) };
__privateSet2(this, _segmentDuration, segmentDuration);
let segmentInfo = { id: 357149030, data: [
{ id: 2807729, data: 1e6 },
{ id: 19840, data: APP_NAME },
{ id: 22337, data: APP_NAME },
segmentDuration
] };
__privateSet2(this, _segmentInfo, segmentInfo);
};
_createTracks = /* @__PURE__ */ new WeakSet();
createTracks_fn = function() {
let tracksElement = { id: 374648427, data: [] };
__privateSet2(this, _tracksElement, tracksElement);
if (__privateGet2(this, _options2).video) {
__privateSet2(this, _videoCodecPrivate, { id: 236, size: 4, data: new Uint8Array(CODEC_PRIVATE_MAX_SIZE) });
let colourElement = { id: 21936, data: [
{ id: 21937, data: 2 },
{ id: 21946, data: 2 },
{ id: 21947, data: 2 },
{ id: 21945, data: 0 }
] };
__privateSet2(this, _colourElement, colourElement);
tracksElement.data.push({ id: 174, data: [
{ id: 215, data: VIDEO_TRACK_NUMBER },
{ id: 29637, data: VIDEO_TRACK_NUMBER },
{ id: 131, data: VIDEO_TRACK_TYPE },
{ id: 134, data: __privateGet2(this, _options2).video.codec },
__privateGet2(this, _videoCodecPrivate),
__privateGet2(this, _options2).video.frameRate ? { id: 2352003, data: 1e9 / __privateGet2(this, _options2).video.frameRate } : null,
{ id: 224, data: [
{ id: 176, data: __privateGet2(this, _options2).video.width },
{ id: 186, data: __privateGet2(this, _options2).video.height },
colourElement
] }
].filter(Boolean) });
}
if (__privateGet2(this, _options2).audio) {
__privateSet2(this, _audioCodecPrivate, { id: 236, size: 4, data: new Uint8Array(CODEC_PRIVATE_MAX_SIZE) });
tracksElement.data.push({ id: 174, data: [
{ id: 215, data: AUDIO_TRACK_NUMBER },
{ id: 29637, data: AUDIO_TRACK_NUMBER },
{ id: 131, data: AUDIO_TRACK_TYPE },
{ id: 134, data: __privateGet2(this, _options2).audio.codec },
__privateGet2(this, _audioCodecPrivate),
{ id: 225, data: [
{ id: 181, data: new EBMLFloat32(__privateGet2(this, _options2).audio.sampleRate) },
{ id: 159, data: __privateGet2(this, _options2).audio.numberOfChannels },
__privateGet2(this, _options2).audio.bitDepth ? { id: 25188, data: __privateGet2(this, _options2).audio.bitDepth } : null
].filter(Boolean) }
] });
}
};
_createSegment = /* @__PURE__ */ new WeakSet();
createSegment_fn = function() {
let segment = { id: 408125543, size: SEGMENT_SIZE_BYTES, data: [
__privateGet2(this, _seekHead),
__privateGet2(this, _segmentInfo),
__privateGet2(this, _tracksElement)
] };
__privateSet2(this, _segment, segment);
__privateGet2(this, _target4).writeEBML(segment);
};
_createCues = /* @__PURE__ */ new WeakSet();
createCues_fn = function() {
__privateSet2(this, _cues, { id: 475249515, data: [] });
};
_segmentDataOffset = /* @__PURE__ */ new WeakSet();
segmentDataOffset_get = function() {
return __privateGet2(this, _target4).dataOffsets.get(__privateGet2(this, _segment));
};
_writeVideoDecoderConfig = /* @__PURE__ */ new WeakSet();
writeVideoDecoderConfig_fn = function(meta) {
if (meta.decoderConfig) {
if (meta.decoderConfig.colorSpace) {
let colorSpace = meta.decoderConfig.colorSpace;
__privateSet2(this, _colorSpace, colorSpace);
__privateGet2(this, _colourElement).data = [
{ id: 21937, data: {
"rgb": 1,
"bt709": 1,
"bt470bg": 5,
"smpte170m": 6
}[colorSpace.matrix] },
{ id: 21946, data: {
"bt709": 1,
"smpte170m": 6,
"iec61966-2-1": 13
}[colorSpace.transfer] },
{ id: 21947, data: {
"bt709": 1,
"bt470bg": 5,
"smpte170m": 6
}[colorSpace.primaries] },
{ id: 21945, data: [1, 2][Number(colorSpace.fullRange)] }
];
let endPos = __privateGet2(this, _target4).pos;
__privateGet2(this, _target4).seek(__privateGet2(this, _target4).offsets.get(__privateGet2(this, _colourElement)));
__privateGet2(this, _target4).writeEBML(__privateGet2(this, _colourElement));
__privateGet2(this, _target4).seek(endPos);
}
if (meta.decoderConfig.description) {
__privateMethod2(this, _writeCodecPrivate, writeCodecPrivate_fn).call(this, __privateGet2(this, _videoCodecPrivate), meta.decoderConfig.description);
}
}
};
_fixVP9ColorSpace = /* @__PURE__ */ new WeakSet();
fixVP9ColorSpace_fn = function(chunk) {
if (chunk.type !== "key")
return;
if (!__privateGet2(this, _colorSpace))
return;
let i = 0;
if (readBits(chunk.data, 0, 2) !== 2)
return;
i += 2;
let profile = (readBits(chunk.data, i + 1, i + 2) << 1) + readBits(chunk.data, i + 0, i + 1);
i += 2;
if (profile === 3)
i++;
let showExistingFrame = readBits(chunk.data, i + 0, i + 1);
i++;
if (showExistingFrame)
return;
let frameType = readBits(chunk.data, i + 0, i + 1);
i++;
if (frameType !== 0)
return;
i += 2;
let syncCode = readBits(chunk.data, i + 0, i + 24);
i += 24;
if (syncCode !== 4817730)
return;
if (profile >= 2)
i++;
let colorSpaceID = {
"rgb": 7,
"bt709": 2,
"bt470bg": 1,
"smpte170m": 3
}[__privateGet2(this, _colorSpace).matrix];
writeBits(chunk.data, i + 0, i + 3, colorSpaceID);
};
_createInternalChunk = /* @__PURE__ */ new WeakSet();
createInternalChunk_fn = function(data, type, timestamp, trackNumber) {
let internalChunk = {
data,
type,
timestamp,
trackNumber
};
return internalChunk;
};
_writeSimpleBlock = /* @__PURE__ */ new WeakSet();
writeSimpleBlock_fn = function(chunk) {
let msTime = Math.floor(chunk.timestamp / 1e3);
let clusterIsTooLong = chunk.type !== "key" && msTime - __privateGet2(this, _currentClusterTimestamp) >= MAX_CHUNK_LENGTH_MS;
if (clusterIsTooLong) {
throw new Error(
`Current Matroska cluster exceeded its maximum allowed length of ${MAX_CHUNK_LENGTH_MS} milliseconds. In order to produce a correct WebM file, you must pass in a video key frame at least every ${MAX_CHUNK_LENGTH_MS} milliseconds.`
);
}
let shouldCreateNewClusterFromKeyFrame = (chunk.trackNumber === VIDEO_TRACK_NUMBER || !__privateGet2(this, _options2).video) && chunk.type === "key" && msTime - __privateGet2(this, _currentClusterTimestamp) >= 1e3;
if (!__privateGet2(this, _currentCluster) || shouldCreateNewClusterFromKeyFrame) {
__privateMethod2(this, _createNewCluster, createNewCluster_fn).call(this, msTime);
}
let prelude = new Uint8Array(4);
let view2 = new DataView(prelude.buffer);
view2.setUint8(0, 128 | chunk.trackNumber);
view2.setUint16(1, msTime - __privateGet2(this, _currentClusterTimestamp), false);
view2.setUint8(3, Number(chunk.type === "key") << 7);
let simpleBlock = { id: 163, data: [
prelude,
chunk.data
] };
__privateGet2(this, _target4).writeEBML(simpleBlock);
__privateSet2(this, _duration, Math.max(__privateGet2(this, _duration), msTime));
};
_writeCodecPrivate = /* @__PURE__ */ new WeakSet();
writeCodecPrivate_fn = function(element, data) {
let endPos = __privateGet2(this, _target4).pos;
__privateGet2(this, _target4).seek(__privateGet2(this, _target4).offsets.get(element));
element = [
{ id: 25506, size: 4, data: new Uint8Array(data) },
{ id: 236, size: 4, data: new Uint8Array(CODEC_PRIVATE_MAX_SIZE - 2 - 4 - data.byteLength) }
];
__privateGet2(this, _target4).writeEBML(element);
__privateGet2(this, _target4).seek(endPos);
};
_createNewCluster = /* @__PURE__ */ new WeakSet();
createNewCluster_fn = function(timestamp) {
if (__privateGet2(this, _currentCluster)) {
__privateMethod2(this, _finalizeCurrentCluster, finalizeCurrentCluster_fn).call(this);
}
__privateSet2(this, _currentCluster, { id: 524531317, size: CLUSTER_SIZE_BYTES, data: [
{ id: 231, data: timestamp }
] });
__privateGet2(this, _target4).writeEBML(__privateGet2(this, _currentCluster));
__privateSet2(this, _currentClusterTimestamp, timestamp);
let clusterOffsetFromSegment = __privateGet2(this, _target4).offsets.get(__privateGet2(this, _currentCluster)) - __privateGet2(this, _segmentDataOffset, segmentDataOffset_get);
__privateGet2(this, _cues).data.push({ id: 187, data: [
{ id: 179, data: timestamp },
{ id: 183, data: [
{ id: 247, data: VIDEO_TRACK_NUMBER },
{ id: 241, data: clusterOffsetFromSegment }
] }
] });
};
_finalizeCurrentCluster = /* @__PURE__ */ new WeakSet();
finalizeCurrentCluster_fn = function() {
let clusterSize = __privateGet2(this, _target4).pos - __privateGet2(this, _target4).dataOffsets.get(__privateGet2(this, _currentCluster));
let endPos = __privateGet2(this, _target4).pos;
__privateGet2(this, _target4).seek(__privateGet2(this, _target4).offsets.get(__privateGet2(this, _currentCluster)) + 4);
__privateGet2(this, _target4).writeEBMLVarInt(clusterSize, CLUSTER_SIZE_BYTES);
__privateGet2(this, _target4).seek(endPos);
};
_ensureNotFinalized2 = /* @__PURE__ */ new WeakSet();
ensureNotFinalized_fn2 = function() {
if (__privateGet2(this, _finalized2)) {
throw new Error("Cannot add new video or audio chunks after the file has been finalized.");
}
};
var main_default = WebMMuxer3;
var readBits = (bytes2, start, end) => {
let result = 0;
for (let i = start; i < end; i++) {
let byteIndex = Math.floor(i / 8);
let byte = bytes2[byteIndex];
let bitIndex = 7 - (i & 7);
let bit = (byte & 1 << bitIndex) >> bitIndex;
result <<= 1;
result |= bit;
}
return result;
};
var writeBits = (bytes2, start, end, value) => {
for (let i = start; i < end; i++) {
let byteIndex = Math.floor(i / 8);
let byte = bytes2[byteIndex];
let bitIndex = 7 - (i & 7);
byte &= ~(1 << bitIndex);
byte |= (value & 1 << end - i - 1) >> end - i - 1 << bitIndex;
bytes2[byteIndex] = byte;
}
};
return __toCommonJS(main_exports);
})();
WebMMuxer2 = WebMMuxer2.default;
if (typeof module === "object" && typeof module.exports === "object") module.exports = WebMMuxer2;
}
});
// node_modules/mp4-muxer/build/mp4-muxer.mjs
var __defProp2 = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __pow = Math.pow;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp2.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet = (obj, member, value, setter) => {
__accessCheck(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
var bytes = new Uint8Array(8);
var view = new DataView(bytes.buffer);
var u8 = (value) => {
return [(value % 256 + 256) % 256];
};
var u16 = (value) => {
view.setUint16(0, value, false);
return [bytes[0], bytes[1]];
};
var i16 = (value) => {
view.setInt16(0, value, false);
return [bytes[0], bytes[1]];
};
var u24 = (value) => {
view.setUint32(0, value, false);
return [bytes[1], bytes[2], bytes[3]];
};
var u32 = (value) => {
view.setUint32(0, value, false);
return [bytes[0], bytes[1], bytes[2], bytes[3]];
};
var u64 = (value) => {
view.setUint32(0, Math.floor(value / __pow(2, 32)), false);
view.setUint32(4, value, false);
return [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]];
};
var fixed_8_8 = (value) => {
view.setInt16(0, __pow(2, 8) * value, false);
return [bytes[0], bytes[1]];
};
var fixed_16_16 = (value) => {
view.setInt32(0, __pow(2, 16) * value, false);
return [bytes[0], bytes[1], bytes[2], bytes[3]];
};
var fixed_2_30 = (value) => {
view.setInt32(0, __pow(2, 30) * value, false);
return [bytes[0], bytes[1], bytes[2], bytes[3]];
};
var ascii = (text, nullTerminated = false) => {
let bytes2 = Array(text.length).fill(null).map((_, i) => text.charCodeAt(i));
if (nullTerminated)
bytes2.push(0);
return bytes2;
};
var last = (arr) => {
return arr && arr[arr.length - 1];
};
var intoTimescale = (timeInSeconds, timescale, round = true) => {
let value = timeInSeconds * timescale;
return round ? Math.round(value) : value;
};
var rotationMatrix = (rotationInDegrees) => {
let theta = rotationInDegrees * (Math.PI / 180);
let cosTheta = Math.cos(theta);
let sinTheta = Math.sin(theta);
return [
cosTheta,
sinTheta,
0,
-sinTheta,
cosTheta,
0,
0,
0,
1
];
};
var IDENTITY_MATRIX = rotationMatrix(0);
var matrixToBytes = (matrix) => {
return [
fixed_16_16(matrix[0]),
fixed_16_16(matrix[1]),
fixed_2_30(matrix[2]),
fixed_16_16(matrix[3]),
fixed_16_16(matrix[4]),
fixed_2_30(matrix[5]),
fixed_16_16(matrix[6]),
fixed_16_16(matrix[7]),
fixed_2_30(matrix[8])
];
};
var box = (type, contents, children) => ({
type,
contents: contents && new Uint8Array(contents.flat(10)),
children
});
var fullBox = (type, version, flags, contents, children) => box(
type,
[u8(version), u24(flags), contents != null ? contents : []],
children
);
var ftyp = (holdsHevc) => {
if (holdsHevc)
return box("ftyp", [
ascii("isom"),
// Major brand
u32(0),
// Minor version
ascii("iso4"),
// Compatible brand 1
ascii("hvc1")
// Compatible brand 2
]);
return box("ftyp", [
ascii("isom"),
// Major brand
u32(0),
// Minor version
ascii("isom"),
// Compatible brand 1
ascii("avc1"),
// Compatible brand 2
ascii("mp41")
// Compatible brand 3
]);
};
var mdat = () => ({ type: "mdat", largeSize: true });
var moov = (tracks, creationTime) => box("moov", null, [
mvhd(creationTime, tracks),
...tracks.map((x) => trak(x, creationTime))
]);
var mvhd = (creationTime, tracks) => {
let duration = intoTimescale(Math.max(
0,
...tracks.filter((x) => x.samples.length > 0).map((x) => last(x.samples).timestamp + last(x.samples).duration)
), GLOBAL_TIMESCALE);
let nextTrackId = Math.max(...tracks.map((x) => x.id)) + 1;
return fullBox("mvhd", 0, 0, [
u32(creationTime),
// Creation time
u32(creationTime),
// Modification time
u32(GLOBAL_TIMESCALE),
// Timescale
u32(duration),
// Duration
fixed_16_16(1),
// Preferred rate
fixed_8_8(1),
// Preferred volume
Array(10).fill(0),
// Reserved
matrixToBytes(IDENTITY_MATRIX),
// Matrix
Array(24).fill(0),
// Pre-defined
u32(nextTrackId)
// Next track ID
]);
};
var trak = (track, creationTime) => box("trak", null, [
tkhd(track, creationTime),
mdia(track, creationTime)
]);
var tkhd = (track, creationTime) => {
let lastSample = last(track.samples);
let durationInGlobalTimescale = intoTimescale(
lastSample ? lastSample.timestamp + lastSample.duration : 0,
GLOBAL_TIMESCALE
);
return fullBox("tkhd", 0, 3, [
u32(creationTime),
// Creation time
u32(creationTime),
// Modification time
u32(track.id),
// Track ID
u32(0),
// Reserved
u32(durationInGlobalTimescale),
// Duration
Array(8).fill(0),
// Reserved
u16(0),
// Layer
u16(0),
// Alternate group
fixed_8_8(track.info.type === "audio" ? 1 : 0),
// Volume
u16(0),
// Reserved
matrixToBytes(rotationMatrix(track.info.type === "video" ? track.info.rotation : 0)),
// Matrix
fixed_16_16(track.info.type === "video" ? track.info.width : 0),
// Track width
fixed_16_16(track.info.type === "video" ? track.info.height : 0)
// Track height
]);
};
var mdia = (track, creationTime) => box("mdia", null, [
mdhd(track, creationTime),
hdlr(track.info.type === "video" ? "vide" : "soun"),
minf(track)
]);
var mdhd = (track, creationTime) => {
let lastSample = last(track.samples);
let localDuration = intoTimescale(
lastSample ? lastSample.timestamp + lastSample.duration : 0,
track.timescale
);
return fullBox("mdhd", 0, 0, [
u32(creationTime),
// Creation time
u32(creationTime),
// Modification time
u32(track.timescale),
// Timescale
u32(localDuration),
// Duration
u16(21956),
// Language ("und", undetermined)
u16(0)
// Quality
]);
};
var hdlr = (componentSubtype) => fullBox("hdlr", 0, 0, [
ascii("mhlr"),
// Component type
ascii(componentSubtype),
// Component subtype
u32(0),
// Component manufacturer
u32(0),
// Component flags
u32(0),
// Component flags mask
ascii("mp4-muxer-hdlr")
// Component name
]);
var minf = (track) => box("minf", null, [
track.info.type === "video" ? vmhd() : smhd(),
dinf(),
stbl(track)
]);
var vmhd = () => fullBox("vmhd", 0, 1, [
u16(0),
// Graphics mode
u16(0),
// Opcolor R
u16(0),
// Opcolor G
u16(0)
// Opcolor B
]);
var smhd = () => fullBox("smhd", 0, 0, [
u16(0),
// Balance
u16(0)
// Reserved
]);
var dinf = () => box("dinf", null, [
dref()
]);
var dref = () => fullBox("dref", 0, 0, [
u32(1)
// Entry count
], [
url()
]);
var url = () => fullBox("url ", 0, 1);
var stbl = (track) => box("stbl", null, [
stsd(track),
stts(track),
stss(track),
stsc(track),
stsz(track),
stco(track)
]);
var stsd = (track) => fullBox("stsd", 0, 0, [
u32(1)
// Entry count
], [
track.info.type === "video" ? videoSampleDescription(
VIDEO_CODEC_TO_BOX_NAME[track.info.codec],
track
) : soundSampleDescription(
AUDIO_CODEC_TO_BOX_NAME[track.info.codec],
track
)
]);
var videoSampleDescription = (compressionType, track) => box(compressionType, [
Array(6).f