From 5978110de9d213acaa2bfb6f775b78f7c18377ef Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Sun, 8 Dec 2024 20:04:47 +0100 Subject: [PATCH] Rewrite reader logic, add separate reader for caching MP4 chunks, add more advanced drain iterators --- dev/demux.html | 4 +- dist/metamuxer.js | 332 +++++++++++++++++++++------------ dist/metamuxer.min.js | 10 +- dist/metamuxer.min.mjs | 10 +- dist/metamuxer.mjs | 332 +++++++++++++++++++++------------ src/input-format.ts | 6 +- src/input.ts | 7 +- src/isobmff/isobmff-demuxer.ts | 45 +++-- src/media-drain.ts | 123 ++++++++++-- src/misc.ts | 7 + src/reader.ts | 156 ++++++++-------- src/source.ts | 14 +- 12 files changed, 691 insertions(+), 355 deletions(-) diff --git a/dev/demux.html b/dev/demux.html index d7a4f71..7b24edf 100644 --- a/dev/demux.html +++ b/dev/demux.html @@ -27,13 +27,11 @@ const context = canvas.getContext('2d'); // Top-level for await loop inside the event listener - for await (const frame of drain.frames(await videoTrack.getDuration() - 10)) { + for await (const frame of drain.frames()) { context.drawImage(frame, 0, 0, width, height); frame.close(); } - console.log("Here??") - /* const videoTrack = await input.getPrimaryVideoTrack(); const drain = new Metamuxer.VideoFrameDrain(videoTrack); diff --git a/dist/metamuxer.js b/dist/metamuxer.js index c523ad2..22fd95a 100644 --- a/dist/metamuxer.js +++ b/dist/metamuxer.js @@ -224,6 +224,12 @@ var Metamuxer = (() => { }); return { promise, resolve, reject }; }; + var removeItem = (arr, item) => { + const index = arr.indexOf(item); + if (index !== -1) { + arr.splice(index, 1); + } + }; // src/subtitles.ts var cueBlockHeaderRegex = /(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g; @@ -4021,6 +4027,12 @@ ${cue.notes ?? ""}`; // src/source.ts var Source = class { + /** @internal */ + _sizePromise = null; + /** @internal */ + _getSize() { + return this._sizePromise ??= this._retrieveSize(); + } }; var ArrayBufferSource = class extends Source { constructor(buffer) { @@ -4032,7 +4044,7 @@ ${cue.notes ?? ""}`; return new Uint8Array(this.buffer, start, end - start); } /** @internal */ - async _getSize() { + async _retrieveSize() { return this.buffer.byteLength; } }; @@ -4048,7 +4060,7 @@ ${cue.notes ?? ""}`; return new Uint8Array(buffer); } /** @internal */ - async _getSize() { + async _retrieveSize() { return this.blob.size; } }; @@ -4133,6 +4145,103 @@ ${cue.notes ?? ""}`; } }; + // src/reader.ts + var PAGE_SIZE = 4096; + var Reader = class { + constructor(source, maxStorableBytes = Infinity) { + this.source = source; + this.maxStorableBytes = maxStorableBytes; + } + loadedSegments = []; + loadingSegments = []; + sourceSizePromise = null; + nextAge = 0; + totalStoredBytes = 0; + async loadRange(start, end) { + const alignedStart = Math.floor(start / PAGE_SIZE) * PAGE_SIZE; + let alignedEnd = Math.ceil(end / PAGE_SIZE) * PAGE_SIZE; + alignedEnd = Math.min(alignedEnd, await this.source._getSize()); + const matchingLoadingSegment = this.loadingSegments.find((x) => x.start <= alignedStart && x.end >= alignedEnd); + if (matchingLoadingSegment) { + await matchingLoadingSegment.promise; + return; + } + const encasingSegmentExists = this.loadedSegments.some((x) => x.start <= alignedStart && x.end >= alignedEnd); + if (encasingSegmentExists) { + return; + } + const bytesPromise = this.source._read(alignedStart, alignedEnd); + const loadingSegment = { start: alignedStart, end: alignedEnd, promise: bytesPromise }; + this.loadingSegments.push(loadingSegment); + const bytes2 = await bytesPromise; + removeItem(this.loadingSegments, loadingSegment); + this.insertIntoLoadedSegments(alignedStart, bytes2); + } + insertIntoLoadedSegments(start, bytes2) { + const segment = { + start, + end: start + bytes2.byteLength, + bytes: bytes2, + view: new DataView(bytes2.buffer), + age: this.nextAge++ + }; + let index = binarySearchLessOrEqual(this.loadedSegments, start, (x) => x.start); + if (index === -1 || this.loadedSegments[index].start < segment.start) { + index++; + } + this.loadedSegments.splice(index, 0, segment); + this.totalStoredBytes += bytes2.byteLength; + for (let i = index + 1; i < this.loadedSegments.length; i++) { + const otherSegment = this.loadedSegments[i]; + if (otherSegment.start >= segment.end) { + break; + } + if (segment.start <= otherSegment.start && otherSegment.end <= segment.end) { + this.loadedSegments.splice(i, 1); + i--; + } + } + while (this.totalStoredBytes > this.maxStorableBytes && this.loadedSegments.length > 1) { + let oldestSegment = null; + let oldestSegmentIndex = -1; + for (let i = 0; i < this.loadedSegments.length; i++) { + const candidate = this.loadedSegments[i]; + if (!oldestSegment || candidate.age < oldestSegment.age) { + oldestSegment = candidate; + oldestSegmentIndex = i; + } + } + assert(oldestSegment); + this.totalStoredBytes -= oldestSegment.bytes.byteLength; + this.loadedSegments.splice(oldestSegmentIndex, 1); + } + } + getViewAndOffset(start, end) { + const startIndex = binarySearchLessOrEqual(this.loadedSegments, start, (x) => x.start); + let segment = null; + if (startIndex !== -1) { + for (let i = startIndex; i < this.loadedSegments.length; i++) { + const candidate = this.loadedSegments[i]; + if (candidate.start > start) { + break; + } + if (end <= candidate.end) { + segment = candidate; + break; + } + } + } + if (!segment) { + throw new Error(`No segment loaded for range [${start}, ${end}).`); + } + segment.age = this.nextAge++; + return { + view: segment.view, + offset: segment.bytes.byteOffset + start - segment.start + }; + } + }; + // src/isobmff/isobmff-reader.ts var IsobmffReader = class { constructor(reader) { @@ -4234,9 +4343,11 @@ ${cue.notes ?? ""}`; metadataPromise = null; movieTimescale = -1; movieDurationInTimescale = -1; + chunkReader; constructor(input) { super(input); - this.isobmffReader = new IsobmffReader(input._reader); + this.isobmffReader = new IsobmffReader(input._mainReader); + this.chunkReader = new IsobmffReader(new Reader(input._source, 64 * 2 ** 20)); } async getDuration() { await this.readMetadata(); @@ -4261,7 +4372,7 @@ ${cue.notes ?? ""}`; } readMetadata() { return this.metadataPromise ??= (async () => { - const sourceSize = await this.isobmffReader.reader.getSourceSize(); + const sourceSize = await this.isobmffReader.reader.source._getSize(); while (this.isobmffReader.pos < sourceSize) { await this.isobmffReader.reader.loadRange(this.isobmffReader.pos, this.isobmffReader.pos + 16); const startPos = this.isobmffReader.pos; @@ -4837,9 +4948,13 @@ ${cue.notes ?? ""}`; if (!sampleInfo) { return null; } - const data = await this.internalTrack.demuxer.isobmffReader.reader.source._read( - sampleInfo.byteOffset, - sampleInfo.byteOffset + sampleInfo.byteSize + await this.internalTrack.demuxer.chunkReader.reader.loadRange( + sampleInfo.chunkOffset, + sampleInfo.chunkOffset + sampleInfo.chunkSize + ); + const data = this.internalTrack.demuxer.chunkReader.readRange( + sampleInfo.sampleOffset, + sampleInfo.sampleOffset + sampleInfo.sampleSize ); const chunk = new EncodedVideoChunk({ data, @@ -4940,20 +5055,28 @@ ${cue.notes ?? ""}`; assert(chunkEntry); const chunkIndex = chunkEntry.startChunkIndex + Math.floor((sampleIndex - chunkEntry.startSampleIndex) / chunkEntry.samplesPerChunk); const chunkOffset = sampleTable.chunkOffsets[chunkIndex]; + let chunkSize = 0; let sampleOffset = chunkOffset; if (sampleTable.sampleSizes.length === 1) { sampleOffset += sampleSize * (sampleIndex - chunkEntry.startSampleIndex); + chunkSize += sampleSize * chunkEntry.samplesPerChunk; } else { const startSampleIndex = chunkEntry.startSampleIndex + (chunkIndex - chunkEntry.startChunkIndex) * chunkEntry.samplesPerChunk; - for (let i = startSampleIndex; i < sampleIndex; i++) { - sampleOffset += sampleTable.sampleSizes[i]; + for (let i = startSampleIndex; i < startSampleIndex + chunkEntry.samplesPerChunk; i++) { + const sampleSize2 = sampleTable.sampleSizes[i]; + if (i < sampleIndex) { + sampleOffset += sampleSize2; + } + chunkSize += sampleSize2; } } return { presentationTimestamp, duration: timingEntry.delta, - byteOffset: sampleOffset, - byteSize: sampleSize, + sampleOffset, + sampleSize, + chunkOffset, + chunkSize, isKeyFrame: sampleTable.keySampleIndices ? binarySearchExact(sampleTable.keySampleIndices, sampleIndex, (x) => x) !== -1 : true }; }; @@ -4982,12 +5105,12 @@ ${cue.notes ?? ""}`; var IsobmffInputFormat = class extends InputFormat { /** @internal */ async _canReadInput(input) { - const sourceSize = await input._reader.getSourceSize(); + const sourceSize = await input._mainReader.source._getSize(); if (sourceSize < 8) { return false; } - await input._reader.loadRange(4, 8); - const isobmffReader = new IsobmffReader(input._reader); + await input._mainReader.loadRange(4, 8); + const isobmffReader = new IsobmffReader(input._mainReader); isobmffReader.pos = 4; const fourCc = isobmffReader.readAscii(4); return fourCc === "ftyp"; @@ -5013,106 +5136,22 @@ ${cue.notes ?? ""}`; var WEBM = MATROSKA; var ALL_FORMATS = [ISOBMFF, MKV]; - // src/reader.ts - var PAGE_SIZE = 4096; - var Reader = class { - constructor(source) { - this.source = source; - } - loadedSegments = []; - sourceSizePromise = null; - getSourceSize() { - if (this.sourceSizePromise) { - return this.sourceSizePromise; - } else { - return this.sourceSizePromise = this.source._getSize(); - } - } - async loadRange(start, end) { - let alignedStart = Math.floor(start / PAGE_SIZE) * PAGE_SIZE; - let alignedEnd = Math.ceil(end / PAGE_SIZE) * PAGE_SIZE; - alignedEnd = Math.min(alignedEnd, await this.getSourceSize()); - const thing = this.loadedSegments.find((x) => x.start <= alignedStart); - if (thing) { - alignedStart = Math.max(alignedStart, thing.end); - } - const thing2 = this.loadedSegments.find((x) => x.end >= alignedEnd); - if (thing2) { - alignedEnd = Math.min(alignedEnd, thing2.start); - } - if (alignedStart >= alignedEnd) { - return; - } - const bytes2 = await this.source._read(alignedStart, alignedEnd); - this.insertIntoLoadedSegments(alignedStart, bytes2); - } - insertIntoLoadedSegments(start, bytes2) { - const segment = { - start, - end: start + bytes2.byteLength, - bytes: bytes2, - view: new DataView(bytes2.buffer) - }; - let index = this.loadedSegments.findLastIndex((x) => x.start <= start); - this.loadedSegments.splice(index + 1, 0, segment); - if (index === -1 || this.loadedSegments[index].end < segment.start) { - index++; - } - const mergeSectionStartIndex = index; - const mergeSectionStart = this.loadedSegments[mergeSectionStartIndex].start; - let mergeSectionEndIndex = index; - let mergeSectionEnd = this.loadedSegments[mergeSectionEndIndex].end; - while (this.loadedSegments.length - 1 > mergeSectionEndIndex && this.loadedSegments[mergeSectionEndIndex + 1].start <= mergeSectionEnd) { - mergeSectionEndIndex++; - mergeSectionEnd = Math.max(mergeSectionEnd, this.loadedSegments[mergeSectionEndIndex].end); - } - if (mergeSectionStartIndex === mergeSectionEndIndex) { - return; - } - for (let i = mergeSectionStartIndex; i <= mergeSectionEndIndex; i++) { - const segment2 = this.loadedSegments[i]; - const coversEntireMergeSection = segment2.start === mergeSectionStart && segment2.end === mergeSectionEnd; - if (coversEntireMergeSection) { - this.loadedSegments.splice(i + 1, mergeSectionEndIndex - i); - this.loadedSegments.splice(mergeSectionStartIndex, i - mergeSectionStartIndex); - return; - } - } - const unifiedBytes = new Uint8Array(mergeSectionEnd - mergeSectionStart); - for (let i = mergeSectionStartIndex; i <= mergeSectionEndIndex; i++) { - const segment2 = this.loadedSegments[i]; - unifiedBytes.set(segment2.bytes, segment2.start - mergeSectionStart); - } - this.loadedSegments.splice(mergeSectionStartIndex + 1, mergeSectionEndIndex - mergeSectionStartIndex); - this.loadedSegments[mergeSectionStartIndex].end = mergeSectionEnd; - this.loadedSegments[mergeSectionStartIndex].bytes = unifiedBytes; - this.loadedSegments[mergeSectionStartIndex].view = new DataView(unifiedBytes.buffer); - } - getViewAndOffset(start, end) { - const segment = this.loadedSegments.find((x) => x.start <= start && end <= x.end); - if (!segment) { - throw new Error(`No segment loaded for range [${start}, ${end}).`); - } - return { - view: segment.view, - offset: segment.bytes.byteOffset + start - segment.start - }; - } - }; - // src/input.ts var Input = class { + /** @internal */ + _source; /** @internal */ _formats; /** @internal */ - _reader; + _mainReader; /** @internal */ _demuxerPromise = null; /** @internal */ _format = null; constructor(options) { this._formats = options.formats; - this._reader = new Reader(options.source); + this._source = options.source; + this._mainReader = new Reader(options.source); } /** @internal */ _getDemuxer() { @@ -5182,11 +5221,51 @@ ${cue.notes ?? ""}`; getNextKeyChunk(chunk) { return this.videoTrack._backing.getNextKeyChunk(chunk); } - async *chunks(startTimestamp = 0) { - let chunk = await this.getChunk(startTimestamp); - while (chunk) { - yield chunk; - chunk = await this.getNextChunk(chunk); + async *chunks(startChunk, endTimestamp = Infinity) { + const chunkQueue = []; + let { promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); + let { promise: queueDequeue, resolve: onQueueDequeue } = promiseWithResolvers(); + let ended = false; + const timestamps = []; + const maxQueueSize = () => Math.max(2, timestamps.length); + void (async () => { + let chunk = startChunk ?? await this.getFirstChunk(); + while (chunk && !ended) { + if (chunk.timestamp / 1e6 >= endTimestamp) { + break; + } + if (chunkQueue.length > maxQueueSize()) { + ({ promise: queueDequeue, resolve: onQueueDequeue } = promiseWithResolvers()); + await queueDequeue; + continue; + } + chunkQueue.push(chunk); + onQueueNotEmpty(); + ({ promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); + chunk = await this.getNextChunk(chunk); + } + ended = true; + onQueueNotEmpty(); + })(); + try { + while (true) { + if (chunkQueue.length > 0) { + yield chunkQueue.shift(); + const now = performance.now(); + timestamps.push(now); + while (timestamps.length > 0 && now - timestamps[0] >= 1e3) { + timestamps.shift(); + } + onQueueDequeue(); + } else if (!ended) { + await queueNotEmpty; + } else { + break; + } + } + } finally { + ended = true; + onQueueDequeue(); } } }; @@ -5249,18 +5328,21 @@ ${cue.notes ?? ""}`; decoder.close(); return result; } - async *frames(startTimestamp = 0) { + async *frames(startTimestamp = 0, endTimestamp = Infinity) { const frameQueue = []; let firstFrameQueued = false; let lastFrame = null; - let { promise: queueNonEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); + let { promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); let ended = false; const decoder = await this.createDecoder((frame) => { + const frameTimestamp = frame.timestamp / 1e6; + if (frameTimestamp >= endTimestamp) { + ended = true; + } if (ended) { frame.close(); return; } - const frameTimestamp = frame.timestamp / 1e6; if (lastFrame) { if (frameTimestamp > startTimestamp) { frameQueue.push(lastFrame); @@ -5276,26 +5358,44 @@ ${cue.notes ?? ""}`; lastFrame = firstFrameQueued ? null : frame; if (frameQueue.length > 0) { onQueueNotEmpty(); - ({ promise: queueNonEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); + ({ promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); } }); - const keyChunk = await this.videoTrack._backing.getKeyChunk(startTimestamp); + const keyChunk = await this.videoTrack._backing.getKeyChunk(startTimestamp) ?? await this.videoTrack._backing.getFirstChunk(); if (!keyChunk) { return; } let decoderIsFlushed = false; void (async () => { let currentChunk = keyChunk; + let chunksEndTimestamp = Infinity; + if (endTimestamp < Infinity) { + const endFrame = await this.videoTrack._backing.getChunk(endTimestamp); + const endKeyFrame = !endFrame ? null : endFrame.type === "key" && endFrame.timestamp / 1e6 === endTimestamp ? endFrame : await this.videoTrack._backing.getNextKeyChunk(endFrame); + if (endKeyFrame) { + chunksEndTimestamp = endKeyFrame.timestamp / 1e6; + } + } + const chunkDrain = new EncodedVideoChunkDrain(this.videoTrack); + const chunks = chunkDrain.chunks(keyChunk, chunksEndTimestamp); + await chunks.next(); while (currentChunk && !ended) { decoder.decode(currentChunk); if (decoder.decodeQueueSize >= 10) { await new Promise((resolve) => decoder.addEventListener("dequeue", resolve, { once: true })); } - const nextChunk = await this.videoTrack._backing.getNextChunk(currentChunk); - currentChunk = nextChunk; + const chunkResult = await chunks.next(); + if (chunkResult.done) { + break; + } + currentChunk = chunkResult.value; } + await chunks.return(); await decoder.flush(); decoder.close(); + if (!firstFrameQueued && lastFrame) { + frameQueue.push(lastFrame); + } decoderIsFlushed = true; onQueueNotEmpty(); })(); @@ -5304,7 +5404,7 @@ ${cue.notes ?? ""}`; if (frameQueue.length > 0) { yield frameQueue.shift(); } else if (!decoderIsFlushed) { - await queueNonEmpty; + await queueNotEmpty; } else { break; } diff --git a/dist/metamuxer.min.js b/dist/metamuxer.min.js index 67d7f32..023af7c 100644 --- a/dist/metamuxer.min.js +++ b/dist/metamuxer.min.js @@ -1,10 +1,10 @@ -"use strict";var Metamuxer=(()=>{var et=Object.defineProperty;var tr=Object.getOwnPropertyDescriptor;var rr=Object.getOwnPropertyNames;var ir=Object.prototype.hasOwnProperty;var sr=(r,e)=>{for(var t in e)et(r,t,{get:e[t],enumerable:!0})},or=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of rr(e))!ir.call(r,s)&&s!==t&&et(r,s,{get:()=>e[s],enumerable:!(i=tr(e,s))||i.enumerable});return r};var nr=r=>or(et({},"__esModule",{value:!0}),r);var ki={};sr(ki,{ALL_FORMATS:()=>er,AUDIO_CODECS:()=>L,ArrayBufferSource:()=>Ne,ArrayBufferTarget:()=>Y,AudioBufferSource:()=>Ue,AudioDataSource:()=>Be,AudioSource:()=>O,BlobSource:()=>He,CanvasSource:()=>Re,EncodedAudioChunkSource:()=>ze,EncodedVideoChunkDrain:()=>Ze,EncodedVideoChunkSource:()=>Ve,ISOBMFF:()=>he,Input:()=>Ye,MATROSKA:()=>qe,MKV:()=>kt,MOV:()=>Zt,MP4:()=>Yt,MediaSource:()=>Q,MediaStreamAudioTrackSource:()=>De,MediaStreamVideoTrackSource:()=>Pe,MkvOutputFormat:()=>ue,Mp4OutputFormat:()=>Oe,Output:()=>We,OutputFormat:()=>R,SUBTITLE_CODECS:()=>ne,Source:()=>J,StreamTarget:()=>ye,SubtitleSource:()=>j,Target:()=>M,TextSubtitleSource:()=>Fe,VIDEO_CODECS:()=>H,VideoFrameDrain:()=>Je,VideoFrameSource:()=>Me,VideoSource:()=>I,WEBM:()=>Jt,WebMOutputFormat:()=>$});function l(r){if(!r)throw new Error("Assertion failed.")}var y=r=>r&&r[r.length-1],P=r=>r>=0&&r<2**32,z=(r,e,t)=>{let i=0;for(let s=e;s>a;i<<=1,i|=c}return i},gt=(r,e,t,i)=>{for(let s=e;s>t-s-1<r instanceof ArrayBuffer?new Uint8Array(r):new Uint8Array(r.buffer,r.byteOffset,r.byteLength),v=new TextEncoder,tt=r=>Object.fromEntries(Object.entries(r).map(([e,t])=>[t,e])),U={bt709:1,bt470bg:5,smpte170m:6},Tt=tt(U),D={bt709:1,smpte170m:6,"iec61966-2-1":13},xt=tt(D),F={rgb:0,bt709:1,bt470bg:5,smpte170m:6},Ct=tt(F),be=r=>!!r&&!!r.primaries&&!!r.transfer&&!!r.matrix&&r.fullRange!==void 0,rt=r=>r instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&r instanceof SharedArrayBuffer||ArrayBuffer.isView(r)&&!(r instanceof DataView),K=class{currentPromise=Promise.resolve();async acquire(){let e,t=new Promise(s=>{e=s}),i=this.currentPromise;return this.currentPromise=t,await i,e}},V=r=>{let e=r*(Math.PI/180),t=Math.cos(e),i=Math.sin(e);return[t,i,0,-i,t,0,0,0,1]},it=V(0),wt=r=>[...r].map(e=>e.toString(16).padStart(2,"0")).join(""),St=r=>(r=r>>1&1431655765|(r&1431655765)<<1,r=r>>2&858993459|(r&858993459)<<2,r=r>>4&252645135|(r&252645135)<<4,r=r>>8&16711935|(r&16711935)<<8,r=r>>16&65535|(r&65535)<<16,r>>>0),yt=(r,e,t)=>{let i=0,s=r.length-1,o=-1;for(;i<=s;){let n=i+s>>1,a=t(r[n]);a===e?(o=n,s=n-1):a{let i=-1,s=0,o=r.length-1;for(;s<=o;){let n=s+(o-s+1)/2|0;t(r[n])<=e?(i=n,s=n+1):o=n-1}return i},st=()=>{let r,e;return{promise:new Promise((i,s)=>{r=i,e=s}),resolve:r,reject:e}};var re=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,ar=/^WEBVTT(.|\n)*?\n{2}/,q=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,ke=class{options;preambleText=null;preambleEmitted=!1;constructor(e){this.options=e}parse(e){e=e.replaceAll(`\r +"use strict";var Metamuxer=(()=>{var rt=Object.defineProperty;var ir=Object.getOwnPropertyDescriptor;var sr=Object.getOwnPropertyNames;var nr=Object.prototype.hasOwnProperty;var or=(r,e)=>{for(var t in e)rt(r,t,{get:e[t],enumerable:!0})},ar=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of sr(e))!nr.call(r,s)&&s!==t&&rt(r,s,{get:()=>e[s],enumerable:!(i=ir(e,s))||i.enumerable});return r};var cr=r=>ar(rt({},"__esModule",{value:!0}),r);var Ti={};or(Ti,{ALL_FORMATS:()=>rr,AUDIO_CODECS:()=>j,ArrayBufferSource:()=>$e,ArrayBufferTarget:()=>te,AudioBufferSource:()=>Ne,AudioDataSource:()=>We,AudioSource:()=>R,BlobSource:()=>je,CanvasSource:()=>Ue,EncodedAudioChunkSource:()=>Fe,EncodedVideoChunkDrain:()=>Te,EncodedVideoChunkSource:()=>ze,ISOBMFF:()=>ge,Input:()=>et,MATROSKA:()=>Je,MKV:()=>gt,MOV:()=>er,MP4:()=>Jt,MediaSource:()=>q,MediaStreamAudioTrackSource:()=>He,MediaStreamVideoTrackSource:()=>De,MkvOutputFormat:()=>fe,Mp4OutputFormat:()=>Pe,Output:()=>Qe,OutputFormat:()=>z,SUBTITLE_CODECS:()=>de,Source:()=>ie,StreamTarget:()=>Ee,SubtitleSource:()=>X,Target:()=>P,TextSubtitleSource:()=>Le,VIDEO_CODECS:()=>$,VideoFrameDrain:()=>tt,VideoFrameSource:()=>Be,VideoSource:()=>V,WEBM:()=>tr,WebMOutputFormat:()=>K});function d(r){if(!r)throw new Error("Assertion failed.")}var v=r=>r&&r[r.length-1],U=r=>r>=0&&r<2**32,D=(r,e,t)=>{let i=0;for(let s=e;s>a;i<<=1,i|=c}return i},Tt=(r,e,t,i)=>{for(let s=e;s>t-s-1<r instanceof ArrayBuffer?new Uint8Array(r):new Uint8Array(r.buffer,r.byteOffset,r.byteLength),_=new TextEncoder,it=r=>Object.fromEntries(Object.entries(r).map(([e,t])=>[t,e])),W={bt709:1,bt470bg:5,smpte170m:6},xt=it(W),N={bt709:1,smpte170m:6,"iec61966-2-1":13},Ct=it(N),H={rgb:0,bt709:1,bt470bg:5,smpte170m:6},wt=it(H),xe=r=>!!r&&!!r.primaries&&!!r.transfer&&!!r.matrix&&r.fullRange!==void 0,st=r=>r instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&r instanceof SharedArrayBuffer||ArrayBuffer.isView(r)&&!(r instanceof DataView),Y=class{currentPromise=Promise.resolve();async acquire(){let e,t=new Promise(s=>{e=s}),i=this.currentPromise;return this.currentPromise=t,await i,e}},M=r=>{let e=r*(Math.PI/180),t=Math.cos(e),i=Math.sin(e);return[t,i,0,-i,t,0,0,0,1]},nt=M(0),St=r=>[...r].map(e=>e.toString(16).padStart(2,"0")).join(""),yt=r=>(r=r>>1&1431655765|(r&1431655765)<<1,r=r>>2&858993459|(r&858993459)<<2,r=r>>4&252645135|(r&252645135)<<4,r=r>>8&16711935|(r&16711935)<<8,r=r>>16&65535|(r&65535)<<16,r>>>0),vt=(r,e,t)=>{let i=0,s=r.length-1,n=-1;for(;i<=s;){let o=i+s>>1,a=t(r[o]);a===e?(n=o,s=o-1):a{let i=-1,s=0,n=r.length-1;for(;s<=n;){let o=s+(n-s+1)/2|0;t(r[o])<=e?(i=o,s=o+1):n=o-1}return i},L=()=>{let r,e;return{promise:new Promise((i,s)=>{r=i,e=s}),resolve:r,reject:e}},_t=(r,e)=>{let t=r.indexOf(e);t!==-1&&r.splice(t,1)};var oe=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,ur=/^WEBVTT(.|\n)*?\n{2}/,Z=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,Ce=class{options;preambleText=null;preambleEmitted=!1;constructor(e){this.options=e}parse(e){e=e.replaceAll(`\r `,` `).replaceAll("\r",` -`),re.lastIndex=0;let t;if(!this.preambleText){if(!ar.test(e)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}t=re.exec(e);let i=e.slice(0,t?.index??e.length).trimEnd();if(!i){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=i,t&&(e=e.slice(t.index),re.lastIndex=0)}for(;t=re.exec(e);){let i=e.slice(0,t.index),s=t[1],o=t.index+t[0].length,n=e.indexOf(` -`,o)+1,a=e.slice(o,n).trim(),c=e.indexOf(` +`),oe.lastIndex=0;let t;if(!this.preambleText){if(!ur.test(e)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}t=oe.exec(e);let i=e.slice(0,t?.index??e.length).trimEnd();if(!i){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=i,t&&(e=e.slice(t.index),oe.lastIndex=0)}for(;t=oe.exec(e);){let i=e.slice(0,t.index),s=t[1],n=t.index+t[0].length,o=e.indexOf(` +`,n)+1,a=e.slice(n,o).trim(),c=e.indexOf(` -`,o);c===-1&&(c=e.length);let u=ge(t[2]),f=ge(t[3])-u,T=e.slice(n,c).trim();e=e.slice(c).trimStart(),re.lastIndex=0;let C={timestamp:u/1e3,duration:f/1e3,text:T,identifier:s,settings:a,notes:i},k={};this.preambleEmitted||(k.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(C,k)}}},cr=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,ge=r=>{let e=cr.exec(r);if(!e)throw new Error("Expected match.");return 60*60*1e3*Number(e[1]||"0")+60*1e3*Number(e[2])+1e3*Number(e[3])+Number(e[4])},Te=r=>{let e=Math.floor(r/36e5),t=Math.floor(r%(60*60*1e3)/(60*1e3)),i=Math.floor(r%(60*1e3)/1e3),s=r%1e3;return e.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+":"+i.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var ie=class{constructor(e){this.writer=e}helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;writeU32(e){this.helperView.setUint32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(e){this.helperView.setUint32(0,Math.floor(e/2**32),!1),this.helperView.setUint32(4,e,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(e){for(let t=0;t[(r%256+256)%256],p=r=>(E.setUint16(0,r,!1),[h[0],h[1]]),ur=r=>(E.setInt16(0,r,!1),[h[0],h[1]]),_t=r=>(E.setUint32(0,r,!1),[h[1],h[2],h[3]]),m=r=>(E.setUint32(0,r,!1),[h[0],h[1],h[2],h[3]]),At=r=>(E.setInt32(0,r,!1),[h[0],h[1],h[2],h[3]]),N=r=>(E.setUint32(0,Math.floor(r/2**32),!1),E.setUint32(4,r,!1),[h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7]]),at=r=>(E.setInt16(0,2**8*r,!1),[h[0],h[1]]),A=r=>(E.setInt32(0,2**16*r,!1),[h[0],h[1],h[2],h[3]]),ot=r=>(E.setInt32(0,2**30*r,!1),[h[0],h[1],h[2],h[3]]),nt=(r,e)=>{let t=[],i=r;do{let s=i&127;i>>=7,t.length>0&&(s|=128),t.push(s),e!==void 0&&e--}while(i>0||e);return t.reverse()},S=(r,e=!1)=>{let t=Array(r.length).fill(null).map((i,s)=>r.charCodeAt(s));return e&&t.push(0),t},ct=r=>{let e=null;for(let t of r)(!e||t.timestamp>e.timestamp)&&(e=t);return e},Et=r=>[A(r[0]),A(r[1]),ot(r[2]),A(r[3]),A(r[4]),ot(r[5]),A(r[6]),A(r[7]),ot(r[8])],b=(r,e,t)=>({type:r,contents:e&&new Uint8Array(e.flat(10)),children:t}),g=(r,e,t,i,s)=>b(r,[x(e),_t(t),i??[]],s),It=r=>r.fragmented?b("ftyp",[S("iso5"),m(512),S("iso5"),S("iso6"),S("mp41")]):b("ftyp",[S("isom"),m(512),S("isom"),r.holdsAvc?S("avc1"):[],S("mp41")]),Ce=r=>({type:"mdat",largeSize:r}),Ot=r=>({type:"free",size:r}),se=(r,e,t=!1)=>b("moov",void 0,[dr(e,r),...r.map(i=>lr(i,e)),t?$r(r):null]),dr=(r,e)=>{let t=_(Math.max(0,...e.filter(n=>n.samples.length>0).map(n=>{let a=ct(n.samples);return a.timestamp+a.duration})),xe),i=Math.max(0,...e.map(n=>n.track.id))+1,s=!P(r)||!P(t),o=s?N:m;return g("mvhd",+s,0,[o(r),o(r),m(xe),o(t),A(1),at(1),Array(10).fill(0),Et(it),Array(24).fill(0),m(i)])},lr=(r,e)=>b("trak",void 0,[mr(r,e),fr(r,e)]),mr=(r,e)=>{let t=ct(r.samples),i=_(t?t.timestamp+t.duration:0,xe),s=!P(e)||!P(i),o=s?N:m,n;if(r.type==="video"){let a=r.track.metadata.rotation;n=a===void 0||typeof a=="number"?V(a??0):a}else n=it;return g("tkhd",+s,3,[o(e),o(e),m(r.track.id),m(0),o(i),Array(8).fill(0),p(0),p(r.track.id),at(r.type==="audio"?1:0),p(0),Et(n),A(r.type==="video"?r.info.width:0),A(r.type==="video"?r.info.height:0)])},fr=(r,e)=>b("mdia",void 0,[hr(r,e),kr(r),gr(r)]),hr=(r,e)=>{let t=ct(r.samples),i=_(t?t.timestamp+t.duration:0,r.timescale),s=!P(e)||!P(i),o=s?N:m;return g("mdhd",+s,0,[o(e),o(e),m(r.timescale),o(i),p(21956),p(0)])},pr={video:"vide",audio:"soun",subtitle:"text"},br={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},kr=r=>g("hdlr",0,0,[S("mhlr"),S(pr[r.type]),m(0),m(0),m(0),S(br[r.type],!0)]),gr=r=>b("minf",void 0,[wr[r.type](),Sr(),_r(r)]),Tr=()=>g("vmhd",0,1,[p(0),p(0),p(0),p(0)]),xr=()=>g("smhd",0,0,[p(0),p(0)]),Cr=()=>g("nmhd",0,0),wr={video:Tr,audio:xr,subtitle:Cr},Sr=()=>b("dinf",void 0,[yr()]),yr=()=>g("dref",0,0,[m(1)],[vr()]),vr=()=>g("url ",0,1),_r=r=>{let e=r.compositionTimeOffsetTable.length>1||r.compositionTimeOffsetTable.some(t=>t.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[Ar(r),Dr(r),Fr(r),Wr(r),Nr(r),Hr(r),e?Lr(r):null])},Ar=r=>{let e;return r.type==="video"?e=Er(Jr[r.track.source._codec],r):r.type==="audio"?e=Rr(ti[r.track.source._codec],r):r.type==="subtitle"&&(e=Br(ii[r.track.source._codec],r)),l(e),g("stsd",0,0,[m(1)],[e])},Er=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),Array(12).fill(0),p(e.info.width),p(e.info.height),m(4718592),m(4718592),m(0),p(1),Array(32).fill(0),p(24),ur(65535)],[ei[e.track.source._codec](e),be(e.info.decoderConfig.colorSpace)?Ir(e):null]),Ir=r=>b("colr",[S("nclx"),p(U[r.info.decoderConfig.colorSpace.primaries]),p(D[r.info.decoderConfig.colorSpace.transfer]),p(F[r.info.decoderConfig.colorSpace.matrix]),x((r.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),Or=r=>r.info.decoderConfig&&b("avcC",[...B(r.info.decoderConfig.description)]),Vr=r=>r.info.decoderConfig&&b("hvcC",[...B(r.info.decoderConfig.description)]),vt=r=>{if(!r.info.decoderConfig)return null;let e=r.info.decoderConfig;l(e.colorSpace);let t=e.codec.split("."),i=Number(t[1]),s=Number(t[2]),a=(Number(t[3])<<4)+(0<<1)+Number(e.colorSpace.fullRange);return g("vpcC",1,0,[x(i),x(s),x(a),x(2),x(2),x(2),p(0)])},Mr=()=>b("av1C",[129,0,0,0]),Rr=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),m(0),p(e.info.numberOfChannels),p(16),p(0),p(0),A(e.info.sampleRate)],[ri[e.track.source._codec](e)]),Pr=r=>{let t=[...B(r.info.decoderConfig.description??new ArrayBuffer(0))];return t=[...x(64),...x(21),..._t(0),...m(0),...m(0),...x(5),...nt(t.length),...t],t=[...p(1),...x(0),...x(4),...nt(t.length),...t,...x(6),...x(1),...x(2)],t=[...x(3),...nt(t.length),...t],g("esds",0,0,t)},zr=r=>{let e=3840,t=0,i=r.info.decoderConfig?.description;if(i){l(i.byteLength>=18);let s=ArrayBuffer.isView(i)?new DataView(i.buffer,i.byteOffset,i.byteLength):new DataView(i);e=s.getUint16(10,!0),t=s.getInt16(14,!0)}return b("dOps",[x(0),x(r.info.numberOfChannels),p(e),m(r.info.sampleRate),at(t),x(0)])},Br=(r,e)=>b(r,[Array(6).fill(0),p(1)],[si[e.track.source._codec](e)]),Ur=r=>b("vttC",[...v.encode(r.info.config.description)]);var Dr=r=>g("stts",0,0,[m(r.timeToSampleTable.length),r.timeToSampleTable.map(e=>[m(e.sampleCount),m(e.sampleDelta)])]),Fr=r=>{if(r.samples.every(t=>t.type==="key"))return null;let e=[...r.samples.entries()].filter(([,t])=>t.type==="key");return g("stss",0,0,[m(e.length),e.map(([t])=>m(t+1))])},Wr=r=>g("stsc",0,0,[m(r.compactlyCodedChunkTable.length),r.compactlyCodedChunkTable.map(e=>[m(e.firstChunk),m(e.samplesPerChunk),m(1)])]),Nr=r=>g("stsz",0,0,[m(0),m(r.samples.length),r.samples.map(e=>m(e.size))]),Hr=r=>r.finalizedChunks.length>0&&y(r.finalizedChunks).offset>=2**32?g("co64",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>N(e.offset))]):g("stco",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>m(e.offset))]),Lr=r=>g("ctts",0,0,[m(r.compositionTimeOffsetTable.length),r.compositionTimeOffsetTable.map(e=>[m(e.sampleCount),m(e.sampleCompositionTimeOffset)])]),$r=r=>b("mvex",void 0,r.map(Qr)),Qr=r=>g("trex",0,0,[m(r.track.id),m(1),m(0),m(0),m(0)]),ut=(r,e)=>b("moof",void 0,[jr(r),...e.map(Kr)]),jr=r=>g("mfhd",0,0,[m(r)]),Vt=r=>{let e=0,t=0,i=0,s=0,o=r.type==="delta";return t|=+o,o?e|=1:e|=2,e<<24|t<<16|i<<8|s},Kr=r=>b("traf",void 0,[qr(r),Xr(r),Gr(r)]),qr=r=>{l(r.currentChunk);let e=0;e|=8,e|=16,e|=32,e|=131072;let t=r.currentChunk.samples[1]??r.currentChunk.samples[0],i={duration:t.timescaleUnitsToNextSample,size:t.size,flags:Vt(t)};return g("tfhd",0,e,[m(r.track.id),m(i.duration),m(i.size),m(i.flags)])},Xr=r=>(l(r.currentChunk),g("tfdt",1,0,[N(_(r.currentChunk.startTimestamp,r.timescale))])),Gr=r=>{l(r.currentChunk);let e=r.currentChunk.samples.map(w=>w.timescaleUnitsToNextSample),t=r.currentChunk.samples.map(w=>w.size),i=r.currentChunk.samples.map(Vt),s=r.currentChunk.samples.map(w=>_(w.timestamp-w.decodeTimestamp,r.timescale)),o=new Set(e),n=new Set(t),a=new Set(i),c=new Set(s),u=a.size===2&&i[0]!==i[1],d=o.size>1,f=n.size>1,T=!u&&a.size>1,C=c.size>1||[...c].some(w=>w!==0),k=0;return k|=1,k|=4*+u,k|=256*+d,k|=512*+f,k|=1024*+T,k|=2048*+C,g("trun",1,k,[m(r.currentChunk.samples.length),m(r.currentChunk.offset-r.currentChunk.moofOffset||0),u?m(i[0]):[],r.currentChunk.samples.map((w,pe)=>[d?m(e[pe]):[],f?m(t[pe]):[],T?m(i[pe]):[],C?At(s[pe]):[]])])},Mt=r=>b("mfra",void 0,[...r.map(Yr),Zr()]),Yr=(r,e)=>g("tfra",1,0,[m(r.track.id),m(63),m(r.finalizedChunks.length),r.finalizedChunks.map(i=>[N(_(i.startTimestamp,r.timescale)),N(i.moofOffset),m(e+1),m(1),m(1)])]),Zr=()=>g("mfro",0,0,[m(0)]),Rt=()=>b("vtte"),Pt=(r,e,t,i,s)=>b("vttc",void 0,[s!==null?b("vsid",[At(s)]):null,t!==null?b("iden",[...v.encode(t)]):null,e!==null?b("ctim",[...v.encode(Te(e))]):null,i!==null?b("sttg",[...v.encode(i)]):null,b("payl",[...v.encode(r)])]),zt=r=>b("vtta",[...v.encode(r)]),Jr={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},ei={avc:Or,hevc:Vr,vp8:vt,vp9:vt,av1:Mr},ti={aac:"mp4a",opus:"Opus"},ri={aac:Pr,opus:zr},ii={webvtt:"wvtt"},si={webvtt:Ur};var X=class{output;mutex=new K;constructor(e){this.output=e}beforeTrackAdd(e){}onTrackClose(e){}trackTimestampInfo=new WeakMap;validateAndNormalizeTimestamp(e,t,i){let s=t/1e6,o=this.trackTimestampInfo.get(e);if(!o){if(!i)throw new Error("First frame must be a key frame.");if(this.timestampsMustStartAtZero&&s>0)throw new Error(`Timestamps must start at zero (got ${s}s).`);o={timestampOffset:s,maxTimestamp:e.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:e.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(e,o)}if(e.source._offsetTimestamps&&(s-=o.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(si.start-s.start);e.push({start:t[0].start,size:t[0].data.byteLength});for(let i=1;ic.start<=t&&tni){for(let c=0;c=e.written[o+1].start;)e.written[o].end=Math.max(e.written[o].end,e.written[o+1].end),e.written.splice(o+1,1)}createChunk(e){let i={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(i),this.chunks.sort((s,o)=>s.start-o.start),this.chunks.indexOf(i)}queueChunksForFlush(e=!1){l(this.writer);for(let t=0;t{if(r==="avc"){let o=Math.ceil(e/16)*Math.ceil(t/16),n=Bt.find(f=>o<=f.maxMacroblocks&&i<=f.maxBitrate)??y(Bt),a=n?n.level:0,c="64".padStart(2,"0"),u="00",d=a.toString(16).padStart(2,"0");return`avc1.${c}${u}${d}`}else if(r==="hevc"){let s="",n="6",a=e*t,c=Ut.find(d=>a<=d.maxPictureSize&&i<=d.maxBitrate)??y(Ut);return`hev1.${s}1.${n}.${c.tier}${c.level}.B0`}else{if(r==="vp8")return"vp8";if(r==="vp9"){let s="00",o=e*t,n=Dt.find(c=>o<=c.maxPictureSize&&i<=c.maxBitrate)??y(Dt);return`vp09.${s}.${n.level}.08`}else if(r==="av1"){let o=e*t,n=Ft.find(c=>o<=c.maxPictureSize&&i<=c.maxBitrate)??y(Ft);return`av01.0.${n.level.toString().padStart(2,"0")}${n.tier}.08`}}throw new TypeError(`Unhandled codec '${r}'.`)},Nt=(r,e)=>{if(r==="avc"){if(!e||e.byteLength<4)throw new TypeError("AVC description must be at least 4 bytes long.");return`avc1.${wt(e.subarray(1,4))}`}else if(r==="hevc"){if(!e)throw new TypeError("HEVC description must be provided.");let t=new DataView(e.buffer,e.byteOffset,e.byteLength),i="hev1.",s=e[1]>>6&3,o=e[1]&31;i+=["","A","B","C"][s]+o,i+=".";let n=St(t.getUint32(2));i+=n.toString(16),i+=".";let a=e[1]>>5&1,c=e[12];i+=a===0?"L":"H",i+=c,i+=".";let u=[];for(let d=0;d<6;d++){let f=e[d+13];u.push(f)}for(;u[u.length-1]===0;)u.pop();return i+=u.map(d=>d.toString(16)).join("."),i}throw new TypeError(`Unhandled codec '${r}'.`)},Ht=(r,e,t)=>{if(r==="aac")return e>=2&&t<=24e3?"mp4a.40.29":t<=24e3?"mp4a.40.5":"mp4a.40.2";if(r==="opus")return"opus";if(r==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${r}'.`)},Lt=(r,e)=>{if(r==="aac"){if(!e||e.byteLength<2)throw new TypeError("AAC description must be at least 2 bytes long.");return`mp4a.40.${e[0]>>3}`}else{if(r==="opus")return"opus";if(r==="vorbis")return"vorbis"}throw new TypeError(`Unhandled codec '${r}'.`)},$t=r=>r==="avc"?{avc:{format:"avc"}}:r==="hevc"?{hevc:{format:"hevc"}}:{},Qt=r=>r==="aac"?{aac:{format:"aac"}}:r==="opus"?{opus:{format:"opus"}}:{},ve=r=>{if(!r)throw new TypeError("Video chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Video chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Video chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Video chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.codedWidth)||r.decoderConfig.codedWidth<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");if(!Number.isInteger(r.decoderConfig.codedHeight)||r.decoderConfig.codedHeight<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");if(r.decoderConfig.description!==void 0&&!rt(r.decoderConfig.description))throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.colorSpace!==void 0){let{colorSpace:e}=r.decoderConfig;if(typeof e!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let t=Object.keys(U);if(e.primaries!=null&&!t.includes(e.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${t.join(", ")}.`);let i=Object.keys(D);if(e.transfer!=null&&!i.includes(e.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${i.join(", ")}.`);let s=Object.keys(F);if(e.matrix!=null&&!s.includes(e.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(e.fullRange!=null&&typeof e.fullRange!="boolean")throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.")}if((r.decoderConfig.codec.startsWith("avc1")||r.decoderConfig.codec.startsWith("avc3"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for AVC must include a description, which is expected to be an AVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec.startsWith("hev1")||r.decoderConfig.codec.startsWith("hvc1"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for HEVC must include a description, which is expected to be an HEVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec==="vp8"||r.decoderConfig.codec.startsWith("vp09"))&&r.decoderConfig.colorSpace===void 0)throw new TypeError("Video chunk metadata decoder configuration for VP8/VP9 must include a colorSpace.")},_e=r=>{if(!r)throw new TypeError("Audio chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Audio chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Audio chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Audio chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.sampleRate)||r.decoderConfig.sampleRate<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");if(!Number.isInteger(r.decoderConfig.numberOfChannels)||r.decoderConfig.numberOfChannels<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");if(r.decoderConfig.description!==void 0&&!rt(r.decoderConfig.description))throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.codec.startsWith("mp4a")&&!r.decoderConfig.description)throw new TypeError("Audio chunk metadata decoder configuration for AAC must include a description, which is expected to be an AudioSpecificConfig as specified in ISO 14496-3.");if(r.decoderConfig.codec==="opus"&&r.decoderConfig.description&&r.decoderConfig.description.byteLength<18)throw new TypeError("Invalid decoder description provided for Opus; must be at least 18 bytes long.")},Ae=r=>{if(!r)throw new TypeError("Subtitle metadata must be provided.");if(typeof r!="object")throw new TypeError("Subtitle metadata must be an object.");if(!r.config)throw new TypeError("Subtitle metadata must include a config object.");if(typeof r.config!="object")throw new TypeError("Subtitle metadata config must be an object.");if(typeof r.config.description!="string")throw new TypeError("Subtitle metadata config description must be a string.")};var xe=1e3,ai=2082844800,_=(r,e,t=!0)=>{let i=r*e;return t?Math.round(i):i},Ee=class extends X{timestampsMustStartAtZero=!0;writer;boxWriter;fastStart;auxTarget=new Y;auxWriter=this.auxTarget._createWriter();auxBoxWriter=new ie(this.auxWriter);ftypSize=null;mdat=null;trackDatas=[];creationTime=Math.floor(Date.now()/1e3)+ai;finalizedChunks=[];nextFragmentNumber=1;constructor(e,t){super(e),this.writer=e._writer,this.boxWriter=new ie(this.writer);let i=this.writer instanceof G?"in-memory":!1;this.fastStart=t._options.fastStart??i,(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),t=this.output._tracks.some(i=>i.type==="video"&&i.source._codec==="avc");this.boxWriter.writeBox(It({holdsAvc:t,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=Ce(!1):this.fastStart==="fragmented"||(this.mdat=Ce(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;ve(t),l(t),l(t.decoderConfig),l(t.decoderConfig.codedWidth!==void 0),l(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},timescale:e.metadata.frameRate??57600,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;_e(t),l(t),l(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},timescale:t.decoderConfig.sampleRate,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;Ae(t),l(t),l(t.config);let s={track:e,type:"subtitle",info:{config:t.config},timescale:1e3,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[],lastCueEndTimestamp:0,cueQueue:[],nextSourceId:0,cueToSourceId:new WeakMap};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),this.validateAndNormalizeTimestamp(e,0,!0),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=this.validateAndNormalizeTimestamp(o.track,t.timestamp,t.type==="key"),c=this.createSampleForTrack(o,n,a,(t.duration??0)/1e6,t.type);await this.registerSample(o,c)}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=t.type,c=this.validateAndNormalizeTimestamp(o.track,t.timestamp,a==="key"),u=this.createSampleForTrack(o,n,c,(t.duration??0)/1e6,a);await this.registerSample(o,u)}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,i);this.validateAndNormalizeTimestamp(o.track,1e6*t.timestamp,!0),e.source._codec==="webvtt"&&(o.cueQueue.push(t),await this.processWebVTTCues(o,t.timestamp))}finally{s()}}async processWebVTTCues(e,t){for(;e.cueQueue.length>0;){let i=new Set([]);for(let u of e.cueQueue)l(u.timestamp<=t),l(e.lastCueEndTimestamp<=u.timestamp+u.duration),i.add(Math.max(u.timestamp,e.lastCueEndTimestamp)),i.add(u.timestamp+u.duration);let s=[...i].sort((u,d)=>u-d),o=s[0],n=s[1]??o;if(t=n)break;q.lastIndex=0;let f=q.test(d.text),T=d.timestamp+d.duration,C=e.cueToSourceId.get(d);if(C===void 0&&ni.timestamp).sort((i,s)=>i-s);for(let i=0;i{if(e===n)return t.type==="key";let a=n.sampleQueue[0];return a&&a.type==="key"});s>=1&&o&&(i=!0,await this.finalizeFragment())}else i=s>=.5}i&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:t.timestamp,samples:[],offset:null,moofOffset:null}),l(e.currentChunk),e.currentChunk.samples.push(t),e.timestampProcessingQueue.push(t)}async finalizeCurrentChunk(e){if(l(this.fastStart!=="fragmented"),!!e.currentChunk){if(e.finalizedChunks.push(e.currentChunk),this.finalizedChunks.push(e.currentChunk),(e.compactlyCodedChunkTable.length===0||y(e.compactlyCodedChunkTable).samplesPerChunk!==e.currentChunk.samples.length)&&e.compactlyCodedChunkTable.push({firstChunk:e.finalizedChunks.length,samplesPerChunk:e.currentChunk.samples.length}),this.fastStart==="in-memory"){e.currentChunk.offset=0;return}e.currentChunk.offset=this.writer.getPos();for(let t of e.currentChunk.samples)l(t.data),this.writer.write(t.data),t.data=null;await this.writer.flush()}}async interleaveSamples(){l(this.fastStart==="fragmented");for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.sampleQueue.length===0&&!s.track.source._closed)break e;s.sampleQueue.length>0&&s.sampleQueue[0].timestamp=2**32&&(a.largeSize=!0,u=this.boxWriter.measureBox(a)+c),a.size=u,this.boxWriter.writeBox(a)}for(let a of this.trackDatas){a.currentChunk.offset=this.writer.getPos(),a.currentChunk.moofOffset=i;for(let c of a.currentChunk.samples)this.writer.write(c.data),c.data=null}let o=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(s));let n=ut(t,this.trackDatas);this.boxWriter.writeBox(n),this.writer.seek(o);for(let a of this.trackDatas)a.finalizedChunks.push(a.currentChunk),this.finalizedChunks.push(a.currentChunk),a.currentChunk=null;e&&await this.writer.flush()}async onTrackClose(e){let t=await this.mutex.acquire();if(e.type==="subtitle"&&e.source._codec==="webvtt"){let i=this.trackDatas.find(s=>s.track===e);i&&await this.processWebVTTCues(i,1/0)}this.fastStart==="fragmented"&&await this.interleaveSamples(),t()}async finalize(){let e=await this.mutex.acquire();for(let t of this.trackDatas)t.type==="subtitle"&&t.track.source._codec==="webvtt"&&await this.processWebVTTCues(t,1/0);if(this.fastStart==="fragmented"){for(let t of this.trackDatas){for(let i of t.sampleQueue)await this.addSampleToTrack(t,i);this.processTimestamps(t)}await this.finalizeFragment(!1)}else for(let t of this.trackDatas)this.processTimestamps(t),await this.finalizeCurrentChunk(t);if(this.fastStart==="in-memory"){l(this.mdat);let t;for(let s=0;s<2;s++){let o=se(this.trackDatas,this.creationTime),n=this.boxWriter.measureBox(o);t=this.boxWriter.measureBox(this.mdat);let a=this.writer.getPos()+n+t;for(let c of this.finalizedChunks){c.offset=a;for(let{data:u}of c.samples)l(u),a+=u.byteLength,t+=u.byteLength}if(a<2**32)break;t>=2**32&&(this.mdat.largeSize=!0)}let i=se(this.trackDatas,this.creationTime);this.boxWriter.writeBox(i),this.mdat.size=t,this.boxWriter.writeBox(this.mdat);for(let s of this.finalizedChunks)for(let o of s.samples)l(o.data),this.writer.write(o.data),o.data=null}else if(this.fastStart==="fragmented"){let t=this.writer.getPos(),i=Mt(this.trackDatas);this.boxWriter.writeBox(i);let s=this.writer.getPos()-t;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(s)}else{l(this.mdat),l(this.ftypSize!==null);let t=this.boxWriter.offsets.get(this.mdat);l(t!==void 0);let i=this.writer.getPos()-t;this.mdat.size=i,this.mdat.largeSize=i>=2**32,this.boxWriter.patchBox(this.mdat);let s=se(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(s);let o=t-this.writer.getPos();this.boxWriter.writeBox(Ot(o))}else this.boxWriter.writeBox(s)}e()}};var ae=class{value;constructor(e){this.value=e}},Z=class{value;constructor(e){this.value=e}},ce=class{value;constructor(e){this.value=e}};var dt=r=>r<256?1:r<65536?2:r<1<<24?3:r<2**32?4:r<2**40?5:6,lt=r=>r>=-64&&r<64?1:r>=-8192&&r<8192?2:r>=-(1<<20)&&r<1<<20?3:r>=-(1<<27)&&r<1<<27?4:r>=-(2**34)&&r<2**34?5:6,jt=r=>{if(r<127)return 1;if(r<16383)return 2;if(r<(1<<21)-1)return 3;if(r<(1<<28)-1)return 4;if(r<2**35-1)return 5;if(r<2**42-1)return 6;throw new Error("EBML VINT size not supported "+r)};var mt=2**15,Kt="https://github.com/Vanilagy/webm-muxer",qt=6,Xt=5,ci={avc:"V_MPEG4/ISO/AVC",hevc:"V_MPEGH/ISO/HEVC",vp8:"V_VP8",vp9:"V_VP9",av1:"V_AV1",aac:"A_AAC",opus:"A_OPUS",webvtt:"S_TEXT/WEBVTT"},ui={video:1,audio:2,subtitle:17},Ie=class extends X{timestampsMustStartAtZero=!1;writer;format;helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;dataOffsets=new WeakMap;trackDatas=[];segment=null;segmentInfo=null;seekHead=null;tracksElement=null;segmentDuration=null;cues=null;currentCluster=null;currentClusterMsTimestamp=null;trackDatasInCurrentCluster=new Set;duration=0;constructor(e,t){super(e),this.writer=e._writer,this.format=t,this.format._options.streamable&&(this.writer.ensureMonotonicity=!0)}writeByte(e){this.helperView.setUint8(0,e),this.writer.write(this.helper.subarray(0,1))}writeFloat32(e){this.helperView.setFloat32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeFloat64(e){this.helperView.setFloat64(0,e,!1),this.writer.write(this.helper)}writeUnsignedInt(e,t=dt(e)){let i=0;switch(t){case 6:this.helperView.setUint8(i++,e/2**40|0);case 5:this.helperView.setUint8(i++,e/2**32|0);case 4:this.helperView.setUint8(i++,e>>24);case 3:this.helperView.setUint8(i++,e>>16);case 2:this.helperView.setUint8(i++,e>>8);case 1:this.helperView.setUint8(i++,e);break;default:throw new Error("Bad UINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeSignedInt(e,t=lt(e)){e<0&&(e+=2**(t*8)),this.writeUnsignedInt(e,t)}writeEBMLVarInt(e,t=jt(e)){let i=0;switch(t){case 1:this.helperView.setUint8(i++,128|e);break;case 2:this.helperView.setUint8(i++,64|e>>8),this.helperView.setUint8(i++,e);break;case 3:this.helperView.setUint8(i++,32|e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 4:this.helperView.setUint8(i++,16|e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 5:this.helperView.setUint8(i++,8|e/2**32&7),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 6:this.helperView.setUint8(i++,4|e/2**40&3),this.helperView.setUint8(i++,e/2**32|0),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;default:throw new Error("Bad EBML VINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeString(e){this.writer.write(new Uint8Array(e.split("").map(t=>t.charCodeAt(0))))}writeEBML(e){if(e!==null){if(e instanceof Uint8Array)this.writer.write(e);else if(Array.isArray(e))for(let t of e)this.writeEBML(t);else if(this.offsets.set(e,this.writer.getPos()),this.writeUnsignedInt(e.id),Array.isArray(e.data)){let t=this.writer.getPos(),i=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+i);let s=this.writer.getPos();if(this.dataOffsets.set(e,s),this.writeEBML(e.data),e.size!==-1){let o=this.writer.getPos()-s,n=this.writer.getPos();this.writer.seek(t),this.writeEBMLVarInt(o,i),this.writer.seek(n)}}else if(typeof e.data=="number"){let t=e.size??dt(e.data);this.writeEBMLVarInt(t),this.writeUnsignedInt(e.data,t)}else if(typeof e.data=="string")this.writeEBMLVarInt(e.data.length),this.writeString(e.data);else if(e.data instanceof Uint8Array)this.writeEBMLVarInt(e.data.byteLength,e.size),this.writer.write(e.data);else if(e.data instanceof ae)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof Z)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof ce){let t=e.size??lt(e.data.value);this.writeEBMLVarInt(t),this.writeSignedInt(e.data.value,t)}}}beforeTrackAdd(e){if(this.format instanceof $)if(e.type==="video"){if(!["vp8","vp9","av1"].includes(e.source._codec))throw new Error("WebM only supports VP8, VP9 and AV1 as video codecs. Switching to MKV removes this restriction.")}else if(e.type==="audio"){if(!["opus","vorbis"].includes(e.source._codec))throw new Error("WebM only supports Opus and Vorbis as audio codecs. Switching to MKV removes this restriction.")}else if(e.type==="subtitle"){if(e.source._codec!=="webvtt")throw new Error("WebM only supports WebVTT as subtitle codec. Switching to MKV removes this restriction.")}else throw new Error("WebM only supports video, audio and subtitle tracks. Switching to MKV removes this restriction.")}async start(){let e=await this.mutex.acquire();this.writeEBMLHeader(),this.format._options.streamable||this.createSeekHead(),this.createSegmentInfo(),this.createCues(),await this.writer.flush(),e()}writeEBMLHeader(){let e={id:440786851,data:[{id:17030,data:1},{id:17143,data:1},{id:17138,data:4},{id:17139,data:8},{id:17026,data:this.format instanceof $?"webm":"matroska"},{id:17031,data:2},{id:17029,data:2}]};this.writeEBML(e)}createSeekHead(){let e=new Uint8Array([28,83,187,107]),t=new Uint8Array([21,73,169,102]),i=new Uint8Array([22,84,174,107]),s={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:t},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:i},{id:21420,size:5,data:0}]}]};this.seekHead=s}createSegmentInfo(){let e={id:17545,data:new Z(0)};this.segmentDuration=e;let t={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:Kt},{id:22337,data:Kt},this.format._options.streamable?null:e]};this.segmentInfo=t}createTracks(){let e={id:374648427,data:[]};this.tracksElement=e;for(let t of this.trackDatas)e.data.push({id:174,data:[{id:215,data:t.track.id},{id:29637,data:t.track.id},{id:131,data:ui[t.type]},{id:134,data:ci[t.track.source._codec]},t.type==="video"?this.videoSpecificTrackInfo(t):null,t.type==="audio"?this.audioSpecificTrackInfo(t):null,t.type==="subtitle"?this.subtitleSpecificTrackInfo(t):null]})}videoSpecificTrackInfo(e){let t=[e.info.decoderConfig.description?{id:25506,data:B(e.info.decoderConfig.description)}:null,e.track.metadata.frameRate?{id:2352003,data:1e9/e.track.metadata.frameRate}:null],i=e.info.decoderConfig.colorSpace,s={id:224,data:[{id:176,data:e.info.width},{id:186,data:e.info.height},be(i)?{id:21936,data:[{id:21937,data:F[i.matrix]},{id:21946,data:D[i.transfer]},{id:21947,data:U[i.primaries]},{id:21945,data:i.fullRange?2:1}]}:null]};return t.push(s),t}audioSpecificTrackInfo(e){return[e.info.decoderConfig.description?{id:25506,data:B(e.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new ae(e.info.sampleRate)},{id:159,data:e.info.numberOfChannels}]}]}subtitleSpecificTrackInfo(e){return[{id:25506,data:v.encode(e.info.config.description)}]}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:qt,data:[this.format._options.streamable?null:this.seekHead,this.segmentInfo,this.tracksElement]};this.segment=e,this.writeEBML(e)}createCues(){this.cues={id:475249515,data:[]}}get segmentDataOffset(){return l(this.segment),this.dataOffsets.get(this.segment)}getVideoTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;ve(t),l(t),l(t.decoderConfig),l(t.decoderConfig.codedWidth!==void 0),l(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;_e(t),l(t),l(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;Ae(t),l(t),l(t.config);let s={track:e,type:"subtitle",info:{config:t.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=t.type==="key",c=this.validateAndNormalizeTimestamp(o.track,t.timestamp,a),u=this.createInternalChunk(n,c,(t.duration??0)/1e6,t.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(o,u),o.chunkQueue.push(u),await this.interleaveChunks()}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=t.type,c=a==="key",u=this.validateAndNormalizeTimestamp(o.track,t.timestamp,c),d=this.createInternalChunk(n,u,(t.duration??0)/1e6,a);o.chunkQueue.push(d),await this.interleaveChunks()}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,i),n=this.validateAndNormalizeTimestamp(o.track,1e6*t.timestamp,!0),a=t.text,c=Math.floor(n*1e3);q.lastIndex=0,a=a.replace(q,T=>{let k=ge(T.slice(1,-1))-c;return`<${Te(k)}>`});let u=v.encode(a),d=`${t.settings??""} +`,n);c===-1&&(c=e.length);let u=we(t[2]),f=we(t[3])-u,g=e.slice(o,c).trim();e=e.slice(c).trimStart(),oe.lastIndex=0;let x={timestamp:u/1e3,duration:f/1e3,text:g,identifier:s,settings:a,notes:i},C={};this.preambleEmitted||(C.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(x,C)}}},dr=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,we=r=>{let e=dr.exec(r);if(!e)throw new Error("Expected match.");return 60*60*1e3*Number(e[1]||"0")+60*1e3*Number(e[2])+1e3*Number(e[3])+Number(e[4])},Se=r=>{let e=Math.floor(r/36e5),t=Math.floor(r%(60*60*1e3)/(60*1e3)),i=Math.floor(r%(60*1e3)/1e3),s=r%1e3;return e.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+":"+i.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var ae=class{constructor(e){this.writer=e}helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;writeU32(e){this.helperView.setUint32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(e){this.helperView.setUint32(0,Math.floor(e/2**32),!1),this.helperView.setUint32(4,e,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(e){for(let t=0;t[(r%256+256)%256],p=r=>(O.setUint16(0,r,!1),[h[0],h[1]]),lr=r=>(O.setInt16(0,r,!1),[h[0],h[1]]),Et=r=>(O.setUint32(0,r,!1),[h[1],h[2],h[3]]),m=r=>(O.setUint32(0,r,!1),[h[0],h[1],h[2],h[3]]),It=r=>(O.setInt32(0,r,!1),[h[0],h[1],h[2],h[3]]),Q=r=>(O.setUint32(0,Math.floor(r/2**32),!1),O.setUint32(4,r,!1),[h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7]]),ct=r=>(O.setInt16(0,2**8*r,!1),[h[0],h[1]]),I=r=>(O.setInt32(0,2**16*r,!1),[h[0],h[1],h[2],h[3]]),ot=r=>(O.setInt32(0,2**30*r,!1),[h[0],h[1],h[2],h[3]]),at=(r,e)=>{let t=[],i=r;do{let s=i&127;i>>=7,t.length>0&&(s|=128),t.push(s),e!==void 0&&e--}while(i>0||e);return t.reverse()},y=(r,e=!1)=>{let t=Array(r.length).fill(null).map((i,s)=>r.charCodeAt(s));return e&&t.push(0),t},ut=r=>{let e=null;for(let t of r)(!e||t.timestamp>e.timestamp)&&(e=t);return e},Ot=r=>[I(r[0]),I(r[1]),ot(r[2]),I(r[3]),I(r[4]),ot(r[5]),I(r[6]),I(r[7]),ot(r[8])],b=(r,e,t)=>({type:r,contents:e&&new Uint8Array(e.flat(10)),children:t}),T=(r,e,t,i,s)=>b(r,[w(e),Et(t),i??[]],s),Vt=r=>r.fragmented?b("ftyp",[y("iso5"),m(512),y("iso5"),y("iso6"),y("mp41")]):b("ftyp",[y("isom"),m(512),y("isom"),r.holdsAvc?y("avc1"):[],y("mp41")]),ve=r=>({type:"mdat",largeSize:r}),Rt=r=>({type:"free",size:r}),ce=(r,e,t=!1)=>b("moov",void 0,[mr(e,r),...r.map(i=>fr(i,e)),t?jr(r):null]),mr=(r,e)=>{let t=A(Math.max(0,...e.filter(o=>o.samples.length>0).map(o=>{let a=ut(o.samples);return a.timestamp+a.duration})),ye),i=Math.max(0,...e.map(o=>o.track.id))+1,s=!U(r)||!U(t),n=s?Q:m;return T("mvhd",+s,0,[n(r),n(r),m(ye),n(t),I(1),ct(1),Array(10).fill(0),Ot(nt),Array(24).fill(0),m(i)])},fr=(r,e)=>b("trak",void 0,[hr(r,e),pr(r,e)]),hr=(r,e)=>{let t=ut(r.samples),i=A(t?t.timestamp+t.duration:0,ye),s=!U(e)||!U(i),n=s?Q:m,o;if(r.type==="video"){let a=r.track.metadata.rotation;o=a===void 0||typeof a=="number"?M(a??0):a}else o=nt;return T("tkhd",+s,3,[n(e),n(e),m(r.track.id),m(0),n(i),Array(8).fill(0),p(0),p(r.track.id),ct(r.type==="audio"?1:0),p(0),Ot(o),I(r.type==="video"?r.info.width:0),I(r.type==="video"?r.info.height:0)])},pr=(r,e)=>b("mdia",void 0,[br(r,e),Tr(r),xr(r)]),br=(r,e)=>{let t=ut(r.samples),i=A(t?t.timestamp+t.duration:0,r.timescale),s=!U(e)||!U(i),n=s?Q:m;return T("mdhd",+s,0,[n(e),n(e),m(r.timescale),n(i),p(21956),p(0)])},kr={video:"vide",audio:"soun",subtitle:"text"},gr={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},Tr=r=>T("hdlr",0,0,[y("mhlr"),y(kr[r.type]),m(0),m(0),m(0),y(gr[r.type],!0)]),xr=r=>b("minf",void 0,[yr[r.type](),vr(),Er(r)]),Cr=()=>T("vmhd",0,1,[p(0),p(0),p(0),p(0)]),wr=()=>T("smhd",0,0,[p(0),p(0)]),Sr=()=>T("nmhd",0,0),yr={video:Cr,audio:wr,subtitle:Sr},vr=()=>b("dinf",void 0,[_r()]),_r=()=>T("dref",0,0,[m(1)],[Ar()]),Ar=()=>T("url ",0,1),Er=r=>{let e=r.compositionTimeOffsetTable.length>1||r.compositionTimeOffsetTable.some(t=>t.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[Ir(r),Wr(r),Nr(r),Hr(r),Lr(r),Qr(r),e?$r(r):null])},Ir=r=>{let e;return r.type==="video"?e=Or(ti[r.track.source._codec],r):r.type==="audio"?e=zr(ii[r.track.source._codec],r):r.type==="subtitle"&&(e=Dr(ni[r.track.source._codec],r)),d(e),T("stsd",0,0,[m(1)],[e])},Or=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),Array(12).fill(0),p(e.info.width),p(e.info.height),m(4718592),m(4718592),m(0),p(1),Array(32).fill(0),p(24),lr(65535)],[ri[e.track.source._codec](e),xe(e.info.decoderConfig.colorSpace)?Vr(e):null]),Vr=r=>b("colr",[y("nclx"),p(W[r.info.decoderConfig.colorSpace.primaries]),p(N[r.info.decoderConfig.colorSpace.transfer]),p(H[r.info.decoderConfig.colorSpace.matrix]),w((r.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),Rr=r=>r.info.decoderConfig&&b("avcC",[...F(r.info.decoderConfig.description)]),Mr=r=>r.info.decoderConfig&&b("hvcC",[...F(r.info.decoderConfig.description)]),At=r=>{if(!r.info.decoderConfig)return null;let e=r.info.decoderConfig;d(e.colorSpace);let t=e.codec.split("."),i=Number(t[1]),s=Number(t[2]),a=(Number(t[3])<<4)+(0<<1)+Number(e.colorSpace.fullRange);return T("vpcC",1,0,[w(i),w(s),w(a),w(2),w(2),w(2),p(0)])},Pr=()=>b("av1C",[129,0,0,0]),zr=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),m(0),p(e.info.numberOfChannels),p(16),p(0),p(0),I(e.info.sampleRate)],[si[e.track.source._codec](e)]),Br=r=>{let t=[...F(r.info.decoderConfig.description??new ArrayBuffer(0))];return t=[...w(64),...w(21),...Et(0),...m(0),...m(0),...w(5),...at(t.length),...t],t=[...p(1),...w(0),...w(4),...at(t.length),...t,...w(6),...w(1),...w(2)],t=[...w(3),...at(t.length),...t],T("esds",0,0,t)},Ur=r=>{let e=3840,t=0,i=r.info.decoderConfig?.description;if(i){d(i.byteLength>=18);let s=ArrayBuffer.isView(i)?new DataView(i.buffer,i.byteOffset,i.byteLength):new DataView(i);e=s.getUint16(10,!0),t=s.getInt16(14,!0)}return b("dOps",[w(0),w(r.info.numberOfChannels),p(e),m(r.info.sampleRate),ct(t),w(0)])},Dr=(r,e)=>b(r,[Array(6).fill(0),p(1)],[oi[e.track.source._codec](e)]),Fr=r=>b("vttC",[..._.encode(r.info.config.description)]);var Wr=r=>T("stts",0,0,[m(r.timeToSampleTable.length),r.timeToSampleTable.map(e=>[m(e.sampleCount),m(e.sampleDelta)])]),Nr=r=>{if(r.samples.every(t=>t.type==="key"))return null;let e=[...r.samples.entries()].filter(([,t])=>t.type==="key");return T("stss",0,0,[m(e.length),e.map(([t])=>m(t+1))])},Hr=r=>T("stsc",0,0,[m(r.compactlyCodedChunkTable.length),r.compactlyCodedChunkTable.map(e=>[m(e.firstChunk),m(e.samplesPerChunk),m(1)])]),Lr=r=>T("stsz",0,0,[m(0),m(r.samples.length),r.samples.map(e=>m(e.size))]),Qr=r=>r.finalizedChunks.length>0&&v(r.finalizedChunks).offset>=2**32?T("co64",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>Q(e.offset))]):T("stco",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>m(e.offset))]),$r=r=>T("ctts",0,0,[m(r.compositionTimeOffsetTable.length),r.compositionTimeOffsetTable.map(e=>[m(e.sampleCount),m(e.sampleCompositionTimeOffset)])]),jr=r=>b("mvex",void 0,r.map(Kr)),Kr=r=>T("trex",0,0,[m(r.track.id),m(1),m(0),m(0),m(0)]),dt=(r,e)=>b("moof",void 0,[qr(r),...e.map(Xr)]),qr=r=>T("mfhd",0,0,[m(r)]),Mt=r=>{let e=0,t=0,i=0,s=0,n=r.type==="delta";return t|=+n,n?e|=1:e|=2,e<<24|t<<16|i<<8|s},Xr=r=>b("traf",void 0,[Gr(r),Yr(r),Zr(r)]),Gr=r=>{d(r.currentChunk);let e=0;e|=8,e|=16,e|=32,e|=131072;let t=r.currentChunk.samples[1]??r.currentChunk.samples[0],i={duration:t.timescaleUnitsToNextSample,size:t.size,flags:Mt(t)};return T("tfhd",0,e,[m(r.track.id),m(i.duration),m(i.size),m(i.flags)])},Yr=r=>(d(r.currentChunk),T("tfdt",1,0,[Q(A(r.currentChunk.startTimestamp,r.timescale))])),Zr=r=>{d(r.currentChunk);let e=r.currentChunk.samples.map(k=>k.timescaleUnitsToNextSample),t=r.currentChunk.samples.map(k=>k.size),i=r.currentChunk.samples.map(Mt),s=r.currentChunk.samples.map(k=>A(k.timestamp-k.decodeTimestamp,r.timescale)),n=new Set(e),o=new Set(t),a=new Set(i),c=new Set(s),u=a.size===2&&i[0]!==i[1],l=n.size>1,f=o.size>1,g=!u&&a.size>1,x=c.size>1||[...c].some(k=>k!==0),C=0;return C|=1,C|=4*+u,C|=256*+l,C|=512*+f,C|=1024*+g,C|=2048*+x,T("trun",1,C,[m(r.currentChunk.samples.length),m(r.currentChunk.offset-r.currentChunk.moofOffset||0),u?m(i[0]):[],r.currentChunk.samples.map((k,S)=>[l?m(e[S]):[],f?m(t[S]):[],g?m(i[S]):[],x?It(s[S]):[]])])},Pt=r=>b("mfra",void 0,[...r.map(Jr),ei()]),Jr=(r,e)=>T("tfra",1,0,[m(r.track.id),m(63),m(r.finalizedChunks.length),r.finalizedChunks.map(i=>[Q(A(i.startTimestamp,r.timescale)),Q(i.moofOffset),m(e+1),m(1),m(1)])]),ei=()=>T("mfro",0,0,[m(0)]),zt=()=>b("vtte"),Bt=(r,e,t,i,s)=>b("vttc",void 0,[s!==null?b("vsid",[It(s)]):null,t!==null?b("iden",[..._.encode(t)]):null,e!==null?b("ctim",[..._.encode(Se(e))]):null,i!==null?b("sttg",[..._.encode(i)]):null,b("payl",[..._.encode(r)])]),Ut=r=>b("vtta",[..._.encode(r)]),ti={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},ri={avc:Rr,hevc:Mr,vp8:At,vp9:At,av1:Pr},ii={aac:"mp4a",opus:"Opus"},si={aac:Br,opus:Ur},ni={webvtt:"wvtt"},oi={webvtt:Fr};var J=class{output;mutex=new Y;constructor(e){this.output=e}beforeTrackAdd(e){}onTrackClose(e){}trackTimestampInfo=new WeakMap;validateAndNormalizeTimestamp(e,t,i){let s=t/1e6,n=this.trackTimestampInfo.get(e);if(!n){if(!i)throw new Error("First frame must be a key frame.");if(this.timestampsMustStartAtZero&&s>0)throw new Error(`Timestamps must start at zero (got ${s}s).`);n={timestampOffset:s,maxTimestamp:e.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:e.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(e,n)}if(e.source._offsetTimestamps&&(s-=n.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(si.start-s.start);e.push({start:t[0].start,size:t[0].data.byteLength});for(let i=1;ic.start<=t&&tci){for(let c=0;c=e.written[n+1].start;)e.written[n].end=Math.max(e.written[n].end,e.written[n+1].end),e.written.splice(n+1,1)}createChunk(e){let i={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(i),this.chunks.sort((s,n)=>s.start-n.start),this.chunks.indexOf(i)}queueChunksForFlush(e=!1){d(this.writer);for(let t=0;t{if(r==="avc"){let n=Math.ceil(e/16)*Math.ceil(t/16),o=Dt.find(f=>n<=f.maxMacroblocks&&i<=f.maxBitrate)??v(Dt),a=o?o.level:0,c="64".padStart(2,"0"),u="00",l=a.toString(16).padStart(2,"0");return`avc1.${c}${u}${l}`}else if(r==="hevc"){let s="",o="6",a=e*t,c=Ft.find(l=>a<=l.maxPictureSize&&i<=l.maxBitrate)??v(Ft);return`hev1.${s}1.${o}.${c.tier}${c.level}.B0`}else{if(r==="vp8")return"vp8";if(r==="vp9"){let s="00",n=e*t,o=Wt.find(c=>n<=c.maxPictureSize&&i<=c.maxBitrate)??v(Wt);return`vp09.${s}.${o.level}.08`}else if(r==="av1"){let n=e*t,o=Nt.find(c=>n<=c.maxPictureSize&&i<=c.maxBitrate)??v(Nt);return`av01.0.${o.level.toString().padStart(2,"0")}${o.tier}.08`}}throw new TypeError(`Unhandled codec '${r}'.`)},Lt=(r,e)=>{if(r==="avc"){if(!e||e.byteLength<4)throw new TypeError("AVC description must be at least 4 bytes long.");return`avc1.${St(e.subarray(1,4))}`}else if(r==="hevc"){if(!e)throw new TypeError("HEVC description must be provided.");let t=new DataView(e.buffer,e.byteOffset,e.byteLength),i="hev1.",s=e[1]>>6&3,n=e[1]&31;i+=["","A","B","C"][s]+n,i+=".";let o=yt(t.getUint32(2));i+=o.toString(16),i+=".";let a=e[1]>>5&1,c=e[12];i+=a===0?"L":"H",i+=c,i+=".";let u=[];for(let l=0;l<6;l++){let f=e[l+13];u.push(f)}for(;u[u.length-1]===0;)u.pop();return i+=u.map(l=>l.toString(16)).join("."),i}throw new TypeError(`Unhandled codec '${r}'.`)},Qt=(r,e,t)=>{if(r==="aac")return e>=2&&t<=24e3?"mp4a.40.29":t<=24e3?"mp4a.40.5":"mp4a.40.2";if(r==="opus")return"opus";if(r==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${r}'.`)},$t=(r,e)=>{if(r==="aac"){if(!e||e.byteLength<2)throw new TypeError("AAC description must be at least 2 bytes long.");return`mp4a.40.${e[0]>>3}`}else{if(r==="opus")return"opus";if(r==="vorbis")return"vorbis"}throw new TypeError(`Unhandled codec '${r}'.`)},jt=r=>r==="avc"?{avc:{format:"avc"}}:r==="hevc"?{hevc:{format:"hevc"}}:{},Kt=r=>r==="aac"?{aac:{format:"aac"}}:r==="opus"?{opus:{format:"opus"}}:{},Ie=r=>{if(!r)throw new TypeError("Video chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Video chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Video chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Video chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.codedWidth)||r.decoderConfig.codedWidth<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");if(!Number.isInteger(r.decoderConfig.codedHeight)||r.decoderConfig.codedHeight<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");if(r.decoderConfig.description!==void 0&&!st(r.decoderConfig.description))throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.colorSpace!==void 0){let{colorSpace:e}=r.decoderConfig;if(typeof e!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let t=Object.keys(W);if(e.primaries!=null&&!t.includes(e.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${t.join(", ")}.`);let i=Object.keys(N);if(e.transfer!=null&&!i.includes(e.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${i.join(", ")}.`);let s=Object.keys(H);if(e.matrix!=null&&!s.includes(e.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(e.fullRange!=null&&typeof e.fullRange!="boolean")throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.")}if((r.decoderConfig.codec.startsWith("avc1")||r.decoderConfig.codec.startsWith("avc3"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for AVC must include a description, which is expected to be an AVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec.startsWith("hev1")||r.decoderConfig.codec.startsWith("hvc1"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for HEVC must include a description, which is expected to be an HEVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec==="vp8"||r.decoderConfig.codec.startsWith("vp09"))&&r.decoderConfig.colorSpace===void 0)throw new TypeError("Video chunk metadata decoder configuration for VP8/VP9 must include a colorSpace.")},Oe=r=>{if(!r)throw new TypeError("Audio chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Audio chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Audio chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Audio chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.sampleRate)||r.decoderConfig.sampleRate<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");if(!Number.isInteger(r.decoderConfig.numberOfChannels)||r.decoderConfig.numberOfChannels<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");if(r.decoderConfig.description!==void 0&&!st(r.decoderConfig.description))throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.codec.startsWith("mp4a")&&!r.decoderConfig.description)throw new TypeError("Audio chunk metadata decoder configuration for AAC must include a description, which is expected to be an AudioSpecificConfig as specified in ISO 14496-3.");if(r.decoderConfig.codec==="opus"&&r.decoderConfig.description&&r.decoderConfig.description.byteLength<18)throw new TypeError("Invalid decoder description provided for Opus; must be at least 18 bytes long.")},Ve=r=>{if(!r)throw new TypeError("Subtitle metadata must be provided.");if(typeof r!="object")throw new TypeError("Subtitle metadata must be an object.");if(!r.config)throw new TypeError("Subtitle metadata must include a config object.");if(typeof r.config!="object")throw new TypeError("Subtitle metadata config must be an object.");if(typeof r.config.description!="string")throw new TypeError("Subtitle metadata config description must be a string.")};var ye=1e3,ui=2082844800,A=(r,e,t=!0)=>{let i=r*e;return t?Math.round(i):i},Re=class extends J{timestampsMustStartAtZero=!0;writer;boxWriter;fastStart;auxTarget=new te;auxWriter=this.auxTarget._createWriter();auxBoxWriter=new ae(this.auxWriter);ftypSize=null;mdat=null;trackDatas=[];creationTime=Math.floor(Date.now()/1e3)+ui;finalizedChunks=[];nextFragmentNumber=1;constructor(e,t){super(e),this.writer=e._writer,this.boxWriter=new ae(this.writer);let i=this.writer instanceof ee?"in-memory":!1;this.fastStart=t._options.fastStart??i,(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),t=this.output._tracks.some(i=>i.type==="video"&&i.source._codec==="avc");this.boxWriter.writeBox(Vt({holdsAvc:t,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=ve(!1):this.fastStart==="fragmented"||(this.mdat=ve(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Ie(t),d(t),d(t.decoderConfig),d(t.decoderConfig.codedWidth!==void 0),d(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},timescale:e.metadata.frameRate??57600,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Oe(t),d(t),d(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},timescale:t.decoderConfig.sampleRate,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Ve(t),d(t),d(t.config);let s={track:e,type:"subtitle",info:{config:t.config},timescale:1e3,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[],lastCueEndTimestamp:0,cueQueue:[],nextSourceId:0,cueToSourceId:new WeakMap};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),this.validateAndNormalizeTimestamp(e,0,!0),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getVideoTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=this.validateAndNormalizeTimestamp(n.track,t.timestamp,t.type==="key"),c=this.createSampleForTrack(n,o,a,(t.duration??0)/1e6,t.type);await this.registerSample(n,c)}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getAudioTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=t.type,c=this.validateAndNormalizeTimestamp(n.track,t.timestamp,a==="key"),u=this.createSampleForTrack(n,o,c,(t.duration??0)/1e6,a);await this.registerSample(n,u)}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let n=this.getSubtitleTrackData(e,i);this.validateAndNormalizeTimestamp(n.track,1e6*t.timestamp,!0),e.source._codec==="webvtt"&&(n.cueQueue.push(t),await this.processWebVTTCues(n,t.timestamp))}finally{s()}}async processWebVTTCues(e,t){for(;e.cueQueue.length>0;){let i=new Set([]);for(let u of e.cueQueue)d(u.timestamp<=t),d(e.lastCueEndTimestamp<=u.timestamp+u.duration),i.add(Math.max(u.timestamp,e.lastCueEndTimestamp)),i.add(u.timestamp+u.duration);let s=[...i].sort((u,l)=>u-l),n=s[0],o=s[1]??n;if(t=o)break;Z.lastIndex=0;let f=Z.test(l.text),g=l.timestamp+l.duration,x=e.cueToSourceId.get(l);if(x===void 0&&oi.timestamp).sort((i,s)=>i-s);for(let i=0;i{if(e===o)return t.type==="key";let a=o.sampleQueue[0];return a&&a.type==="key"});s>=1&&n&&(i=!0,await this.finalizeFragment())}else i=s>=.5}i&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:t.timestamp,samples:[],offset:null,moofOffset:null}),d(e.currentChunk),e.currentChunk.samples.push(t),e.timestampProcessingQueue.push(t)}async finalizeCurrentChunk(e){if(d(this.fastStart!=="fragmented"),!!e.currentChunk){if(e.finalizedChunks.push(e.currentChunk),this.finalizedChunks.push(e.currentChunk),(e.compactlyCodedChunkTable.length===0||v(e.compactlyCodedChunkTable).samplesPerChunk!==e.currentChunk.samples.length)&&e.compactlyCodedChunkTable.push({firstChunk:e.finalizedChunks.length,samplesPerChunk:e.currentChunk.samples.length}),this.fastStart==="in-memory"){e.currentChunk.offset=0;return}e.currentChunk.offset=this.writer.getPos();for(let t of e.currentChunk.samples)d(t.data),this.writer.write(t.data),t.data=null;await this.writer.flush()}}async interleaveSamples(){d(this.fastStart==="fragmented");for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.sampleQueue.length===0&&!s.track.source._closed)break e;s.sampleQueue.length>0&&s.sampleQueue[0].timestamp=2**32&&(a.largeSize=!0,u=this.boxWriter.measureBox(a)+c),a.size=u,this.boxWriter.writeBox(a)}for(let a of this.trackDatas){a.currentChunk.offset=this.writer.getPos(),a.currentChunk.moofOffset=i;for(let c of a.currentChunk.samples)this.writer.write(c.data),c.data=null}let n=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(s));let o=dt(t,this.trackDatas);this.boxWriter.writeBox(o),this.writer.seek(n);for(let a of this.trackDatas)a.finalizedChunks.push(a.currentChunk),this.finalizedChunks.push(a.currentChunk),a.currentChunk=null;e&&await this.writer.flush()}async onTrackClose(e){let t=await this.mutex.acquire();if(e.type==="subtitle"&&e.source._codec==="webvtt"){let i=this.trackDatas.find(s=>s.track===e);i&&await this.processWebVTTCues(i,1/0)}this.fastStart==="fragmented"&&await this.interleaveSamples(),t()}async finalize(){let e=await this.mutex.acquire();for(let t of this.trackDatas)t.type==="subtitle"&&t.track.source._codec==="webvtt"&&await this.processWebVTTCues(t,1/0);if(this.fastStart==="fragmented"){for(let t of this.trackDatas){for(let i of t.sampleQueue)await this.addSampleToTrack(t,i);this.processTimestamps(t)}await this.finalizeFragment(!1)}else for(let t of this.trackDatas)this.processTimestamps(t),await this.finalizeCurrentChunk(t);if(this.fastStart==="in-memory"){d(this.mdat);let t;for(let s=0;s<2;s++){let n=ce(this.trackDatas,this.creationTime),o=this.boxWriter.measureBox(n);t=this.boxWriter.measureBox(this.mdat);let a=this.writer.getPos()+o+t;for(let c of this.finalizedChunks){c.offset=a;for(let{data:u}of c.samples)d(u),a+=u.byteLength,t+=u.byteLength}if(a<2**32)break;t>=2**32&&(this.mdat.largeSize=!0)}let i=ce(this.trackDatas,this.creationTime);this.boxWriter.writeBox(i),this.mdat.size=t,this.boxWriter.writeBox(this.mdat);for(let s of this.finalizedChunks)for(let n of s.samples)d(n.data),this.writer.write(n.data),n.data=null}else if(this.fastStart==="fragmented"){let t=this.writer.getPos(),i=Pt(this.trackDatas);this.boxWriter.writeBox(i);let s=this.writer.getPos()-t;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(s)}else{d(this.mdat),d(this.ftypSize!==null);let t=this.boxWriter.offsets.get(this.mdat);d(t!==void 0);let i=this.writer.getPos()-t;this.mdat.size=i,this.mdat.largeSize=i>=2**32,this.boxWriter.patchBox(this.mdat);let s=ce(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(s);let n=t-this.writer.getPos();this.boxWriter.writeBox(Rt(n))}else this.boxWriter.writeBox(s)}e()}};var le=class{value;constructor(e){this.value=e}},re=class{value;constructor(e){this.value=e}},me=class{value;constructor(e){this.value=e}};var lt=r=>r<256?1:r<65536?2:r<1<<24?3:r<2**32?4:r<2**40?5:6,mt=r=>r>=-64&&r<64?1:r>=-8192&&r<8192?2:r>=-(1<<20)&&r<1<<20?3:r>=-(1<<27)&&r<1<<27?4:r>=-(2**34)&&r<2**34?5:6,qt=r=>{if(r<127)return 1;if(r<16383)return 2;if(r<(1<<21)-1)return 3;if(r<(1<<28)-1)return 4;if(r<2**35-1)return 5;if(r<2**42-1)return 6;throw new Error("EBML VINT size not supported "+r)};var ft=2**15,Xt="https://github.com/Vanilagy/webm-muxer",Gt=6,Yt=5,di={avc:"V_MPEG4/ISO/AVC",hevc:"V_MPEGH/ISO/HEVC",vp8:"V_VP8",vp9:"V_VP9",av1:"V_AV1",aac:"A_AAC",opus:"A_OPUS",webvtt:"S_TEXT/WEBVTT"},li={video:1,audio:2,subtitle:17},Me=class extends J{timestampsMustStartAtZero=!1;writer;format;helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;dataOffsets=new WeakMap;trackDatas=[];segment=null;segmentInfo=null;seekHead=null;tracksElement=null;segmentDuration=null;cues=null;currentCluster=null;currentClusterMsTimestamp=null;trackDatasInCurrentCluster=new Set;duration=0;constructor(e,t){super(e),this.writer=e._writer,this.format=t,this.format._options.streamable&&(this.writer.ensureMonotonicity=!0)}writeByte(e){this.helperView.setUint8(0,e),this.writer.write(this.helper.subarray(0,1))}writeFloat32(e){this.helperView.setFloat32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeFloat64(e){this.helperView.setFloat64(0,e,!1),this.writer.write(this.helper)}writeUnsignedInt(e,t=lt(e)){let i=0;switch(t){case 6:this.helperView.setUint8(i++,e/2**40|0);case 5:this.helperView.setUint8(i++,e/2**32|0);case 4:this.helperView.setUint8(i++,e>>24);case 3:this.helperView.setUint8(i++,e>>16);case 2:this.helperView.setUint8(i++,e>>8);case 1:this.helperView.setUint8(i++,e);break;default:throw new Error("Bad UINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeSignedInt(e,t=mt(e)){e<0&&(e+=2**(t*8)),this.writeUnsignedInt(e,t)}writeEBMLVarInt(e,t=qt(e)){let i=0;switch(t){case 1:this.helperView.setUint8(i++,128|e);break;case 2:this.helperView.setUint8(i++,64|e>>8),this.helperView.setUint8(i++,e);break;case 3:this.helperView.setUint8(i++,32|e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 4:this.helperView.setUint8(i++,16|e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 5:this.helperView.setUint8(i++,8|e/2**32&7),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 6:this.helperView.setUint8(i++,4|e/2**40&3),this.helperView.setUint8(i++,e/2**32|0),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;default:throw new Error("Bad EBML VINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeString(e){this.writer.write(new Uint8Array(e.split("").map(t=>t.charCodeAt(0))))}writeEBML(e){if(e!==null){if(e instanceof Uint8Array)this.writer.write(e);else if(Array.isArray(e))for(let t of e)this.writeEBML(t);else if(this.offsets.set(e,this.writer.getPos()),this.writeUnsignedInt(e.id),Array.isArray(e.data)){let t=this.writer.getPos(),i=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+i);let s=this.writer.getPos();if(this.dataOffsets.set(e,s),this.writeEBML(e.data),e.size!==-1){let n=this.writer.getPos()-s,o=this.writer.getPos();this.writer.seek(t),this.writeEBMLVarInt(n,i),this.writer.seek(o)}}else if(typeof e.data=="number"){let t=e.size??lt(e.data);this.writeEBMLVarInt(t),this.writeUnsignedInt(e.data,t)}else if(typeof e.data=="string")this.writeEBMLVarInt(e.data.length),this.writeString(e.data);else if(e.data instanceof Uint8Array)this.writeEBMLVarInt(e.data.byteLength,e.size),this.writer.write(e.data);else if(e.data instanceof le)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof re)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof me){let t=e.size??mt(e.data.value);this.writeEBMLVarInt(t),this.writeSignedInt(e.data.value,t)}}}beforeTrackAdd(e){if(this.format instanceof K)if(e.type==="video"){if(!["vp8","vp9","av1"].includes(e.source._codec))throw new Error("WebM only supports VP8, VP9 and AV1 as video codecs. Switching to MKV removes this restriction.")}else if(e.type==="audio"){if(!["opus","vorbis"].includes(e.source._codec))throw new Error("WebM only supports Opus and Vorbis as audio codecs. Switching to MKV removes this restriction.")}else if(e.type==="subtitle"){if(e.source._codec!=="webvtt")throw new Error("WebM only supports WebVTT as subtitle codec. Switching to MKV removes this restriction.")}else throw new Error("WebM only supports video, audio and subtitle tracks. Switching to MKV removes this restriction.")}async start(){let e=await this.mutex.acquire();this.writeEBMLHeader(),this.format._options.streamable||this.createSeekHead(),this.createSegmentInfo(),this.createCues(),await this.writer.flush(),e()}writeEBMLHeader(){let e={id:440786851,data:[{id:17030,data:1},{id:17143,data:1},{id:17138,data:4},{id:17139,data:8},{id:17026,data:this.format instanceof K?"webm":"matroska"},{id:17031,data:2},{id:17029,data:2}]};this.writeEBML(e)}createSeekHead(){let e=new Uint8Array([28,83,187,107]),t=new Uint8Array([21,73,169,102]),i=new Uint8Array([22,84,174,107]),s={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:t},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:i},{id:21420,size:5,data:0}]}]};this.seekHead=s}createSegmentInfo(){let e={id:17545,data:new re(0)};this.segmentDuration=e;let t={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:Xt},{id:22337,data:Xt},this.format._options.streamable?null:e]};this.segmentInfo=t}createTracks(){let e={id:374648427,data:[]};this.tracksElement=e;for(let t of this.trackDatas)e.data.push({id:174,data:[{id:215,data:t.track.id},{id:29637,data:t.track.id},{id:131,data:li[t.type]},{id:134,data:di[t.track.source._codec]},t.type==="video"?this.videoSpecificTrackInfo(t):null,t.type==="audio"?this.audioSpecificTrackInfo(t):null,t.type==="subtitle"?this.subtitleSpecificTrackInfo(t):null]})}videoSpecificTrackInfo(e){let t=[e.info.decoderConfig.description?{id:25506,data:F(e.info.decoderConfig.description)}:null,e.track.metadata.frameRate?{id:2352003,data:1e9/e.track.metadata.frameRate}:null],i=e.info.decoderConfig.colorSpace,s={id:224,data:[{id:176,data:e.info.width},{id:186,data:e.info.height},xe(i)?{id:21936,data:[{id:21937,data:H[i.matrix]},{id:21946,data:N[i.transfer]},{id:21947,data:W[i.primaries]},{id:21945,data:i.fullRange?2:1}]}:null]};return t.push(s),t}audioSpecificTrackInfo(e){return[e.info.decoderConfig.description?{id:25506,data:F(e.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new le(e.info.sampleRate)},{id:159,data:e.info.numberOfChannels}]}]}subtitleSpecificTrackInfo(e){return[{id:25506,data:_.encode(e.info.config.description)}]}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:Gt,data:[this.format._options.streamable?null:this.seekHead,this.segmentInfo,this.tracksElement]};this.segment=e,this.writeEBML(e)}createCues(){this.cues={id:475249515,data:[]}}get segmentDataOffset(){return d(this.segment),this.dataOffsets.get(this.segment)}getVideoTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Ie(t),d(t),d(t.decoderConfig),d(t.decoderConfig.codedWidth!==void 0),d(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Oe(t),d(t),d(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Ve(t),d(t),d(t.config);let s={track:e,type:"subtitle",info:{config:t.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getVideoTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=t.type==="key",c=this.validateAndNormalizeTimestamp(n.track,t.timestamp,a),u=this.createInternalChunk(o,c,(t.duration??0)/1e6,t.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(n,u),n.chunkQueue.push(u),await this.interleaveChunks()}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getAudioTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=t.type,c=a==="key",u=this.validateAndNormalizeTimestamp(n.track,t.timestamp,c),l=this.createInternalChunk(o,u,(t.duration??0)/1e6,a);n.chunkQueue.push(l),await this.interleaveChunks()}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let n=this.getSubtitleTrackData(e,i),o=this.validateAndNormalizeTimestamp(n.track,1e6*t.timestamp,!0),a=t.text,c=Math.floor(o*1e3);Z.lastIndex=0,a=a.replace(Z,g=>{let C=we(g.slice(1,-1))-c;return`<${Se(C)}>`});let u=_.encode(a),l=`${t.settings??""} ${t.identifier??""} -${t.notes??""}`,f=this.createInternalChunk(u,n,t.duration,"key",d.trim()?v.encode(d):null);o.chunkQueue.push(f),await this.interleaveChunks()}finally{s()}}async interleaveChunks(){for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.chunkQueue.length===0&&!s.track.source._closed)break e;s.chunkQueue.length>0&&s.chunkQueue[0].timestamp=2&&i++;let c={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];gt(t.data,i+0,i+3,c)}createInternalChunk(e,t,i,s,o=null){return{data:e,type:s,timestamp:t,duration:i,additions:o}}writeBlock(e,t){this.segment||(this.createTracks(),this.createSegment());let i=Math.floor(1e3*t.timestamp),s=this.trackDatas.every(d=>{if(d.track.source._closed)return!0;if(e===d)return t.type==="key";let f=d.chunkQueue[0];return f&&f.type==="key"});(!this.currentCluster||s&&i-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(i);let o=i-this.currentClusterMsTimestamp;if(o<0)return;if(o>=mt)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${mt} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${mt} milliseconds.`);let a=new Uint8Array(4),c=new DataView(a.buffer);c.setUint8(0,128|e.track.id),c.setInt16(1,o,!1);let u=Math.floor(1e3*t.duration);if(u===0&&!t.additions){c.setUint8(3,+(t.type==="key")<<7);let d={id:163,data:[a,t.data]};this.writeEBML(d)}else{let d={id:160,data:[{id:161,data:[a,t.data]},t.type==="delta"?{id:251,data:new ce(e.lastWrittenMsTimestamp-i)}:null,t.additions?{id:30113,data:[{id:166,data:[{id:165,data:t.additions},{id:238,data:1}]}]}:null,u>0?{id:155,data:u}:null]};this.writeEBML(d)}this.duration=Math.max(this.duration,i+u),e.lastWrittenMsTimestamp=i,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:Xt,data:[{id:231,data:e}]},this.writeEBML(this.currentCluster),this.currentClusterMsTimestamp=e,this.trackDatasInCurrentCluster.clear()}finalizeCurrentCluster(){l(this.currentCluster);let e=this.writer.getPos()-this.dataOffsets.get(this.currentCluster),t=this.writer.getPos();this.writer.seek(this.offsets.get(this.currentCluster)+4),this.writeEBMLVarInt(e,Xt),this.writer.seek(t);let i=this.offsets.get(this.currentCluster)-this.segmentDataOffset;l(this.cues),this.cues.data.push({id:187,data:[{id:179,data:this.currentClusterMsTimestamp},...[...this.trackDatasInCurrentCluster].map(s=>({id:183,data:[{id:247,data:s.track.id},{id:241,data:i}]}))]})}async onTrackClose(){let e=await this.mutex.acquire();await this.interleaveChunks(),e()}async finalize(){let e=await this.mutex.acquire();this.segment||(this.createTracks(),this.createSegment());for(let t of this.trackDatas)for(;t.chunkQueue.length>0;)this.writeBlock(t,t.chunkQueue.shift());if(!this.format._options.streamable&&this.currentCluster&&this.finalizeCurrentCluster(),l(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let t=this.writer.getPos(),i=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(i,qt),this.segmentDuration.data=new Z(this.duration),this.writer.seek(this.offsets.get(this.segmentDuration)),this.writeEBML(this.segmentDuration),this.seekHead.data[0].data[1].data=this.offsets.get(this.cues)-this.segmentDataOffset,this.seekHead.data[1].data[1].data=this.offsets.get(this.segmentInfo)-this.segmentDataOffset,this.seekHead.data[2].data[1].data=this.offsets.get(this.tracksElement)-this.segmentDataOffset,this.writer.seek(this.offsets.get(this.seekHead)),this.writeEBML(this.seekHead),this.writer.seek(t)}e()}};var R=class{},Oe=class extends R{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(e.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=e}_createMuxer(e){return new Ee(e,this)}},ue=class extends R{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.streamable!==void 0&&typeof e.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=e}_createMuxer(e){return new Ie(e,this)}},$=class extends ue{};var Q=class{_connectedTrack=null;_closed=!1;_offsetTimestamps=!1;_ensureValidDigest(){if(!this._connectedTrack)throw new Error("Cannot call digest without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call digest before output has been started.");if(this._connectedTrack.output._finalizing)throw new Error("Cannot call digest after output has started finalizing.");if(this._closed)throw new Error("Cannot call digest after source has been closed.")}_start(){}async _flush(){}close(){if(this._closed)throw new Error("Source already closed.");if(!this._connectedTrack)throw new Error("Cannot call close without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call close before output has been started.");this._closed=!0,!this._connectedTrack.output._finalizing&&this._connectedTrack.output._muxer.onTrackClose(this._connectedTrack)}},I=class extends Q{_connectedTrack=null;_codec;constructor(e){if(super(),!H.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${H.join(", ")}.`);this._codec=e}},Ve=class extends I{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,e,t)}},di=5,li=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!H.includes(r.codec))throw new TypeError(`Invalid video codec '${r.codec}'. Must be one of: ${H.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.");if(r.latencyMode!==void 0&&!["quality","realtime"].includes(r.latencyMode))throw new TypeError("config.latencyMode, when provided, must be 'quality' or 'realtime'.")},de=class{constructor(e,t){this.source=e;this.codecConfig=t;li(t)}encoder=null;muxer=null;lastMultipleOfKeyFrameInterval=-1;lastWidth=null;lastHeight=null;async digest(e){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(e.codedWidth!==this.lastWidth||e.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${e.codedWidth}x${e.codedHeight}.`)}else this.lastWidth=e.codedWidth,this.lastHeight=e.codedHeight;this.ensureEncoder(e),l(this.encoder);let t=Math.floor(e.timestamp/1e6/di);this.encoder.encode(e,{keyFrame:t!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=t,this.encoder.encodeQueueSize>=4&&await new Promise(i=>this.encoder.addEventListener("dequeue",i,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new VideoEncoder({output:(t,i)=>void this.muxer.addEncodedVideoChunk(this.source._connectedTrack,t,i),error:t=>console.error("Video encode error:",t)}),this.encoder.configure({codec:Wt(this.codecConfig.codec,e.codedWidth,e.codedHeight,this.codecConfig.bitrate),width:e.codedWidth,height:e.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode,...$t(this.codecConfig.codec)}),l(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Me=class extends I{_encoder;constructor(e){super(e.codec),this._encoder=new de(this,e)}digest(e){if(!(e instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},Re=class extends I{_encoder;_canvas;constructor(e,t){if(!(e instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(t.codec),this._encoder=new de(this,t),this._canvas=e}digest(e,t=0){if(!Number.isFinite(e)||e<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(t)||t<0)throw new TypeError("duration must be a non-negative number.");let i=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*e),duration:Math.round(1e6*t),alpha:"discard"}),s=this._encoder.digest(i);return i.close(),s}_flush(){return this._encoder.flush()}},Pe=class extends I{_encoder;_abortController=null;_track;_offsetTimestamps=!0;constructor(e,t){if(!(e instanceof MediaStreamTrack)||e.kind!=="video")throw new TypeError("track must be a video MediaStreamTrack.");t={...t,latencyMode:"realtime"},super(t.codec),this._encoder=new de(this,t),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),t=new WritableStream({write:i=>{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},O=class extends Q{_connectedTrack=null;_codec;constructor(e){if(super(),!L.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${L.join(", ")}.`);this._codec=e}},ze=class extends O{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,e,t)}},mi=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!L.includes(r.codec))throw new TypeError(`Invalid audio codec '${r.codec}'. Must be one of: ${L.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},le=class{constructor(e,t){this.source=e;this.codecConfig=t;mi(t)}encoder=null;muxer=null;lastNumberOfChannels=null;lastSampleRate=null;async digest(e){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(e.numberOfChannels!==this.lastNumberOfChannels||e.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${e.numberOfChannels} channels at ${e.sampleRate} Hz.`)}else this.lastNumberOfChannels=e.numberOfChannels,this.lastSampleRate=e.sampleRate;this.ensureEncoder(e),l(this.encoder),this.encoder.encode(e),this.encoder.encodeQueueSize>=4&&await new Promise(t=>this.encoder.addEventListener("dequeue",t,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new AudioEncoder({output:(t,i)=>void this.muxer.addEncodedAudioChunk(this.source._connectedTrack,t,i),error:t=>console.error("Audio encode error:",t)}),this.encoder.configure({codec:Ht(this.codecConfig.codec,e.numberOfChannels,e.sampleRate),numberOfChannels:e.numberOfChannels,sampleRate:e.sampleRate,bitrate:this.codecConfig.bitrate,...Qt(this.codecConfig.codec)}),l(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Be=class extends O{_encoder;constructor(e){super(e.codec),this._encoder=new le(this,e)}digest(e){if(!(e instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},Ue=class extends O{_encoder;_accumulatedFrameCount=0;constructor(e){super(e.codec),this._encoder=new le(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let t=e.numberOfChannels,i=e.sampleRate,s=e.length,o=new Float32Array(t*s);for(let c=0;c{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},j=class extends Q{_connectedTrack=null;_codec;constructor(e){if(super(),!ne.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${ne.join(", ")}.`);this._codec=e}},Fe=class extends j{_parser;constructor(e){super(e),this._parser=new ke({codec:e,output:(t,i)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,t,i),error:t=>console.error("Subtitle parse error:",t)})}digest(e){if(typeof e!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(e),this._connectedTrack.output._muxer.mutex.currentPromise}};var We=class{_muxer;_writer;_tracks=[];_started=!1;_finalizing=!1;_mutex=new K;constructor(e){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(!(e.format instanceof R))throw new TypeError("options.format must be an OutputFormat.");if(!(e.target instanceof M))throw new TypeError("options.target must be a Target.");if(e.target._output)throw new Error("Target is already used for another output.");e.target._output=this,this._writer=e.target._createWriter(),this._muxer=e.format._createMuxer(this)}addVideoTrack(e,t={}){if(!(e instanceof I))throw new TypeError("source must be a VideoSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");if(typeof t.rotation=="number"&&![0,90,180,270].includes(t.rotation))throw new TypeError(`Invalid video rotation: ${t.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(t.rotation)&&(t.rotation.length!==9||t.rotation.some(i=>!Number.isFinite(i))))throw new TypeError(`Invalid video transformation matrix: ${t.rotation.join()}`);if(t.frameRate!==void 0&&(!Number.isInteger(t.frameRate)||t.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${t.frameRate}. Must be a positive integer.`);this._addTrack("video",e,t)}addAudioTrack(e,t={}){if(!(e instanceof O))throw new TypeError("source must be an AudioSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",e,t)}addSubtitleTrack(e,t={}){if(!(e instanceof j))throw new TypeError("source must be a SubtitleSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",e,t)}_addTrack(e,t,i){if(this._started)throw new Error("Cannot add track after output has started.");if(t._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:e,source:t,metadata:i};this._muxer.beforeTrackAdd(s),this._tracks.push(s),t._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let e=await this._mutex.acquire();await this._muxer.start();for(let t of this._tracks)t.source._start();e()}async finalize(){if(!this._started)throw new Error("Cannot finalize before starting.");if(this._finalizing)throw new Error("Cannot call finalize twice.");this._finalizing=!0;let e=await this._mutex.acquire(),t=this._tracks.map(i=>i.source._flush());await Promise.all(t),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),e()}};var J=class{},Ne=class extends J{constructor(t){super();this.buffer=t}async _read(t,i){return new Uint8Array(this.buffer,t,i-t)}async _getSize(){return this.buffer.byteLength}},He=class extends J{constructor(t){super();this.blob=t}async _read(t,i){let o=await this.blob.slice(t,i).arrayBuffer();return new Uint8Array(o)}async _getSize(){return this.blob.size}};var ee=class{input;constructor(e){this.input=e}};var Le=class{_backing;constructor(e){this._backing=e}isVideoTrack(){return this instanceof me}isAudioTrack(){return this instanceof fe}getDuration(){return this._backing.getDuration()}},me=class extends Le{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getWidth(){return this._backing.getWidth()}getHeight(){return this._backing.getHeight()}getRotation(){return this._backing.getRotation()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}},fe=class extends Le{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getNumberOfChannels(){return this._backing.getNumberOfChannels()}getSampleRate(){return this._backing.getSampleRate()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}};var te=class{constructor(e){this.reader=e}pos=0;readRange(e,t){let{view:i,offset:s}=this.reader.getViewAndOffset(e,t);return new Uint8Array(i.buffer,s,t-e)}readU8(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+1);return this.pos++,e.getUint8(t)}readU16(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+2);return this.pos+=2,e.getUint16(t,!1)}readU24(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+3);this.pos+=3;let i=e.getUint16(t,!1),s=e.getUint8(t+2);return i*256+s}readS32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getUint32(t,!1)}readI32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU64(){let e=this.readU32(),t=this.readU32();return e*4294967296+t}readF64(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+8);return this.pos+=8,e.getFloat64(t,!1)}readFixed_16_16(){return this.readS32()/65536}readFixed_2_30(){return this.readS32()/1073741824}readAscii(e){let{view:t,offset:i}=this.reader.getViewAndOffset(this.pos,this.pos+e);this.pos+=e;let s="";for(let o=0;oe.inputTrack)}async getMimeType(){await this.readMetadata();let e="video/mp4";if(this.tracks.length>0){let t=await Promise.all(this.tracks.map(s=>s.inputTrack.getCodecMimeType())),i=[...new Set(t)];e+=`; codecs="${i.join(", ")}"`}return e}readMetadata(){return this.metadataPromise??=(async()=>{let e=await this.isobmffReader.reader.getSourceSize();for(;this.isobmffReader.posi.presentationTimestamp-s.presentationTimestamp),e.sampleTable}readContiguousBoxes(e){let t=this.isobmffReader.pos;for(;this.isobmffReader.pos-td.every((f,T)=>f===c[T]));u===-1?s.rotation=0:s.rotation=90*u}break;case"mdhd":{let s=this.currentTrack;l(s);let o=this.isobmffReader.readU8();this.isobmffReader.pos+=3,o===0?(this.isobmffReader.pos+=8,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU32()):o===1&&(this.isobmffReader.pos+=16,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU64())}break;case"hdlr":{let s=this.currentTrack;l(s),this.isobmffReader.pos+=8;let o=this.isobmffReader.readAscii(4);o==="vide"?s.info={type:"video",width:-1,height:-1,codec:null,codecDescription:null,colorSpace:null}:o==="soun"&&(s.info={type:"audio",numberOfChannels:-1,sampleRate:-1,codec:null,codecDescription:null})}break;case"stbl":{let s=this.currentTrack;l(s),s.sampleTableOffset=e,this.readContiguousBoxes(t.contentSize)}break;case"stsd":{let s=this.currentTrack;if(l(s),s.info===null||s.sampleTable)break;let o=this.isobmffReader.readU8();this.isobmffReader.pos+=3;let n=this.isobmffReader.readU32();for(let a=0;a0){if(u===1)this.isobmffReader.pos+=4*4;else if(u===2){this.isobmffReader.pos+=4,f=this.isobmffReader.readF64(),d=this.isobmffReader.readU32(),this.isobmffReader.pos+=4;let T=this.isobmffReader.readU32(),C=this.isobmffReader.readU32(),k=this.isobmffReader.readU32(),w=this.isobmffReader.readU32()}}s.info.numberOfChannels=d,s.info.sampleRate=f,this.readContiguousBoxes(e+c.totalSize-this.isobmffReader.pos)}}}break;case"avcC":{let s=this.currentTrack;l(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"hvcC":{let s=this.currentTrack;l(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"colr":{let s=this.currentTrack;if(l(s&&s.info?.type==="video"),this.isobmffReader.readAscii(4)!=="nclx")break;let n=this.isobmffReader.readU16(),a=this.isobmffReader.readU16(),c=this.isobmffReader.readU16(),u=!!(this.isobmffReader.readU8()&128);s.info.colorSpace={primaries:Tt[n],transfer:xt[a],matrix:Ct[c],fullRange:u}}break;case"wave":t.totalSize>8&&this.readContiguousBoxes(t.contentSize);break;case"esds":{let s=this.currentTrack;l(s&&s.info),this.isobmffReader.pos+=4;let o=this.isobmffReader.readU8();l(o===3),this.isobmffReader.readIsomVariableInteger(),this.isobmffReader.pos+=2;let n=this.isobmffReader.readU8(),a=(n&128)!==0,c=(n&64)!==0,u=(n&32)!==0;if(a&&(this.isobmffReader.pos+=2),c){let k=this.isobmffReader.readU8();this.isobmffReader.pos+=k}u&&(this.isobmffReader.pos+=2);let d=this.isobmffReader.readU8();l(d===4),this.isobmffReader.readIsomVariableInteger();let f=this.isobmffReader.readU8();l(f===64),this.isobmffReader.pos+=12;let T=this.isobmffReader.readU8();l(T===5);let C=this.isobmffReader.readIsomVariableInteger();s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+C)}break;case"stts":{let s=this.currentTrack;if(l(s),!s.sampleTable)break;this.isobmffReader.pos+=4;let o=this.isobmffReader.readU32(),n=0,a=0;for(let c=0;c{let t=W(r.presentationTimestamps,e,i=>i.presentationTimestamp);return t===-1?-1:r.presentationTimestamps[t].sampleIndex},hi=(r,e)=>{let t=W(r.sampleTimingEntries,e,k=>k.startIndex),i=r.sampleTimingEntries[t];if(!i||i.startIndex+i.count<=e)return null;let o=i.startDecodeTimestamp+(e-i.startIndex)*i.delta,n=W(r.sampleCompositionTimeOffsets,e,k=>k.startIndex),a=r.sampleCompositionTimeOffsets[n];a&&(o+=a.offset);let c=r.sampleSizes[Math.min(e,r.sampleSizes.length-1)],u=W(r.sampleToChunk,e,k=>k.startSampleIndex),d=r.sampleToChunk[u];l(d);let f=d.startChunkIndex+Math.floor((e-d.startSampleIndex)/d.samplesPerChunk),C=r.chunkOffsets[f];if(r.sampleSizes.length===1)C+=c*(e-d.startSampleIndex);else{let k=d.startSampleIndex+(f-d.startChunkIndex)*d.samplesPerChunk;for(let w=k;wk)!==-1:!0}},pi=(r,e)=>{if(!r.keySampleIndices)return e;let t=W(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t]??-1},bi=(r,e)=>{if(!r.keySampleIndices)return e+1;let t=W(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t+1]??-1};var je=class extends ee{};var Ke=class{},pt=class extends Ke{async _canReadInput(e){if(await e._reader.getSourceSize()<8)return!1;await e._reader.loadRange(4,8);let i=new te(e._reader);return i.pos=4,i.readAscii(4)==="ftyp"}_createDemuxer(e){return new $e(e)}},bt=class extends Ke{async _canReadInput(){return!1}_createDemuxer(e){return new je(e)}},he=new pt,Yt=he,Zt=he,qe=new bt,kt=qe,Jt=qe,er=[he,kt];var Xe=4096,Ge=class{constructor(e){this.source=e}loadedSegments=[];sourceSizePromise=null;getSourceSize(){return this.sourceSizePromise?this.sourceSizePromise:this.sourceSizePromise=this.source._getSize()}async loadRange(e,t){let i=Math.floor(e/Xe)*Xe,s=Math.ceil(t/Xe)*Xe;s=Math.min(s,await this.getSourceSize());let o=this.loadedSegments.find(c=>c.start<=i);o&&(i=Math.max(i,o.end));let n=this.loadedSegments.find(c=>c.end>=s);if(n&&(s=Math.min(s,n.start)),i>=s)return;let a=await this.source._read(i,s);this.insertIntoLoadedSegments(i,a)}insertIntoLoadedSegments(e,t){let i={start:e,end:e+t.byteLength,bytes:t,view:new DataView(t.buffer)},s=this.loadedSegments.findLastIndex(d=>d.start<=e);this.loadedSegments.splice(s+1,0,i),(s===-1||this.loadedSegments[s].enda&&this.loadedSegments[a+1].start<=c;)a++,c=Math.max(c,this.loadedSegments[a].end);if(o===a)return;for(let d=o;d<=a;d++){let f=this.loadedSegments[d];if(f.start===n&&f.end===c){this.loadedSegments.splice(d+1,a-d),this.loadedSegments.splice(o,d-o);return}}let u=new Uint8Array(c-n);for(let d=o;d<=a;d++){let f=this.loadedSegments[d];u.set(f.bytes,f.start-n)}this.loadedSegments.splice(o+1,a-o),this.loadedSegments[o].end=c,this.loadedSegments[o].bytes=u,this.loadedSegments[o].view=new DataView(u.buffer)}getViewAndOffset(e,t){let i=this.loadedSegments.find(s=>s.start<=e&&t<=s.end);if(!i)throw new Error(`No segment loaded for range [${e}, ${t}).`);return{view:i.view,offset:i.bytes.byteOffset+e-i.start}}};var Ye=class{_formats;_reader;_demuxerPromise=null;_format=null;constructor(e){this._formats=e.formats,this._reader=new Ge(e.source)}_getDemuxer(){return this._demuxerPromise??=(async()=>{for(let e of this._formats)if(await e._canReadInput(this))return this._format=e,e._createDemuxer(this);throw new Error("Input has an unrecognizable format.")})()}async getFormat(){return await this._getDemuxer(),l(this._format),this._format}async getDuration(){return(await this._getDemuxer()).getDuration()}async getTracks(){return(await this._getDemuxer()).getTracks()}async getVideoTracks(){return(await this.getTracks()).filter(t=>t.isVideoTrack())}async getPrimaryVideoTrack(){return(await this.getTracks()).find(t=>t.isVideoTrack())??null}async getAudioTracks(){return(await this.getTracks()).filter(t=>t.isAudioTrack())}async getPrimaryAudioTrack(){return(await this.getTracks()).find(t=>t.isAudioTrack())??null}async getMimeType(){return(await this._getDemuxer()).getMimeType()}};var Ze=class{constructor(e){this.videoTrack=e}getFirstChunk(){return this.videoTrack._backing.getFirstChunk()}getChunk(e){return this.videoTrack._backing.getChunk(e)}getNextChunk(e){return this.videoTrack._backing.getNextChunk(e)}getKeyChunk(e){return this.videoTrack._backing.getKeyChunk(e)}getNextKeyChunk(e){return this.videoTrack._backing.getNextKeyChunk(e)}async*chunks(e=0){let t=await this.getChunk(e);for(;t;)yield t,t=await this.getNextChunk(t)}},Je=class{constructor(e){this.videoTrack=e}decoderConfig=null;async createDecoder(e){this.decoderConfig||(this.decoderConfig=await this.videoTrack.getDecoderConfig());let t=new VideoDecoder({output:e,error:i=>console.error(i)});return t.configure(this.decoderConfig),t}async getKeyFrame(e){let t=null,i=await this.createDecoder(o=>t=o),s=await this.videoTrack._backing.getKeyChunk(e);return s?(i.decode(s),await i.flush(),i.close(),t):null}async getFrame(e){let t=null,i=await this.createDecoder(a=>{a.timestamp/1e6<=e?(t?.close(),t=a):a.close()}),s=await this.videoTrack._backing.getKeyChunk(e);if(!s)return null;let o=await this.videoTrack._backing.getChunk(e);l(o),i.decode(s);let n=s;for(;n!==o;){let a=await this.videoTrack._backing.getNextChunk(n);l(a),n=a,i.decode(a),i.decodeQueueSize>=10&&await new Promise(c=>i.addEventListener("dequeue",c,{once:!0}))}return await i.flush(),i.close(),t}async*frames(e=0){let t=[],i=!1,s=null,{promise:o,resolve:n}=st(),a=!1,c=await this.createDecoder(f=>{if(a){f.close();return}let T=f.timestamp/1e6;s&&(T>e?(t.push(s),i=!0):s.close()),T>=e&&(t.push(f),i=!0),s=i?null:f,t.length>0&&(n(),{promise:o,resolve:n}=st())}),u=await this.videoTrack._backing.getKeyChunk(e);if(!u)return;let d=!1;(async()=>{let f=u;for(;f&&!a;)c.decode(f),c.decodeQueueSize>=10&&await new Promise(C=>c.addEventListener("dequeue",C,{once:!0})),f=await this.videoTrack._backing.getNextChunk(f);await c.flush(),c.close(),d=!0,n()})();try{for(;;)if(t.length>0)yield t.shift();else if(!d)await o;else break}finally{a=!0}}};return nr(ki);})(); +${t.notes??""}`,f=this.createInternalChunk(u,o,t.duration,"key",l.trim()?_.encode(l):null);n.chunkQueue.push(f),await this.interleaveChunks()}finally{s()}}async interleaveChunks(){for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.chunkQueue.length===0&&!s.track.source._closed)break e;s.chunkQueue.length>0&&s.chunkQueue[0].timestamp=2&&i++;let c={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];Tt(t.data,i+0,i+3,c)}createInternalChunk(e,t,i,s,n=null){return{data:e,type:s,timestamp:t,duration:i,additions:n}}writeBlock(e,t){this.segment||(this.createTracks(),this.createSegment());let i=Math.floor(1e3*t.timestamp),s=this.trackDatas.every(l=>{if(l.track.source._closed)return!0;if(e===l)return t.type==="key";let f=l.chunkQueue[0];return f&&f.type==="key"});(!this.currentCluster||s&&i-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(i);let n=i-this.currentClusterMsTimestamp;if(n<0)return;if(n>=ft)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${ft} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${ft} milliseconds.`);let a=new Uint8Array(4),c=new DataView(a.buffer);c.setUint8(0,128|e.track.id),c.setInt16(1,n,!1);let u=Math.floor(1e3*t.duration);if(u===0&&!t.additions){c.setUint8(3,+(t.type==="key")<<7);let l={id:163,data:[a,t.data]};this.writeEBML(l)}else{let l={id:160,data:[{id:161,data:[a,t.data]},t.type==="delta"?{id:251,data:new me(e.lastWrittenMsTimestamp-i)}:null,t.additions?{id:30113,data:[{id:166,data:[{id:165,data:t.additions},{id:238,data:1}]}]}:null,u>0?{id:155,data:u}:null]};this.writeEBML(l)}this.duration=Math.max(this.duration,i+u),e.lastWrittenMsTimestamp=i,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:Yt,data:[{id:231,data:e}]},this.writeEBML(this.currentCluster),this.currentClusterMsTimestamp=e,this.trackDatasInCurrentCluster.clear()}finalizeCurrentCluster(){d(this.currentCluster);let e=this.writer.getPos()-this.dataOffsets.get(this.currentCluster),t=this.writer.getPos();this.writer.seek(this.offsets.get(this.currentCluster)+4),this.writeEBMLVarInt(e,Yt),this.writer.seek(t);let i=this.offsets.get(this.currentCluster)-this.segmentDataOffset;d(this.cues),this.cues.data.push({id:187,data:[{id:179,data:this.currentClusterMsTimestamp},...[...this.trackDatasInCurrentCluster].map(s=>({id:183,data:[{id:247,data:s.track.id},{id:241,data:i}]}))]})}async onTrackClose(){let e=await this.mutex.acquire();await this.interleaveChunks(),e()}async finalize(){let e=await this.mutex.acquire();this.segment||(this.createTracks(),this.createSegment());for(let t of this.trackDatas)for(;t.chunkQueue.length>0;)this.writeBlock(t,t.chunkQueue.shift());if(!this.format._options.streamable&&this.currentCluster&&this.finalizeCurrentCluster(),d(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let t=this.writer.getPos(),i=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(i,Gt),this.segmentDuration.data=new re(this.duration),this.writer.seek(this.offsets.get(this.segmentDuration)),this.writeEBML(this.segmentDuration),this.seekHead.data[0].data[1].data=this.offsets.get(this.cues)-this.segmentDataOffset,this.seekHead.data[1].data[1].data=this.offsets.get(this.segmentInfo)-this.segmentDataOffset,this.seekHead.data[2].data[1].data=this.offsets.get(this.tracksElement)-this.segmentDataOffset,this.writer.seek(this.offsets.get(this.seekHead)),this.writeEBML(this.seekHead),this.writer.seek(t)}e()}};var z=class{},Pe=class extends z{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(e.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=e}_createMuxer(e){return new Re(e,this)}},fe=class extends z{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.streamable!==void 0&&typeof e.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=e}_createMuxer(e){return new Me(e,this)}},K=class extends fe{};var q=class{_connectedTrack=null;_closed=!1;_offsetTimestamps=!1;_ensureValidDigest(){if(!this._connectedTrack)throw new Error("Cannot call digest without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call digest before output has been started.");if(this._connectedTrack.output._finalizing)throw new Error("Cannot call digest after output has started finalizing.");if(this._closed)throw new Error("Cannot call digest after source has been closed.")}_start(){}async _flush(){}close(){if(this._closed)throw new Error("Source already closed.");if(!this._connectedTrack)throw new Error("Cannot call close without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call close before output has been started.");this._closed=!0,!this._connectedTrack.output._finalizing&&this._connectedTrack.output._muxer.onTrackClose(this._connectedTrack)}},V=class extends q{_connectedTrack=null;_codec;constructor(e){if(super(),!$.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${$.join(", ")}.`);this._codec=e}},ze=class extends V{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,e,t)}},mi=5,fi=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!$.includes(r.codec))throw new TypeError(`Invalid video codec '${r.codec}'. Must be one of: ${$.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.");if(r.latencyMode!==void 0&&!["quality","realtime"].includes(r.latencyMode))throw new TypeError("config.latencyMode, when provided, must be 'quality' or 'realtime'.")},he=class{constructor(e,t){this.source=e;this.codecConfig=t;fi(t)}encoder=null;muxer=null;lastMultipleOfKeyFrameInterval=-1;lastWidth=null;lastHeight=null;async digest(e){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(e.codedWidth!==this.lastWidth||e.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${e.codedWidth}x${e.codedHeight}.`)}else this.lastWidth=e.codedWidth,this.lastHeight=e.codedHeight;this.ensureEncoder(e),d(this.encoder);let t=Math.floor(e.timestamp/1e6/mi);this.encoder.encode(e,{keyFrame:t!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=t,this.encoder.encodeQueueSize>=4&&await new Promise(i=>this.encoder.addEventListener("dequeue",i,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new VideoEncoder({output:(t,i)=>void this.muxer.addEncodedVideoChunk(this.source._connectedTrack,t,i),error:t=>console.error("Video encode error:",t)}),this.encoder.configure({codec:Ht(this.codecConfig.codec,e.codedWidth,e.codedHeight,this.codecConfig.bitrate),width:e.codedWidth,height:e.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode,...jt(this.codecConfig.codec)}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Be=class extends V{_encoder;constructor(e){super(e.codec),this._encoder=new he(this,e)}digest(e){if(!(e instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},Ue=class extends V{_encoder;_canvas;constructor(e,t){if(!(e instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(t.codec),this._encoder=new he(this,t),this._canvas=e}digest(e,t=0){if(!Number.isFinite(e)||e<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(t)||t<0)throw new TypeError("duration must be a non-negative number.");let i=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*e),duration:Math.round(1e6*t),alpha:"discard"}),s=this._encoder.digest(i);return i.close(),s}_flush(){return this._encoder.flush()}},De=class extends V{_encoder;_abortController=null;_track;_offsetTimestamps=!0;constructor(e,t){if(!(e instanceof MediaStreamTrack)||e.kind!=="video")throw new TypeError("track must be a video MediaStreamTrack.");t={...t,latencyMode:"realtime"},super(t.codec),this._encoder=new he(this,t),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),t=new WritableStream({write:i=>{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},R=class extends q{_connectedTrack=null;_codec;constructor(e){if(super(),!j.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${j.join(", ")}.`);this._codec=e}},Fe=class extends R{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,e,t)}},hi=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!j.includes(r.codec))throw new TypeError(`Invalid audio codec '${r.codec}'. Must be one of: ${j.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},pe=class{constructor(e,t){this.source=e;this.codecConfig=t;hi(t)}encoder=null;muxer=null;lastNumberOfChannels=null;lastSampleRate=null;async digest(e){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(e.numberOfChannels!==this.lastNumberOfChannels||e.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${e.numberOfChannels} channels at ${e.sampleRate} Hz.`)}else this.lastNumberOfChannels=e.numberOfChannels,this.lastSampleRate=e.sampleRate;this.ensureEncoder(e),d(this.encoder),this.encoder.encode(e),this.encoder.encodeQueueSize>=4&&await new Promise(t=>this.encoder.addEventListener("dequeue",t,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new AudioEncoder({output:(t,i)=>void this.muxer.addEncodedAudioChunk(this.source._connectedTrack,t,i),error:t=>console.error("Audio encode error:",t)}),this.encoder.configure({codec:Qt(this.codecConfig.codec,e.numberOfChannels,e.sampleRate),numberOfChannels:e.numberOfChannels,sampleRate:e.sampleRate,bitrate:this.codecConfig.bitrate,...Kt(this.codecConfig.codec)}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},We=class extends R{_encoder;constructor(e){super(e.codec),this._encoder=new pe(this,e)}digest(e){if(!(e instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},Ne=class extends R{_encoder;_accumulatedFrameCount=0;constructor(e){super(e.codec),this._encoder=new pe(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let t=e.numberOfChannels,i=e.sampleRate,s=e.length,n=new Float32Array(t*s);for(let c=0;c{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},X=class extends q{_connectedTrack=null;_codec;constructor(e){if(super(),!de.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${de.join(", ")}.`);this._codec=e}},Le=class extends X{_parser;constructor(e){super(e),this._parser=new Ce({codec:e,output:(t,i)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,t,i),error:t=>console.error("Subtitle parse error:",t)})}digest(e){if(typeof e!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(e),this._connectedTrack.output._muxer.mutex.currentPromise}};var Qe=class{_muxer;_writer;_tracks=[];_started=!1;_finalizing=!1;_mutex=new Y;constructor(e){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(!(e.format instanceof z))throw new TypeError("options.format must be an OutputFormat.");if(!(e.target instanceof P))throw new TypeError("options.target must be a Target.");if(e.target._output)throw new Error("Target is already used for another output.");e.target._output=this,this._writer=e.target._createWriter(),this._muxer=e.format._createMuxer(this)}addVideoTrack(e,t={}){if(!(e instanceof V))throw new TypeError("source must be a VideoSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");if(typeof t.rotation=="number"&&![0,90,180,270].includes(t.rotation))throw new TypeError(`Invalid video rotation: ${t.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(t.rotation)&&(t.rotation.length!==9||t.rotation.some(i=>!Number.isFinite(i))))throw new TypeError(`Invalid video transformation matrix: ${t.rotation.join()}`);if(t.frameRate!==void 0&&(!Number.isInteger(t.frameRate)||t.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${t.frameRate}. Must be a positive integer.`);this._addTrack("video",e,t)}addAudioTrack(e,t={}){if(!(e instanceof R))throw new TypeError("source must be an AudioSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",e,t)}addSubtitleTrack(e,t={}){if(!(e instanceof X))throw new TypeError("source must be a SubtitleSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",e,t)}_addTrack(e,t,i){if(this._started)throw new Error("Cannot add track after output has started.");if(t._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:e,source:t,metadata:i};this._muxer.beforeTrackAdd(s),this._tracks.push(s),t._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let e=await this._mutex.acquire();await this._muxer.start();for(let t of this._tracks)t.source._start();e()}async finalize(){if(!this._started)throw new Error("Cannot finalize before starting.");if(this._finalizing)throw new Error("Cannot call finalize twice.");this._finalizing=!0;let e=await this._mutex.acquire(),t=this._tracks.map(i=>i.source._flush());await Promise.all(t),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),e()}};var ie=class{_sizePromise=null;_getSize(){return this._sizePromise??=this._retrieveSize()}},$e=class extends ie{constructor(t){super();this.buffer=t}async _read(t,i){return new Uint8Array(this.buffer,t,i-t)}async _retrieveSize(){return this.buffer.byteLength}},je=class extends ie{constructor(t){super();this.blob=t}async _read(t,i){let n=await this.blob.slice(t,i).arrayBuffer();return new Uint8Array(n)}async _retrieveSize(){return this.blob.size}};var se=class{input;constructor(e){this.input=e}};var Ke=class{_backing;constructor(e){this._backing=e}isVideoTrack(){return this instanceof be}isAudioTrack(){return this instanceof ke}getDuration(){return this._backing.getDuration()}},be=class extends Ke{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getWidth(){return this._backing.getWidth()}getHeight(){return this._backing.getHeight()}getRotation(){return this._backing.getRotation()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}},ke=class extends Ke{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getNumberOfChannels(){return this._backing.getNumberOfChannels()}getSampleRate(){return this._backing.getSampleRate()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}};var qe=4096,ne=class{constructor(e,t=1/0){this.source=e;this.maxStorableBytes=t}loadedSegments=[];loadingSegments=[];sourceSizePromise=null;nextAge=0;totalStoredBytes=0;async loadRange(e,t){let i=Math.floor(e/qe)*qe,s=Math.ceil(t/qe)*qe;s=Math.min(s,await this.source._getSize());let n=this.loadingSegments.find(l=>l.start<=i&&l.end>=s);if(n){await n.promise;return}if(this.loadedSegments.some(l=>l.start<=i&&l.end>=s))return;let a=this.source._read(i,s),c={start:i,end:s,promise:a};this.loadingSegments.push(c);let u=await a;_t(this.loadingSegments,c),this.insertIntoLoadedSegments(i,u)}insertIntoLoadedSegments(e,t){let i={start:e,end:e+t.byteLength,bytes:t,view:new DataView(t.buffer),age:this.nextAge++},s=E(this.loadedSegments,e,n=>n.start);(s===-1||this.loadedSegments[s].start=i.end)break;i.start<=o.start&&o.end<=i.end&&(this.loadedSegments.splice(n,1),n--)}for(;this.totalStoredBytes>this.maxStorableBytes&&this.loadedSegments.length>1;){let n=null,o=-1;for(let a=0;an.start),s=null;if(i!==-1)for(let n=i;ne)break;if(t<=o.end){s=o;break}}if(!s)throw new Error(`No segment loaded for range [${e}, ${t}).`);return s.age=this.nextAge++,{view:s.view,offset:s.bytes.byteOffset+e-s.start}}};var G=class{constructor(e){this.reader=e}pos=0;readRange(e,t){let{view:i,offset:s}=this.reader.getViewAndOffset(e,t);return new Uint8Array(i.buffer,s,t-e)}readU8(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+1);return this.pos++,e.getUint8(t)}readU16(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+2);return this.pos+=2,e.getUint16(t,!1)}readU24(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+3);this.pos+=3;let i=e.getUint16(t,!1),s=e.getUint8(t+2);return i*256+s}readS32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getUint32(t,!1)}readI32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU64(){let e=this.readU32(),t=this.readU32();return e*4294967296+t}readF64(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+8);return this.pos+=8,e.getFloat64(t,!1)}readFixed_16_16(){return this.readS32()/65536}readFixed_2_30(){return this.readS32()/1073741824}readAscii(e){let{view:t,offset:i}=this.reader.getViewAndOffset(this.pos,this.pos+e);this.pos+=e;let s="";for(let n=0;ne.inputTrack)}async getMimeType(){await this.readMetadata();let e="video/mp4";if(this.tracks.length>0){let t=await Promise.all(this.tracks.map(s=>s.inputTrack.getCodecMimeType())),i=[...new Set(t)];e+=`; codecs="${i.join(", ")}"`}return e}readMetadata(){return this.metadataPromise??=(async()=>{let e=await this.isobmffReader.reader.source._getSize();for(;this.isobmffReader.posi.presentationTimestamp-s.presentationTimestamp),e.sampleTable}readContiguousBoxes(e){let t=this.isobmffReader.pos;for(;this.isobmffReader.pos-tl.every((f,g)=>f===c[g]));u===-1?s.rotation=0:s.rotation=90*u}break;case"mdhd":{let s=this.currentTrack;d(s);let n=this.isobmffReader.readU8();this.isobmffReader.pos+=3,n===0?(this.isobmffReader.pos+=8,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU32()):n===1&&(this.isobmffReader.pos+=16,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU64())}break;case"hdlr":{let s=this.currentTrack;d(s),this.isobmffReader.pos+=8;let n=this.isobmffReader.readAscii(4);n==="vide"?s.info={type:"video",width:-1,height:-1,codec:null,codecDescription:null,colorSpace:null}:n==="soun"&&(s.info={type:"audio",numberOfChannels:-1,sampleRate:-1,codec:null,codecDescription:null})}break;case"stbl":{let s=this.currentTrack;d(s),s.sampleTableOffset=e,this.readContiguousBoxes(t.contentSize)}break;case"stsd":{let s=this.currentTrack;if(d(s),s.info===null||s.sampleTable)break;let n=this.isobmffReader.readU8();this.isobmffReader.pos+=3;let o=this.isobmffReader.readU32();for(let a=0;a0){if(u===1)this.isobmffReader.pos+=4*4;else if(u===2){this.isobmffReader.pos+=4,f=this.isobmffReader.readF64(),l=this.isobmffReader.readU32(),this.isobmffReader.pos+=4;let g=this.isobmffReader.readU32(),x=this.isobmffReader.readU32(),C=this.isobmffReader.readU32(),k=this.isobmffReader.readU32()}}s.info.numberOfChannels=l,s.info.sampleRate=f,this.readContiguousBoxes(e+c.totalSize-this.isobmffReader.pos)}}}break;case"avcC":{let s=this.currentTrack;d(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"hvcC":{let s=this.currentTrack;d(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"colr":{let s=this.currentTrack;if(d(s&&s.info?.type==="video"),this.isobmffReader.readAscii(4)!=="nclx")break;let o=this.isobmffReader.readU16(),a=this.isobmffReader.readU16(),c=this.isobmffReader.readU16(),u=!!(this.isobmffReader.readU8()&128);s.info.colorSpace={primaries:xt[o],transfer:Ct[a],matrix:wt[c],fullRange:u}}break;case"wave":t.totalSize>8&&this.readContiguousBoxes(t.contentSize);break;case"esds":{let s=this.currentTrack;d(s&&s.info),this.isobmffReader.pos+=4;let n=this.isobmffReader.readU8();d(n===3),this.isobmffReader.readIsomVariableInteger(),this.isobmffReader.pos+=2;let o=this.isobmffReader.readU8(),a=(o&128)!==0,c=(o&64)!==0,u=(o&32)!==0;if(a&&(this.isobmffReader.pos+=2),c){let C=this.isobmffReader.readU8();this.isobmffReader.pos+=C}u&&(this.isobmffReader.pos+=2);let l=this.isobmffReader.readU8();d(l===4),this.isobmffReader.readIsomVariableInteger();let f=this.isobmffReader.readU8();d(f===64),this.isobmffReader.pos+=12;let g=this.isobmffReader.readU8();d(g===5);let x=this.isobmffReader.readIsomVariableInteger();s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+x)}break;case"stts":{let s=this.currentTrack;if(d(s),!s.sampleTable)break;this.isobmffReader.pos+=4;let n=this.isobmffReader.readU32(),o=0,a=0;for(let c=0;c{let t=E(r.presentationTimestamps,e,i=>i.presentationTimestamp);return t===-1?-1:r.presentationTimestamps[t].sampleIndex},bi=(r,e)=>{let t=E(r.sampleTimingEntries,e,k=>k.startIndex),i=r.sampleTimingEntries[t];if(!i||i.startIndex+i.count<=e)return null;let n=i.startDecodeTimestamp+(e-i.startIndex)*i.delta,o=E(r.sampleCompositionTimeOffsets,e,k=>k.startIndex),a=r.sampleCompositionTimeOffsets[o];a&&(n+=a.offset);let c=r.sampleSizes[Math.min(e,r.sampleSizes.length-1)],u=E(r.sampleToChunk,e,k=>k.startSampleIndex),l=r.sampleToChunk[u];d(l);let f=l.startChunkIndex+Math.floor((e-l.startSampleIndex)/l.samplesPerChunk),g=r.chunkOffsets[f],x=0,C=g;if(r.sampleSizes.length===1)C+=c*(e-l.startSampleIndex),x+=c*l.samplesPerChunk;else{let k=l.startSampleIndex+(f-l.startChunkIndex)*l.samplesPerChunk;for(let S=k;Sk)!==-1:!0}},ki=(r,e)=>{if(!r.keySampleIndices)return e;let t=E(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t]??-1},gi=(r,e)=>{if(!r.keySampleIndices)return e+1;let t=E(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t+1]??-1};var Ye=class extends se{};var Ze=class{},bt=class extends Ze{async _canReadInput(e){if(await e._mainReader.source._getSize()<8)return!1;await e._mainReader.loadRange(4,8);let i=new G(e._mainReader);return i.pos=4,i.readAscii(4)==="ftyp"}_createDemuxer(e){return new Xe(e)}},kt=class extends Ze{async _canReadInput(){return!1}_createDemuxer(e){return new Ye(e)}},ge=new bt,Jt=ge,er=ge,Je=new kt,gt=Je,tr=Je,rr=[ge,gt];var et=class{_source;_formats;_mainReader;_demuxerPromise=null;_format=null;constructor(e){this._formats=e.formats,this._source=e.source,this._mainReader=new ne(e.source)}_getDemuxer(){return this._demuxerPromise??=(async()=>{for(let e of this._formats)if(await e._canReadInput(this))return this._format=e,e._createDemuxer(this);throw new Error("Input has an unrecognizable format.")})()}async getFormat(){return await this._getDemuxer(),d(this._format),this._format}async getDuration(){return(await this._getDemuxer()).getDuration()}async getTracks(){return(await this._getDemuxer()).getTracks()}async getVideoTracks(){return(await this.getTracks()).filter(t=>t.isVideoTrack())}async getPrimaryVideoTrack(){return(await this.getTracks()).find(t=>t.isVideoTrack())??null}async getAudioTracks(){return(await this.getTracks()).filter(t=>t.isAudioTrack())}async getPrimaryAudioTrack(){return(await this.getTracks()).find(t=>t.isAudioTrack())??null}async getMimeType(){return(await this._getDemuxer()).getMimeType()}};var Te=class{constructor(e){this.videoTrack=e}getFirstChunk(){return this.videoTrack._backing.getFirstChunk()}getChunk(e){return this.videoTrack._backing.getChunk(e)}getNextChunk(e){return this.videoTrack._backing.getNextChunk(e)}getKeyChunk(e){return this.videoTrack._backing.getKeyChunk(e)}getNextKeyChunk(e){return this.videoTrack._backing.getNextKeyChunk(e)}async*chunks(e,t=1/0){let i=[],{promise:s,resolve:n}=L(),{promise:o,resolve:a}=L(),c=!1,u=[],l=()=>Math.max(2,u.length);(async()=>{let f=e??await this.getFirstChunk();for(;f&&!c&&!(f.timestamp/1e6>=t);){if(i.length>l()){({promise:o,resolve:a}=L()),await o;continue}i.push(f),n(),{promise:s,resolve:n}=L(),f=await this.getNextChunk(f)}c=!0,n()})();try{for(;;)if(i.length>0){yield i.shift();let f=performance.now();for(u.push(f);u.length>0&&f-u[0]>=1e3;)u.shift();a()}else if(!c)await s;else break}finally{c=!0,a()}}},tt=class{constructor(e){this.videoTrack=e}decoderConfig=null;async createDecoder(e){this.decoderConfig||(this.decoderConfig=await this.videoTrack.getDecoderConfig());let t=new VideoDecoder({output:e,error:i=>console.error(i)});return t.configure(this.decoderConfig),t}async getKeyFrame(e){let t=null,i=await this.createDecoder(n=>t=n),s=await this.videoTrack._backing.getKeyChunk(e);return s?(i.decode(s),await i.flush(),i.close(),t):null}async getFrame(e){let t=null,i=await this.createDecoder(a=>{a.timestamp/1e6<=e?(t?.close(),t=a):a.close()}),s=await this.videoTrack._backing.getKeyChunk(e);if(!s)return null;let n=await this.videoTrack._backing.getChunk(e);d(n),i.decode(s);let o=s;for(;o!==n;){let a=await this.videoTrack._backing.getNextChunk(o);d(a),o=a,i.decode(a),i.decodeQueueSize>=10&&await new Promise(c=>i.addEventListener("dequeue",c,{once:!0}))}return await i.flush(),i.close(),t}async*frames(e=0,t=1/0){let i=[],s=!1,n=null,{promise:o,resolve:a}=L(),c=!1,u=await this.createDecoder(g=>{let x=g.timestamp/1e6;if(x>=t&&(c=!0),c){g.close();return}n&&(x>e?(i.push(n),s=!0):n.close()),x>=e&&(i.push(g),s=!0),n=s?null:g,i.length>0&&(a(),{promise:o,resolve:a}=L())}),l=await this.videoTrack._backing.getKeyChunk(e)??await this.videoTrack._backing.getFirstChunk();if(!l)return;let f=!1;(async()=>{let g=l,x=1/0;if(t<1/0){let S=await this.videoTrack._backing.getChunk(t),B=S?S.type==="key"&&S.timestamp/1e6===t?S:await this.videoTrack._backing.getNextKeyChunk(S):null;B&&(x=B.timestamp/1e6)}let k=new Te(this.videoTrack).chunks(l,x);for(await k.next();g&&!c;){u.decode(g),u.decodeQueueSize>=10&&await new Promise(B=>u.addEventListener("dequeue",B,{once:!0}));let S=await k.next();if(S.done)break;g=S.value}await k.return(),await u.flush(),u.close(),!s&&n&&i.push(n),f=!0,a()})();try{for(;;)if(i.length>0)yield i.shift();else if(!f)await o;else break}finally{c=!0}}};return cr(Ti);})(); if (typeof module === "object" && typeof module.exports === "object") Object.assign(module.exports, Metamuxer) diff --git a/dist/metamuxer.min.mjs b/dist/metamuxer.min.mjs index edaf1a2..25982c9 100644 --- a/dist/metamuxer.min.mjs +++ b/dist/metamuxer.min.mjs @@ -1,9 +1,9 @@ -function l(r){if(!r)throw new Error("Assertion failed.")}var y=r=>r&&r[r.length-1],M=r=>r>=0&&r<2**32,R=(r,e,t)=>{let i=0;for(let s=e;s>a;i<<=1,i|=c}return i},bt=(r,e,t,i)=>{for(let s=e;s>t-s-1<r instanceof ArrayBuffer?new Uint8Array(r):new Uint8Array(r.buffer,r.byteOffset,r.byteLength),v=new TextEncoder,Be=r=>Object.fromEntries(Object.entries(r).map(([e,t])=>[t,e])),z={bt709:1,bt470bg:5,smpte170m:6},kt=Be(z),B={bt709:1,smpte170m:6,"iec61966-2-1":13},gt=Be(B),U={rgb:0,bt709:1,bt470bg:5,smpte170m:6},Tt=Be(U),fe=r=>!!r&&!!r.primaries&&!!r.transfer&&!!r.matrix&&r.fullRange!==void 0,Ue=r=>r instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&r instanceof SharedArrayBuffer||ArrayBuffer.isView(r)&&!(r instanceof DataView),H=class{currentPromise=Promise.resolve();async acquire(){let e,t=new Promise(s=>{e=s}),i=this.currentPromise;return this.currentPromise=t,await i,e}},V=r=>{let e=r*(Math.PI/180),t=Math.cos(e),i=Math.sin(e);return[t,i,0,-i,t,0,0,0,1]},De=V(0),xt=r=>[...r].map(e=>e.toString(16).padStart(2,"0")).join(""),Ct=r=>(r=r>>1&1431655765|(r&1431655765)<<1,r=r>>2&858993459|(r&858993459)<<2,r=r>>4&252645135|(r&252645135)<<4,r=r>>8&16711935|(r&16711935)<<8,r=r>>16&65535|(r&65535)<<16,r>>>0),wt=(r,e,t)=>{let i=0,s=r.length-1,o=-1;for(;i<=s;){let n=i+s>>1,a=t(r[n]);a===e?(o=n,s=n-1):a{let i=-1,s=0,o=r.length-1;for(;s<=o;){let n=s+(o-s+1)/2|0;t(r[n])<=e?(i=n,s=n+1):o=n-1}return i},Fe=()=>{let r,e;return{promise:new Promise((i,s)=>{r=i,e=s}),resolve:r,reject:e}};var ee=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,Gt=/^WEBVTT(.|\n)*?\n{2}/,L=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,he=class{options;preambleText=null;preambleEmitted=!1;constructor(e){this.options=e}parse(e){e=e.replaceAll(`\r +function d(r){if(!r)throw new Error("Assertion failed.")}var v=r=>r&&r[r.length-1],z=r=>r>=0&&r<2**32,B=(r,e,t)=>{let i=0;for(let s=e;s>a;i<<=1,i|=c}return i},kt=(r,e,t,i)=>{for(let s=e;s>t-s-1<r instanceof ArrayBuffer?new Uint8Array(r):new Uint8Array(r.buffer,r.byteOffset,r.byteLength),_=new TextEncoder,Fe=r=>Object.fromEntries(Object.entries(r).map(([e,t])=>[t,e])),D={bt709:1,bt470bg:5,smpte170m:6},gt=Fe(D),F={bt709:1,smpte170m:6,"iec61966-2-1":13},Tt=Fe(F),W={rgb:0,bt709:1,bt470bg:5,smpte170m:6},xt=Fe(W),be=r=>!!r&&!!r.primaries&&!!r.transfer&&!!r.matrix&&r.fullRange!==void 0,We=r=>r instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&r instanceof SharedArrayBuffer||ArrayBuffer.isView(r)&&!(r instanceof DataView),j=class{currentPromise=Promise.resolve();async acquire(){let e,t=new Promise(s=>{e=s}),i=this.currentPromise;return this.currentPromise=t,await i,e}},M=r=>{let e=r*(Math.PI/180),t=Math.cos(e),i=Math.sin(e);return[t,i,0,-i,t,0,0,0,1]},Ne=M(0),Ct=r=>[...r].map(e=>e.toString(16).padStart(2,"0")).join(""),wt=r=>(r=r>>1&1431655765|(r&1431655765)<<1,r=r>>2&858993459|(r&858993459)<<2,r=r>>4&252645135|(r&252645135)<<4,r=r>>8&16711935|(r&16711935)<<8,r=r>>16&65535|(r&65535)<<16,r>>>0),St=(r,e,t)=>{let i=0,s=r.length-1,n=-1;for(;i<=s;){let o=i+s>>1,a=t(r[o]);a===e?(n=o,s=o-1):a{let i=-1,s=0,n=r.length-1;for(;s<=n;){let o=s+(n-s+1)/2|0;t(r[o])<=e?(i=o,s=o+1):n=o-1}return i},N=()=>{let r,e;return{promise:new Promise((i,s)=>{r=i,e=s}),resolve:r,reject:e}},yt=(r,e)=>{let t=r.indexOf(e);t!==-1&&r.splice(t,1)};var se=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,Zt=/^WEBVTT(.|\n)*?\n{2}/,K=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,ke=class{options;preambleText=null;preambleEmitted=!1;constructor(e){this.options=e}parse(e){e=e.replaceAll(`\r `,` `).replaceAll("\r",` -`),ee.lastIndex=0;let t;if(!this.preambleText){if(!Gt.test(e)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}t=ee.exec(e);let i=e.slice(0,t?.index??e.length).trimEnd();if(!i){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=i,t&&(e=e.slice(t.index),ee.lastIndex=0)}for(;t=ee.exec(e);){let i=e.slice(0,t.index),s=t[1],o=t.index+t[0].length,n=e.indexOf(` -`,o)+1,a=e.slice(o,n).trim(),c=e.indexOf(` +`),se.lastIndex=0;let t;if(!this.preambleText){if(!Zt.test(e)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}t=se.exec(e);let i=e.slice(0,t?.index??e.length).trimEnd();if(!i){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=i,t&&(e=e.slice(t.index),se.lastIndex=0)}for(;t=se.exec(e);){let i=e.slice(0,t.index),s=t[1],n=t.index+t[0].length,o=e.indexOf(` +`,n)+1,a=e.slice(n,o).trim(),c=e.indexOf(` -`,o);c===-1&&(c=e.length);let u=pe(t[2]),f=pe(t[3])-u,T=e.slice(n,c).trim();e=e.slice(c).trimStart(),ee.lastIndex=0;let C={timestamp:u/1e3,duration:f/1e3,text:T,identifier:s,settings:a,notes:i},k={};this.preambleEmitted||(k.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(C,k)}}},Yt=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,pe=r=>{let e=Yt.exec(r);if(!e)throw new Error("Expected match.");return 60*60*1e3*Number(e[1]||"0")+60*1e3*Number(e[2])+1e3*Number(e[3])+Number(e[4])},be=r=>{let e=Math.floor(r/36e5),t=Math.floor(r%(60*60*1e3)/(60*1e3)),i=Math.floor(r%(60*1e3)/1e3),s=r%1e3;return e.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+":"+i.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var te=class{constructor(e){this.writer=e}helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;writeU32(e){this.helperView.setUint32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(e){this.helperView.setUint32(0,Math.floor(e/2**32),!1),this.helperView.setUint32(4,e,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(e){for(let t=0;t[(r%256+256)%256],p=r=>(E.setUint16(0,r,!1),[h[0],h[1]]),Zt=r=>(E.setInt16(0,r,!1),[h[0],h[1]]),yt=r=>(E.setUint32(0,r,!1),[h[1],h[2],h[3]]),m=r=>(E.setUint32(0,r,!1),[h[0],h[1],h[2],h[3]]),vt=r=>(E.setInt32(0,r,!1),[h[0],h[1],h[2],h[3]]),F=r=>(E.setUint32(0,Math.floor(r/2**32),!1),E.setUint32(4,r,!1),[h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7]]),He=r=>(E.setInt16(0,2**8*r,!1),[h[0],h[1]]),A=r=>(E.setInt32(0,2**16*r,!1),[h[0],h[1],h[2],h[3]]),We=r=>(E.setInt32(0,2**30*r,!1),[h[0],h[1],h[2],h[3]]),Ne=(r,e)=>{let t=[],i=r;do{let s=i&127;i>>=7,t.length>0&&(s|=128),t.push(s),e!==void 0&&e--}while(i>0||e);return t.reverse()},S=(r,e=!1)=>{let t=Array(r.length).fill(null).map((i,s)=>r.charCodeAt(s));return e&&t.push(0),t},Le=r=>{let e=null;for(let t of r)(!e||t.timestamp>e.timestamp)&&(e=t);return e},_t=r=>[A(r[0]),A(r[1]),We(r[2]),A(r[3]),A(r[4]),We(r[5]),A(r[6]),A(r[7]),We(r[8])],b=(r,e,t)=>({type:r,contents:e&&new Uint8Array(e.flat(10)),children:t}),g=(r,e,t,i,s)=>b(r,[x(e),yt(t),i??[]],s),At=r=>r.fragmented?b("ftyp",[S("iso5"),m(512),S("iso5"),S("iso6"),S("mp41")]):b("ftyp",[S("isom"),m(512),S("isom"),r.holdsAvc?S("avc1"):[],S("mp41")]),ge=r=>({type:"mdat",largeSize:r}),Et=r=>({type:"free",size:r}),re=(r,e,t=!1)=>b("moov",void 0,[Jt(e,r),...r.map(i=>er(i,e)),t?Rr(r):null]),Jt=(r,e)=>{let t=_(Math.max(0,...e.filter(n=>n.samples.length>0).map(n=>{let a=Le(n.samples);return a.timestamp+a.duration})),ke),i=Math.max(0,...e.map(n=>n.track.id))+1,s=!M(r)||!M(t),o=s?F:m;return g("mvhd",+s,0,[o(r),o(r),m(ke),o(t),A(1),He(1),Array(10).fill(0),_t(De),Array(24).fill(0),m(i)])},er=(r,e)=>b("trak",void 0,[tr(r,e),rr(r,e)]),tr=(r,e)=>{let t=Le(r.samples),i=_(t?t.timestamp+t.duration:0,ke),s=!M(e)||!M(i),o=s?F:m,n;if(r.type==="video"){let a=r.track.metadata.rotation;n=a===void 0||typeof a=="number"?V(a??0):a}else n=De;return g("tkhd",+s,3,[o(e),o(e),m(r.track.id),m(0),o(i),Array(8).fill(0),p(0),p(r.track.id),He(r.type==="audio"?1:0),p(0),_t(n),A(r.type==="video"?r.info.width:0),A(r.type==="video"?r.info.height:0)])},rr=(r,e)=>b("mdia",void 0,[ir(r,e),nr(r),ar(r)]),ir=(r,e)=>{let t=Le(r.samples),i=_(t?t.timestamp+t.duration:0,r.timescale),s=!M(e)||!M(i),o=s?F:m;return g("mdhd",+s,0,[o(e),o(e),m(r.timescale),o(i),p(21956),p(0)])},sr={video:"vide",audio:"soun",subtitle:"text"},or={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},nr=r=>g("hdlr",0,0,[S("mhlr"),S(sr[r.type]),m(0),m(0),m(0),S(or[r.type],!0)]),ar=r=>b("minf",void 0,[lr[r.type](),mr(),pr(r)]),cr=()=>g("vmhd",0,1,[p(0),p(0),p(0),p(0)]),ur=()=>g("smhd",0,0,[p(0),p(0)]),dr=()=>g("nmhd",0,0),lr={video:cr,audio:ur,subtitle:dr},mr=()=>b("dinf",void 0,[fr()]),fr=()=>g("dref",0,0,[m(1)],[hr()]),hr=()=>g("url ",0,1),pr=r=>{let e=r.compositionTimeOffsetTable.length>1||r.compositionTimeOffsetTable.some(t=>t.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[br(r),Ar(r),Er(r),Ir(r),Or(r),Vr(r),e?Mr(r):null])},br=r=>{let e;return r.type==="video"?e=kr(Hr[r.track.source._codec],r):r.type==="audio"?e=wr($r[r.track.source._codec],r):r.type==="subtitle"&&(e=vr(jr[r.track.source._codec],r)),l(e),g("stsd",0,0,[m(1)],[e])},kr=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),Array(12).fill(0),p(e.info.width),p(e.info.height),m(4718592),m(4718592),m(0),p(1),Array(32).fill(0),p(24),Zt(65535)],[Lr[e.track.source._codec](e),fe(e.info.decoderConfig.colorSpace)?gr(e):null]),gr=r=>b("colr",[S("nclx"),p(z[r.info.decoderConfig.colorSpace.primaries]),p(B[r.info.decoderConfig.colorSpace.transfer]),p(U[r.info.decoderConfig.colorSpace.matrix]),x((r.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),Tr=r=>r.info.decoderConfig&&b("avcC",[...P(r.info.decoderConfig.description)]),xr=r=>r.info.decoderConfig&&b("hvcC",[...P(r.info.decoderConfig.description)]),St=r=>{if(!r.info.decoderConfig)return null;let e=r.info.decoderConfig;l(e.colorSpace);let t=e.codec.split("."),i=Number(t[1]),s=Number(t[2]),a=(Number(t[3])<<4)+(0<<1)+Number(e.colorSpace.fullRange);return g("vpcC",1,0,[x(i),x(s),x(a),x(2),x(2),x(2),p(0)])},Cr=()=>b("av1C",[129,0,0,0]),wr=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),m(0),p(e.info.numberOfChannels),p(16),p(0),p(0),A(e.info.sampleRate)],[Qr[e.track.source._codec](e)]),Sr=r=>{let t=[...P(r.info.decoderConfig.description??new ArrayBuffer(0))];return t=[...x(64),...x(21),...yt(0),...m(0),...m(0),...x(5),...Ne(t.length),...t],t=[...p(1),...x(0),...x(4),...Ne(t.length),...t,...x(6),...x(1),...x(2)],t=[...x(3),...Ne(t.length),...t],g("esds",0,0,t)},yr=r=>{let e=3840,t=0,i=r.info.decoderConfig?.description;if(i){l(i.byteLength>=18);let s=ArrayBuffer.isView(i)?new DataView(i.buffer,i.byteOffset,i.byteLength):new DataView(i);e=s.getUint16(10,!0),t=s.getInt16(14,!0)}return b("dOps",[x(0),x(r.info.numberOfChannels),p(e),m(r.info.sampleRate),He(t),x(0)])},vr=(r,e)=>b(r,[Array(6).fill(0),p(1)],[Kr[e.track.source._codec](e)]),_r=r=>b("vttC",[...v.encode(r.info.config.description)]);var Ar=r=>g("stts",0,0,[m(r.timeToSampleTable.length),r.timeToSampleTable.map(e=>[m(e.sampleCount),m(e.sampleDelta)])]),Er=r=>{if(r.samples.every(t=>t.type==="key"))return null;let e=[...r.samples.entries()].filter(([,t])=>t.type==="key");return g("stss",0,0,[m(e.length),e.map(([t])=>m(t+1))])},Ir=r=>g("stsc",0,0,[m(r.compactlyCodedChunkTable.length),r.compactlyCodedChunkTable.map(e=>[m(e.firstChunk),m(e.samplesPerChunk),m(1)])]),Or=r=>g("stsz",0,0,[m(0),m(r.samples.length),r.samples.map(e=>m(e.size))]),Vr=r=>r.finalizedChunks.length>0&&y(r.finalizedChunks).offset>=2**32?g("co64",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>F(e.offset))]):g("stco",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>m(e.offset))]),Mr=r=>g("ctts",0,0,[m(r.compositionTimeOffsetTable.length),r.compositionTimeOffsetTable.map(e=>[m(e.sampleCount),m(e.sampleCompositionTimeOffset)])]),Rr=r=>b("mvex",void 0,r.map(Pr)),Pr=r=>g("trex",0,0,[m(r.track.id),m(1),m(0),m(0),m(0)]),$e=(r,e)=>b("moof",void 0,[zr(r),...e.map(Br)]),zr=r=>g("mfhd",0,0,[m(r)]),It=r=>{let e=0,t=0,i=0,s=0,o=r.type==="delta";return t|=+o,o?e|=1:e|=2,e<<24|t<<16|i<<8|s},Br=r=>b("traf",void 0,[Ur(r),Dr(r),Fr(r)]),Ur=r=>{l(r.currentChunk);let e=0;e|=8,e|=16,e|=32,e|=131072;let t=r.currentChunk.samples[1]??r.currentChunk.samples[0],i={duration:t.timescaleUnitsToNextSample,size:t.size,flags:It(t)};return g("tfhd",0,e,[m(r.track.id),m(i.duration),m(i.size),m(i.flags)])},Dr=r=>(l(r.currentChunk),g("tfdt",1,0,[F(_(r.currentChunk.startTimestamp,r.timescale))])),Fr=r=>{l(r.currentChunk);let e=r.currentChunk.samples.map(w=>w.timescaleUnitsToNextSample),t=r.currentChunk.samples.map(w=>w.size),i=r.currentChunk.samples.map(It),s=r.currentChunk.samples.map(w=>_(w.timestamp-w.decodeTimestamp,r.timescale)),o=new Set(e),n=new Set(t),a=new Set(i),c=new Set(s),u=a.size===2&&i[0]!==i[1],d=o.size>1,f=n.size>1,T=!u&&a.size>1,C=c.size>1||[...c].some(w=>w!==0),k=0;return k|=1,k|=4*+u,k|=256*+d,k|=512*+f,k|=1024*+T,k|=2048*+C,g("trun",1,k,[m(r.currentChunk.samples.length),m(r.currentChunk.offset-r.currentChunk.moofOffset||0),u?m(i[0]):[],r.currentChunk.samples.map((w,me)=>[d?m(e[me]):[],f?m(t[me]):[],T?m(i[me]):[],C?vt(s[me]):[]])])},Ot=r=>b("mfra",void 0,[...r.map(Wr),Nr()]),Wr=(r,e)=>g("tfra",1,0,[m(r.track.id),m(63),m(r.finalizedChunks.length),r.finalizedChunks.map(i=>[F(_(i.startTimestamp,r.timescale)),F(i.moofOffset),m(e+1),m(1),m(1)])]),Nr=()=>g("mfro",0,0,[m(0)]),Vt=()=>b("vtte"),Mt=(r,e,t,i,s)=>b("vttc",void 0,[s!==null?b("vsid",[vt(s)]):null,t!==null?b("iden",[...v.encode(t)]):null,e!==null?b("ctim",[...v.encode(be(e))]):null,i!==null?b("sttg",[...v.encode(i)]):null,b("payl",[...v.encode(r)])]),Rt=r=>b("vtta",[...v.encode(r)]),Hr={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},Lr={avc:Tr,hevc:xr,vp8:St,vp9:St,av1:Cr},$r={aac:"mp4a",opus:"Opus"},Qr={aac:Sr,opus:yr},jr={webvtt:"wvtt"},Kr={webvtt:_r};var $=class{output;mutex=new H;constructor(e){this.output=e}beforeTrackAdd(e){}onTrackClose(e){}trackTimestampInfo=new WeakMap;validateAndNormalizeTimestamp(e,t,i){let s=t/1e6,o=this.trackTimestampInfo.get(e);if(!o){if(!i)throw new Error("First frame must be a key frame.");if(this.timestampsMustStartAtZero&&s>0)throw new Error(`Timestamps must start at zero (got ${s}s).`);o={timestampOffset:s,maxTimestamp:e.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:e.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(e,o)}if(e.source._offsetTimestamps&&(s-=o.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(si.start-s.start);e.push({start:t[0].start,size:t[0].data.byteLength});for(let i=1;ic.start<=t&&tXr){for(let c=0;c=e.written[o+1].start;)e.written[o].end=Math.max(e.written[o].end,e.written[o+1].end),e.written.splice(o+1,1)}createChunk(e){let i={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(i),this.chunks.sort((s,o)=>s.start-o.start),this.chunks.indexOf(i)}queueChunksForFlush(e=!1){l(this.writer);for(let t=0;t{if(r==="avc"){let o=Math.ceil(e/16)*Math.ceil(t/16),n=Pt.find(f=>o<=f.maxMacroblocks&&i<=f.maxBitrate)??y(Pt),a=n?n.level:0,c="64".padStart(2,"0"),u="00",d=a.toString(16).padStart(2,"0");return`avc1.${c}${u}${d}`}else if(r==="hevc"){let s="",n="6",a=e*t,c=zt.find(d=>a<=d.maxPictureSize&&i<=d.maxBitrate)??y(zt);return`hev1.${s}1.${n}.${c.tier}${c.level}.B0`}else{if(r==="vp8")return"vp8";if(r==="vp9"){let s="00",o=e*t,n=Bt.find(c=>o<=c.maxPictureSize&&i<=c.maxBitrate)??y(Bt);return`vp09.${s}.${n.level}.08`}else if(r==="av1"){let o=e*t,n=Ut.find(c=>o<=c.maxPictureSize&&i<=c.maxBitrate)??y(Ut);return`av01.0.${n.level.toString().padStart(2,"0")}${n.tier}.08`}}throw new TypeError(`Unhandled codec '${r}'.`)},Ft=(r,e)=>{if(r==="avc"){if(!e||e.byteLength<4)throw new TypeError("AVC description must be at least 4 bytes long.");return`avc1.${xt(e.subarray(1,4))}`}else if(r==="hevc"){if(!e)throw new TypeError("HEVC description must be provided.");let t=new DataView(e.buffer,e.byteOffset,e.byteLength),i="hev1.",s=e[1]>>6&3,o=e[1]&31;i+=["","A","B","C"][s]+o,i+=".";let n=Ct(t.getUint32(2));i+=n.toString(16),i+=".";let a=e[1]>>5&1,c=e[12];i+=a===0?"L":"H",i+=c,i+=".";let u=[];for(let d=0;d<6;d++){let f=e[d+13];u.push(f)}for(;u[u.length-1]===0;)u.pop();return i+=u.map(d=>d.toString(16)).join("."),i}throw new TypeError(`Unhandled codec '${r}'.`)},Wt=(r,e,t)=>{if(r==="aac")return e>=2&&t<=24e3?"mp4a.40.29":t<=24e3?"mp4a.40.5":"mp4a.40.2";if(r==="opus")return"opus";if(r==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${r}'.`)},Nt=(r,e)=>{if(r==="aac"){if(!e||e.byteLength<2)throw new TypeError("AAC description must be at least 2 bytes long.");return`mp4a.40.${e[0]>>3}`}else{if(r==="opus")return"opus";if(r==="vorbis")return"vorbis"}throw new TypeError(`Unhandled codec '${r}'.`)},Ht=r=>r==="avc"?{avc:{format:"avc"}}:r==="hevc"?{hevc:{format:"hevc"}}:{},Lt=r=>r==="aac"?{aac:{format:"aac"}}:r==="opus"?{opus:{format:"opus"}}:{},we=r=>{if(!r)throw new TypeError("Video chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Video chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Video chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Video chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.codedWidth)||r.decoderConfig.codedWidth<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");if(!Number.isInteger(r.decoderConfig.codedHeight)||r.decoderConfig.codedHeight<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");if(r.decoderConfig.description!==void 0&&!Ue(r.decoderConfig.description))throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.colorSpace!==void 0){let{colorSpace:e}=r.decoderConfig;if(typeof e!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let t=Object.keys(z);if(e.primaries!=null&&!t.includes(e.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${t.join(", ")}.`);let i=Object.keys(B);if(e.transfer!=null&&!i.includes(e.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${i.join(", ")}.`);let s=Object.keys(U);if(e.matrix!=null&&!s.includes(e.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(e.fullRange!=null&&typeof e.fullRange!="boolean")throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.")}if((r.decoderConfig.codec.startsWith("avc1")||r.decoderConfig.codec.startsWith("avc3"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for AVC must include a description, which is expected to be an AVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec.startsWith("hev1")||r.decoderConfig.codec.startsWith("hvc1"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for HEVC must include a description, which is expected to be an HEVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec==="vp8"||r.decoderConfig.codec.startsWith("vp09"))&&r.decoderConfig.colorSpace===void 0)throw new TypeError("Video chunk metadata decoder configuration for VP8/VP9 must include a colorSpace.")},Se=r=>{if(!r)throw new TypeError("Audio chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Audio chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Audio chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Audio chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.sampleRate)||r.decoderConfig.sampleRate<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");if(!Number.isInteger(r.decoderConfig.numberOfChannels)||r.decoderConfig.numberOfChannels<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");if(r.decoderConfig.description!==void 0&&!Ue(r.decoderConfig.description))throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.codec.startsWith("mp4a")&&!r.decoderConfig.description)throw new TypeError("Audio chunk metadata decoder configuration for AAC must include a description, which is expected to be an AudioSpecificConfig as specified in ISO 14496-3.");if(r.decoderConfig.codec==="opus"&&r.decoderConfig.description&&r.decoderConfig.description.byteLength<18)throw new TypeError("Invalid decoder description provided for Opus; must be at least 18 bytes long.")},ye=r=>{if(!r)throw new TypeError("Subtitle metadata must be provided.");if(typeof r!="object")throw new TypeError("Subtitle metadata must be an object.");if(!r.config)throw new TypeError("Subtitle metadata must include a config object.");if(typeof r.config!="object")throw new TypeError("Subtitle metadata config must be an object.");if(typeof r.config.description!="string")throw new TypeError("Subtitle metadata config description must be a string.")};var ke=1e3,Gr=2082844800,_=(r,e,t=!0)=>{let i=r*e;return t?Math.round(i):i},ve=class extends ${timestampsMustStartAtZero=!0;writer;boxWriter;fastStart;auxTarget=new se;auxWriter=this.auxTarget._createWriter();auxBoxWriter=new te(this.auxWriter);ftypSize=null;mdat=null;trackDatas=[];creationTime=Math.floor(Date.now()/1e3)+Gr;finalizedChunks=[];nextFragmentNumber=1;constructor(e,t){super(e),this.writer=e._writer,this.boxWriter=new te(this.writer);let i=this.writer instanceof Q?"in-memory":!1;this.fastStart=t._options.fastStart??i,(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),t=this.output._tracks.some(i=>i.type==="video"&&i.source._codec==="avc");this.boxWriter.writeBox(At({holdsAvc:t,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=ge(!1):this.fastStart==="fragmented"||(this.mdat=ge(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;we(t),l(t),l(t.decoderConfig),l(t.decoderConfig.codedWidth!==void 0),l(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},timescale:e.metadata.frameRate??57600,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;Se(t),l(t),l(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},timescale:t.decoderConfig.sampleRate,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;ye(t),l(t),l(t.config);let s={track:e,type:"subtitle",info:{config:t.config},timescale:1e3,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[],lastCueEndTimestamp:0,cueQueue:[],nextSourceId:0,cueToSourceId:new WeakMap};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),this.validateAndNormalizeTimestamp(e,0,!0),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=this.validateAndNormalizeTimestamp(o.track,t.timestamp,t.type==="key"),c=this.createSampleForTrack(o,n,a,(t.duration??0)/1e6,t.type);await this.registerSample(o,c)}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=t.type,c=this.validateAndNormalizeTimestamp(o.track,t.timestamp,a==="key"),u=this.createSampleForTrack(o,n,c,(t.duration??0)/1e6,a);await this.registerSample(o,u)}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,i);this.validateAndNormalizeTimestamp(o.track,1e6*t.timestamp,!0),e.source._codec==="webvtt"&&(o.cueQueue.push(t),await this.processWebVTTCues(o,t.timestamp))}finally{s()}}async processWebVTTCues(e,t){for(;e.cueQueue.length>0;){let i=new Set([]);for(let u of e.cueQueue)l(u.timestamp<=t),l(e.lastCueEndTimestamp<=u.timestamp+u.duration),i.add(Math.max(u.timestamp,e.lastCueEndTimestamp)),i.add(u.timestamp+u.duration);let s=[...i].sort((u,d)=>u-d),o=s[0],n=s[1]??o;if(t=n)break;L.lastIndex=0;let f=L.test(d.text),T=d.timestamp+d.duration,C=e.cueToSourceId.get(d);if(C===void 0&&ni.timestamp).sort((i,s)=>i-s);for(let i=0;i{if(e===n)return t.type==="key";let a=n.sampleQueue[0];return a&&a.type==="key"});s>=1&&o&&(i=!0,await this.finalizeFragment())}else i=s>=.5}i&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:t.timestamp,samples:[],offset:null,moofOffset:null}),l(e.currentChunk),e.currentChunk.samples.push(t),e.timestampProcessingQueue.push(t)}async finalizeCurrentChunk(e){if(l(this.fastStart!=="fragmented"),!!e.currentChunk){if(e.finalizedChunks.push(e.currentChunk),this.finalizedChunks.push(e.currentChunk),(e.compactlyCodedChunkTable.length===0||y(e.compactlyCodedChunkTable).samplesPerChunk!==e.currentChunk.samples.length)&&e.compactlyCodedChunkTable.push({firstChunk:e.finalizedChunks.length,samplesPerChunk:e.currentChunk.samples.length}),this.fastStart==="in-memory"){e.currentChunk.offset=0;return}e.currentChunk.offset=this.writer.getPos();for(let t of e.currentChunk.samples)l(t.data),this.writer.write(t.data),t.data=null;await this.writer.flush()}}async interleaveSamples(){l(this.fastStart==="fragmented");for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.sampleQueue.length===0&&!s.track.source._closed)break e;s.sampleQueue.length>0&&s.sampleQueue[0].timestamp=2**32&&(a.largeSize=!0,u=this.boxWriter.measureBox(a)+c),a.size=u,this.boxWriter.writeBox(a)}for(let a of this.trackDatas){a.currentChunk.offset=this.writer.getPos(),a.currentChunk.moofOffset=i;for(let c of a.currentChunk.samples)this.writer.write(c.data),c.data=null}let o=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(s));let n=$e(t,this.trackDatas);this.boxWriter.writeBox(n),this.writer.seek(o);for(let a of this.trackDatas)a.finalizedChunks.push(a.currentChunk),this.finalizedChunks.push(a.currentChunk),a.currentChunk=null;e&&await this.writer.flush()}async onTrackClose(e){let t=await this.mutex.acquire();if(e.type==="subtitle"&&e.source._codec==="webvtt"){let i=this.trackDatas.find(s=>s.track===e);i&&await this.processWebVTTCues(i,1/0)}this.fastStart==="fragmented"&&await this.interleaveSamples(),t()}async finalize(){let e=await this.mutex.acquire();for(let t of this.trackDatas)t.type==="subtitle"&&t.track.source._codec==="webvtt"&&await this.processWebVTTCues(t,1/0);if(this.fastStart==="fragmented"){for(let t of this.trackDatas){for(let i of t.sampleQueue)await this.addSampleToTrack(t,i);this.processTimestamps(t)}await this.finalizeFragment(!1)}else for(let t of this.trackDatas)this.processTimestamps(t),await this.finalizeCurrentChunk(t);if(this.fastStart==="in-memory"){l(this.mdat);let t;for(let s=0;s<2;s++){let o=re(this.trackDatas,this.creationTime),n=this.boxWriter.measureBox(o);t=this.boxWriter.measureBox(this.mdat);let a=this.writer.getPos()+n+t;for(let c of this.finalizedChunks){c.offset=a;for(let{data:u}of c.samples)l(u),a+=u.byteLength,t+=u.byteLength}if(a<2**32)break;t>=2**32&&(this.mdat.largeSize=!0)}let i=re(this.trackDatas,this.creationTime);this.boxWriter.writeBox(i),this.mdat.size=t,this.boxWriter.writeBox(this.mdat);for(let s of this.finalizedChunks)for(let o of s.samples)l(o.data),this.writer.write(o.data),o.data=null}else if(this.fastStart==="fragmented"){let t=this.writer.getPos(),i=Ot(this.trackDatas);this.boxWriter.writeBox(i);let s=this.writer.getPos()-t;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(s)}else{l(this.mdat),l(this.ftypSize!==null);let t=this.boxWriter.offsets.get(this.mdat);l(t!==void 0);let i=this.writer.getPos()-t;this.mdat.size=i,this.mdat.largeSize=i>=2**32,this.boxWriter.patchBox(this.mdat);let s=re(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(s);let o=t-this.writer.getPos();this.boxWriter.writeBox(Et(o))}else this.boxWriter.writeBox(s)}e()}};var oe=class{value;constructor(e){this.value=e}},q=class{value;constructor(e){this.value=e}},ne=class{value;constructor(e){this.value=e}};var je=r=>r<256?1:r<65536?2:r<1<<24?3:r<2**32?4:r<2**40?5:6,Ke=r=>r>=-64&&r<64?1:r>=-8192&&r<8192?2:r>=-(1<<20)&&r<1<<20?3:r>=-(1<<27)&&r<1<<27?4:r>=-(2**34)&&r<2**34?5:6,$t=r=>{if(r<127)return 1;if(r<16383)return 2;if(r<(1<<21)-1)return 3;if(r<(1<<28)-1)return 4;if(r<2**35-1)return 5;if(r<2**42-1)return 6;throw new Error("EBML VINT size not supported "+r)};var qe=2**15,Qt="https://github.com/Vanilagy/webm-muxer",jt=6,Kt=5,Yr={avc:"V_MPEG4/ISO/AVC",hevc:"V_MPEGH/ISO/HEVC",vp8:"V_VP8",vp9:"V_VP9",av1:"V_AV1",aac:"A_AAC",opus:"A_OPUS",webvtt:"S_TEXT/WEBVTT"},Zr={video:1,audio:2,subtitle:17},_e=class extends ${timestampsMustStartAtZero=!1;writer;format;helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;dataOffsets=new WeakMap;trackDatas=[];segment=null;segmentInfo=null;seekHead=null;tracksElement=null;segmentDuration=null;cues=null;currentCluster=null;currentClusterMsTimestamp=null;trackDatasInCurrentCluster=new Set;duration=0;constructor(e,t){super(e),this.writer=e._writer,this.format=t,this.format._options.streamable&&(this.writer.ensureMonotonicity=!0)}writeByte(e){this.helperView.setUint8(0,e),this.writer.write(this.helper.subarray(0,1))}writeFloat32(e){this.helperView.setFloat32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeFloat64(e){this.helperView.setFloat64(0,e,!1),this.writer.write(this.helper)}writeUnsignedInt(e,t=je(e)){let i=0;switch(t){case 6:this.helperView.setUint8(i++,e/2**40|0);case 5:this.helperView.setUint8(i++,e/2**32|0);case 4:this.helperView.setUint8(i++,e>>24);case 3:this.helperView.setUint8(i++,e>>16);case 2:this.helperView.setUint8(i++,e>>8);case 1:this.helperView.setUint8(i++,e);break;default:throw new Error("Bad UINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeSignedInt(e,t=Ke(e)){e<0&&(e+=2**(t*8)),this.writeUnsignedInt(e,t)}writeEBMLVarInt(e,t=$t(e)){let i=0;switch(t){case 1:this.helperView.setUint8(i++,128|e);break;case 2:this.helperView.setUint8(i++,64|e>>8),this.helperView.setUint8(i++,e);break;case 3:this.helperView.setUint8(i++,32|e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 4:this.helperView.setUint8(i++,16|e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 5:this.helperView.setUint8(i++,8|e/2**32&7),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 6:this.helperView.setUint8(i++,4|e/2**40&3),this.helperView.setUint8(i++,e/2**32|0),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;default:throw new Error("Bad EBML VINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeString(e){this.writer.write(new Uint8Array(e.split("").map(t=>t.charCodeAt(0))))}writeEBML(e){if(e!==null){if(e instanceof Uint8Array)this.writer.write(e);else if(Array.isArray(e))for(let t of e)this.writeEBML(t);else if(this.offsets.set(e,this.writer.getPos()),this.writeUnsignedInt(e.id),Array.isArray(e.data)){let t=this.writer.getPos(),i=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+i);let s=this.writer.getPos();if(this.dataOffsets.set(e,s),this.writeEBML(e.data),e.size!==-1){let o=this.writer.getPos()-s,n=this.writer.getPos();this.writer.seek(t),this.writeEBMLVarInt(o,i),this.writer.seek(n)}}else if(typeof e.data=="number"){let t=e.size??je(e.data);this.writeEBMLVarInt(t),this.writeUnsignedInt(e.data,t)}else if(typeof e.data=="string")this.writeEBMLVarInt(e.data.length),this.writeString(e.data);else if(e.data instanceof Uint8Array)this.writeEBMLVarInt(e.data.byteLength,e.size),this.writer.write(e.data);else if(e.data instanceof oe)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof q)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof ne){let t=e.size??Ke(e.data.value);this.writeEBMLVarInt(t),this.writeSignedInt(e.data.value,t)}}}beforeTrackAdd(e){if(this.format instanceof X)if(e.type==="video"){if(!["vp8","vp9","av1"].includes(e.source._codec))throw new Error("WebM only supports VP8, VP9 and AV1 as video codecs. Switching to MKV removes this restriction.")}else if(e.type==="audio"){if(!["opus","vorbis"].includes(e.source._codec))throw new Error("WebM only supports Opus and Vorbis as audio codecs. Switching to MKV removes this restriction.")}else if(e.type==="subtitle"){if(e.source._codec!=="webvtt")throw new Error("WebM only supports WebVTT as subtitle codec. Switching to MKV removes this restriction.")}else throw new Error("WebM only supports video, audio and subtitle tracks. Switching to MKV removes this restriction.")}async start(){let e=await this.mutex.acquire();this.writeEBMLHeader(),this.format._options.streamable||this.createSeekHead(),this.createSegmentInfo(),this.createCues(),await this.writer.flush(),e()}writeEBMLHeader(){let e={id:440786851,data:[{id:17030,data:1},{id:17143,data:1},{id:17138,data:4},{id:17139,data:8},{id:17026,data:this.format instanceof X?"webm":"matroska"},{id:17031,data:2},{id:17029,data:2}]};this.writeEBML(e)}createSeekHead(){let e=new Uint8Array([28,83,187,107]),t=new Uint8Array([21,73,169,102]),i=new Uint8Array([22,84,174,107]),s={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:t},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:i},{id:21420,size:5,data:0}]}]};this.seekHead=s}createSegmentInfo(){let e={id:17545,data:new q(0)};this.segmentDuration=e;let t={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:Qt},{id:22337,data:Qt},this.format._options.streamable?null:e]};this.segmentInfo=t}createTracks(){let e={id:374648427,data:[]};this.tracksElement=e;for(let t of this.trackDatas)e.data.push({id:174,data:[{id:215,data:t.track.id},{id:29637,data:t.track.id},{id:131,data:Zr[t.type]},{id:134,data:Yr[t.track.source._codec]},t.type==="video"?this.videoSpecificTrackInfo(t):null,t.type==="audio"?this.audioSpecificTrackInfo(t):null,t.type==="subtitle"?this.subtitleSpecificTrackInfo(t):null]})}videoSpecificTrackInfo(e){let t=[e.info.decoderConfig.description?{id:25506,data:P(e.info.decoderConfig.description)}:null,e.track.metadata.frameRate?{id:2352003,data:1e9/e.track.metadata.frameRate}:null],i=e.info.decoderConfig.colorSpace,s={id:224,data:[{id:176,data:e.info.width},{id:186,data:e.info.height},fe(i)?{id:21936,data:[{id:21937,data:U[i.matrix]},{id:21946,data:B[i.transfer]},{id:21947,data:z[i.primaries]},{id:21945,data:i.fullRange?2:1}]}:null]};return t.push(s),t}audioSpecificTrackInfo(e){return[e.info.decoderConfig.description?{id:25506,data:P(e.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new oe(e.info.sampleRate)},{id:159,data:e.info.numberOfChannels}]}]}subtitleSpecificTrackInfo(e){return[{id:25506,data:v.encode(e.info.config.description)}]}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:jt,data:[this.format._options.streamable?null:this.seekHead,this.segmentInfo,this.tracksElement]};this.segment=e,this.writeEBML(e)}createCues(){this.cues={id:475249515,data:[]}}get segmentDataOffset(){return l(this.segment),this.dataOffsets.get(this.segment)}getVideoTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;we(t),l(t),l(t.decoderConfig),l(t.decoderConfig.codedWidth!==void 0),l(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;Se(t),l(t),l(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(o=>o.track===e);if(i)return i;ye(t),l(t),l(t.config);let s={track:e,type:"subtitle",info:{config:t.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=t.type==="key",c=this.validateAndNormalizeTimestamp(o.track,t.timestamp,a),u=this.createInternalChunk(n,c,(t.duration??0)/1e6,t.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(o,u),o.chunkQueue.push(u),await this.interleaveChunks()}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,i),n=new Uint8Array(t.byteLength);t.copyTo(n);let a=t.type,c=a==="key",u=this.validateAndNormalizeTimestamp(o.track,t.timestamp,c),d=this.createInternalChunk(n,u,(t.duration??0)/1e6,a);o.chunkQueue.push(d),await this.interleaveChunks()}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,i),n=this.validateAndNormalizeTimestamp(o.track,1e6*t.timestamp,!0),a=t.text,c=Math.floor(n*1e3);L.lastIndex=0,a=a.replace(L,T=>{let k=pe(T.slice(1,-1))-c;return`<${be(k)}>`});let u=v.encode(a),d=`${t.settings??""} +`,n);c===-1&&(c=e.length);let u=ge(t[2]),f=ge(t[3])-u,g=e.slice(o,c).trim();e=e.slice(c).trimStart(),se.lastIndex=0;let x={timestamp:u/1e3,duration:f/1e3,text:g,identifier:s,settings:a,notes:i},C={};this.preambleEmitted||(C.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(x,C)}}},Jt=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,ge=r=>{let e=Jt.exec(r);if(!e)throw new Error("Expected match.");return 60*60*1e3*Number(e[1]||"0")+60*1e3*Number(e[2])+1e3*Number(e[3])+Number(e[4])},Te=r=>{let e=Math.floor(r/36e5),t=Math.floor(r%(60*60*1e3)/(60*1e3)),i=Math.floor(r%(60*1e3)/1e3),s=r%1e3;return e.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+":"+i.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var ne=class{constructor(e){this.writer=e}helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;writeU32(e){this.helperView.setUint32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(e){this.helperView.setUint32(0,Math.floor(e/2**32),!1),this.helperView.setUint32(4,e,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(e){for(let t=0;t[(r%256+256)%256],p=r=>(O.setUint16(0,r,!1),[h[0],h[1]]),er=r=>(O.setInt16(0,r,!1),[h[0],h[1]]),_t=r=>(O.setUint32(0,r,!1),[h[1],h[2],h[3]]),m=r=>(O.setUint32(0,r,!1),[h[0],h[1],h[2],h[3]]),At=r=>(O.setInt32(0,r,!1),[h[0],h[1],h[2],h[3]]),H=r=>(O.setUint32(0,Math.floor(r/2**32),!1),O.setUint32(4,r,!1),[h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7]]),Qe=r=>(O.setInt16(0,2**8*r,!1),[h[0],h[1]]),I=r=>(O.setInt32(0,2**16*r,!1),[h[0],h[1],h[2],h[3]]),He=r=>(O.setInt32(0,2**30*r,!1),[h[0],h[1],h[2],h[3]]),Le=(r,e)=>{let t=[],i=r;do{let s=i&127;i>>=7,t.length>0&&(s|=128),t.push(s),e!==void 0&&e--}while(i>0||e);return t.reverse()},y=(r,e=!1)=>{let t=Array(r.length).fill(null).map((i,s)=>r.charCodeAt(s));return e&&t.push(0),t},$e=r=>{let e=null;for(let t of r)(!e||t.timestamp>e.timestamp)&&(e=t);return e},Et=r=>[I(r[0]),I(r[1]),He(r[2]),I(r[3]),I(r[4]),He(r[5]),I(r[6]),I(r[7]),He(r[8])],b=(r,e,t)=>({type:r,contents:e&&new Uint8Array(e.flat(10)),children:t}),T=(r,e,t,i,s)=>b(r,[w(e),_t(t),i??[]],s),It=r=>r.fragmented?b("ftyp",[y("iso5"),m(512),y("iso5"),y("iso6"),y("mp41")]):b("ftyp",[y("isom"),m(512),y("isom"),r.holdsAvc?y("avc1"):[],y("mp41")]),Ce=r=>({type:"mdat",largeSize:r}),Ot=r=>({type:"free",size:r}),oe=(r,e,t=!1)=>b("moov",void 0,[tr(e,r),...r.map(i=>rr(i,e)),t?zr(r):null]),tr=(r,e)=>{let t=A(Math.max(0,...e.filter(o=>o.samples.length>0).map(o=>{let a=$e(o.samples);return a.timestamp+a.duration})),xe),i=Math.max(0,...e.map(o=>o.track.id))+1,s=!z(r)||!z(t),n=s?H:m;return T("mvhd",+s,0,[n(r),n(r),m(xe),n(t),I(1),Qe(1),Array(10).fill(0),Et(Ne),Array(24).fill(0),m(i)])},rr=(r,e)=>b("trak",void 0,[ir(r,e),sr(r,e)]),ir=(r,e)=>{let t=$e(r.samples),i=A(t?t.timestamp+t.duration:0,xe),s=!z(e)||!z(i),n=s?H:m,o;if(r.type==="video"){let a=r.track.metadata.rotation;o=a===void 0||typeof a=="number"?M(a??0):a}else o=Ne;return T("tkhd",+s,3,[n(e),n(e),m(r.track.id),m(0),n(i),Array(8).fill(0),p(0),p(r.track.id),Qe(r.type==="audio"?1:0),p(0),Et(o),I(r.type==="video"?r.info.width:0),I(r.type==="video"?r.info.height:0)])},sr=(r,e)=>b("mdia",void 0,[nr(r,e),cr(r),ur(r)]),nr=(r,e)=>{let t=$e(r.samples),i=A(t?t.timestamp+t.duration:0,r.timescale),s=!z(e)||!z(i),n=s?H:m;return T("mdhd",+s,0,[n(e),n(e),m(r.timescale),n(i),p(21956),p(0)])},or={video:"vide",audio:"soun",subtitle:"text"},ar={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},cr=r=>T("hdlr",0,0,[y("mhlr"),y(or[r.type]),m(0),m(0),m(0),y(ar[r.type],!0)]),ur=r=>b("minf",void 0,[fr[r.type](),hr(),kr(r)]),dr=()=>T("vmhd",0,1,[p(0),p(0),p(0),p(0)]),lr=()=>T("smhd",0,0,[p(0),p(0)]),mr=()=>T("nmhd",0,0),fr={video:dr,audio:lr,subtitle:mr},hr=()=>b("dinf",void 0,[pr()]),pr=()=>T("dref",0,0,[m(1)],[br()]),br=()=>T("url ",0,1),kr=r=>{let e=r.compositionTimeOffsetTable.length>1||r.compositionTimeOffsetTable.some(t=>t.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[gr(r),Ir(r),Or(r),Vr(r),Rr(r),Mr(r),e?Pr(r):null])},gr=r=>{let e;return r.type==="video"?e=Tr(Qr[r.track.source._codec],r):r.type==="audio"?e=yr(jr[r.track.source._codec],r):r.type==="subtitle"&&(e=Ar(qr[r.track.source._codec],r)),d(e),T("stsd",0,0,[m(1)],[e])},Tr=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),Array(12).fill(0),p(e.info.width),p(e.info.height),m(4718592),m(4718592),m(0),p(1),Array(32).fill(0),p(24),er(65535)],[$r[e.track.source._codec](e),be(e.info.decoderConfig.colorSpace)?xr(e):null]),xr=r=>b("colr",[y("nclx"),p(D[r.info.decoderConfig.colorSpace.primaries]),p(F[r.info.decoderConfig.colorSpace.transfer]),p(W[r.info.decoderConfig.colorSpace.matrix]),w((r.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),Cr=r=>r.info.decoderConfig&&b("avcC",[...U(r.info.decoderConfig.description)]),wr=r=>r.info.decoderConfig&&b("hvcC",[...U(r.info.decoderConfig.description)]),vt=r=>{if(!r.info.decoderConfig)return null;let e=r.info.decoderConfig;d(e.colorSpace);let t=e.codec.split("."),i=Number(t[1]),s=Number(t[2]),a=(Number(t[3])<<4)+(0<<1)+Number(e.colorSpace.fullRange);return T("vpcC",1,0,[w(i),w(s),w(a),w(2),w(2),w(2),p(0)])},Sr=()=>b("av1C",[129,0,0,0]),yr=(r,e)=>b(r,[Array(6).fill(0),p(1),p(0),p(0),m(0),p(e.info.numberOfChannels),p(16),p(0),p(0),I(e.info.sampleRate)],[Kr[e.track.source._codec](e)]),vr=r=>{let t=[...U(r.info.decoderConfig.description??new ArrayBuffer(0))];return t=[...w(64),...w(21),..._t(0),...m(0),...m(0),...w(5),...Le(t.length),...t],t=[...p(1),...w(0),...w(4),...Le(t.length),...t,...w(6),...w(1),...w(2)],t=[...w(3),...Le(t.length),...t],T("esds",0,0,t)},_r=r=>{let e=3840,t=0,i=r.info.decoderConfig?.description;if(i){d(i.byteLength>=18);let s=ArrayBuffer.isView(i)?new DataView(i.buffer,i.byteOffset,i.byteLength):new DataView(i);e=s.getUint16(10,!0),t=s.getInt16(14,!0)}return b("dOps",[w(0),w(r.info.numberOfChannels),p(e),m(r.info.sampleRate),Qe(t),w(0)])},Ar=(r,e)=>b(r,[Array(6).fill(0),p(1)],[Xr[e.track.source._codec](e)]),Er=r=>b("vttC",[..._.encode(r.info.config.description)]);var Ir=r=>T("stts",0,0,[m(r.timeToSampleTable.length),r.timeToSampleTable.map(e=>[m(e.sampleCount),m(e.sampleDelta)])]),Or=r=>{if(r.samples.every(t=>t.type==="key"))return null;let e=[...r.samples.entries()].filter(([,t])=>t.type==="key");return T("stss",0,0,[m(e.length),e.map(([t])=>m(t+1))])},Vr=r=>T("stsc",0,0,[m(r.compactlyCodedChunkTable.length),r.compactlyCodedChunkTable.map(e=>[m(e.firstChunk),m(e.samplesPerChunk),m(1)])]),Rr=r=>T("stsz",0,0,[m(0),m(r.samples.length),r.samples.map(e=>m(e.size))]),Mr=r=>r.finalizedChunks.length>0&&v(r.finalizedChunks).offset>=2**32?T("co64",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>H(e.offset))]):T("stco",0,0,[m(r.finalizedChunks.length),r.finalizedChunks.map(e=>m(e.offset))]),Pr=r=>T("ctts",0,0,[m(r.compositionTimeOffsetTable.length),r.compositionTimeOffsetTable.map(e=>[m(e.sampleCount),m(e.sampleCompositionTimeOffset)])]),zr=r=>b("mvex",void 0,r.map(Br)),Br=r=>T("trex",0,0,[m(r.track.id),m(1),m(0),m(0),m(0)]),je=(r,e)=>b("moof",void 0,[Ur(r),...e.map(Dr)]),Ur=r=>T("mfhd",0,0,[m(r)]),Vt=r=>{let e=0,t=0,i=0,s=0,n=r.type==="delta";return t|=+n,n?e|=1:e|=2,e<<24|t<<16|i<<8|s},Dr=r=>b("traf",void 0,[Fr(r),Wr(r),Nr(r)]),Fr=r=>{d(r.currentChunk);let e=0;e|=8,e|=16,e|=32,e|=131072;let t=r.currentChunk.samples[1]??r.currentChunk.samples[0],i={duration:t.timescaleUnitsToNextSample,size:t.size,flags:Vt(t)};return T("tfhd",0,e,[m(r.track.id),m(i.duration),m(i.size),m(i.flags)])},Wr=r=>(d(r.currentChunk),T("tfdt",1,0,[H(A(r.currentChunk.startTimestamp,r.timescale))])),Nr=r=>{d(r.currentChunk);let e=r.currentChunk.samples.map(k=>k.timescaleUnitsToNextSample),t=r.currentChunk.samples.map(k=>k.size),i=r.currentChunk.samples.map(Vt),s=r.currentChunk.samples.map(k=>A(k.timestamp-k.decodeTimestamp,r.timescale)),n=new Set(e),o=new Set(t),a=new Set(i),c=new Set(s),u=a.size===2&&i[0]!==i[1],l=n.size>1,f=o.size>1,g=!u&&a.size>1,x=c.size>1||[...c].some(k=>k!==0),C=0;return C|=1,C|=4*+u,C|=256*+l,C|=512*+f,C|=1024*+g,C|=2048*+x,T("trun",1,C,[m(r.currentChunk.samples.length),m(r.currentChunk.offset-r.currentChunk.moofOffset||0),u?m(i[0]):[],r.currentChunk.samples.map((k,S)=>[l?m(e[S]):[],f?m(t[S]):[],g?m(i[S]):[],x?At(s[S]):[]])])},Rt=r=>b("mfra",void 0,[...r.map(Hr),Lr()]),Hr=(r,e)=>T("tfra",1,0,[m(r.track.id),m(63),m(r.finalizedChunks.length),r.finalizedChunks.map(i=>[H(A(i.startTimestamp,r.timescale)),H(i.moofOffset),m(e+1),m(1),m(1)])]),Lr=()=>T("mfro",0,0,[m(0)]),Mt=()=>b("vtte"),Pt=(r,e,t,i,s)=>b("vttc",void 0,[s!==null?b("vsid",[At(s)]):null,t!==null?b("iden",[..._.encode(t)]):null,e!==null?b("ctim",[..._.encode(Te(e))]):null,i!==null?b("sttg",[..._.encode(i)]):null,b("payl",[..._.encode(r)])]),zt=r=>b("vtta",[..._.encode(r)]),Qr={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},$r={avc:Cr,hevc:wr,vp8:vt,vp9:vt,av1:Sr},jr={aac:"mp4a",opus:"Opus"},Kr={aac:vr,opus:_r},qr={webvtt:"wvtt"},Xr={webvtt:Er};var q=class{output;mutex=new j;constructor(e){this.output=e}beforeTrackAdd(e){}onTrackClose(e){}trackTimestampInfo=new WeakMap;validateAndNormalizeTimestamp(e,t,i){let s=t/1e6,n=this.trackTimestampInfo.get(e);if(!n){if(!i)throw new Error("First frame must be a key frame.");if(this.timestampsMustStartAtZero&&s>0)throw new Error(`Timestamps must start at zero (got ${s}s).`);n={timestampOffset:s,maxTimestamp:e.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:e.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(e,n)}if(e.source._offsetTimestamps&&(s-=n.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(si.start-s.start);e.push({start:t[0].start,size:t[0].data.byteLength});for(let i=1;ic.start<=t&&tYr){for(let c=0;c=e.written[n+1].start;)e.written[n].end=Math.max(e.written[n].end,e.written[n+1].end),e.written.splice(n+1,1)}createChunk(e){let i={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(i),this.chunks.sort((s,n)=>s.start-n.start),this.chunks.indexOf(i)}queueChunksForFlush(e=!1){d(this.writer);for(let t=0;t{if(r==="avc"){let n=Math.ceil(e/16)*Math.ceil(t/16),o=Bt.find(f=>n<=f.maxMacroblocks&&i<=f.maxBitrate)??v(Bt),a=o?o.level:0,c="64".padStart(2,"0"),u="00",l=a.toString(16).padStart(2,"0");return`avc1.${c}${u}${l}`}else if(r==="hevc"){let s="",o="6",a=e*t,c=Ut.find(l=>a<=l.maxPictureSize&&i<=l.maxBitrate)??v(Ut);return`hev1.${s}1.${o}.${c.tier}${c.level}.B0`}else{if(r==="vp8")return"vp8";if(r==="vp9"){let s="00",n=e*t,o=Dt.find(c=>n<=c.maxPictureSize&&i<=c.maxBitrate)??v(Dt);return`vp09.${s}.${o.level}.08`}else if(r==="av1"){let n=e*t,o=Ft.find(c=>n<=c.maxPictureSize&&i<=c.maxBitrate)??v(Ft);return`av01.0.${o.level.toString().padStart(2,"0")}${o.tier}.08`}}throw new TypeError(`Unhandled codec '${r}'.`)},Nt=(r,e)=>{if(r==="avc"){if(!e||e.byteLength<4)throw new TypeError("AVC description must be at least 4 bytes long.");return`avc1.${Ct(e.subarray(1,4))}`}else if(r==="hevc"){if(!e)throw new TypeError("HEVC description must be provided.");let t=new DataView(e.buffer,e.byteOffset,e.byteLength),i="hev1.",s=e[1]>>6&3,n=e[1]&31;i+=["","A","B","C"][s]+n,i+=".";let o=wt(t.getUint32(2));i+=o.toString(16),i+=".";let a=e[1]>>5&1,c=e[12];i+=a===0?"L":"H",i+=c,i+=".";let u=[];for(let l=0;l<6;l++){let f=e[l+13];u.push(f)}for(;u[u.length-1]===0;)u.pop();return i+=u.map(l=>l.toString(16)).join("."),i}throw new TypeError(`Unhandled codec '${r}'.`)},Ht=(r,e,t)=>{if(r==="aac")return e>=2&&t<=24e3?"mp4a.40.29":t<=24e3?"mp4a.40.5":"mp4a.40.2";if(r==="opus")return"opus";if(r==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${r}'.`)},Lt=(r,e)=>{if(r==="aac"){if(!e||e.byteLength<2)throw new TypeError("AAC description must be at least 2 bytes long.");return`mp4a.40.${e[0]>>3}`}else{if(r==="opus")return"opus";if(r==="vorbis")return"vorbis"}throw new TypeError(`Unhandled codec '${r}'.`)},Qt=r=>r==="avc"?{avc:{format:"avc"}}:r==="hevc"?{hevc:{format:"hevc"}}:{},$t=r=>r==="aac"?{aac:{format:"aac"}}:r==="opus"?{opus:{format:"opus"}}:{},ve=r=>{if(!r)throw new TypeError("Video chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Video chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Video chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Video chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.codedWidth)||r.decoderConfig.codedWidth<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");if(!Number.isInteger(r.decoderConfig.codedHeight)||r.decoderConfig.codedHeight<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");if(r.decoderConfig.description!==void 0&&!We(r.decoderConfig.description))throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.colorSpace!==void 0){let{colorSpace:e}=r.decoderConfig;if(typeof e!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let t=Object.keys(D);if(e.primaries!=null&&!t.includes(e.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${t.join(", ")}.`);let i=Object.keys(F);if(e.transfer!=null&&!i.includes(e.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${i.join(", ")}.`);let s=Object.keys(W);if(e.matrix!=null&&!s.includes(e.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(e.fullRange!=null&&typeof e.fullRange!="boolean")throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.")}if((r.decoderConfig.codec.startsWith("avc1")||r.decoderConfig.codec.startsWith("avc3"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for AVC must include a description, which is expected to be an AVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec.startsWith("hev1")||r.decoderConfig.codec.startsWith("hvc1"))&&!r.decoderConfig.description)throw new TypeError("Video chunk metadata decoder configuration for HEVC must include a description, which is expected to be an HEVCDecoderConfigurationRecord as specified in ISO 14496-15.");if((r.decoderConfig.codec==="vp8"||r.decoderConfig.codec.startsWith("vp09"))&&r.decoderConfig.colorSpace===void 0)throw new TypeError("Video chunk metadata decoder configuration for VP8/VP9 must include a colorSpace.")},_e=r=>{if(!r)throw new TypeError("Audio chunk metadata must be provided.");if(typeof r!="object")throw new TypeError("Audio chunk metadata must be an object.");if(!r.decoderConfig)throw new TypeError("Audio chunk metadata must include a decoder configuration.");if(typeof r.decoderConfig!="object")throw new TypeError("Audio chunk metadata decoder configuration must be an object.");if(typeof r.decoderConfig.codec!="string")throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(r.decoderConfig.sampleRate)||r.decoderConfig.sampleRate<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");if(!Number.isInteger(r.decoderConfig.numberOfChannels)||r.decoderConfig.numberOfChannels<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");if(r.decoderConfig.description!==void 0&&!We(r.decoderConfig.description))throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(r.decoderConfig.codec.startsWith("mp4a")&&!r.decoderConfig.description)throw new TypeError("Audio chunk metadata decoder configuration for AAC must include a description, which is expected to be an AudioSpecificConfig as specified in ISO 14496-3.");if(r.decoderConfig.codec==="opus"&&r.decoderConfig.description&&r.decoderConfig.description.byteLength<18)throw new TypeError("Invalid decoder description provided for Opus; must be at least 18 bytes long.")},Ae=r=>{if(!r)throw new TypeError("Subtitle metadata must be provided.");if(typeof r!="object")throw new TypeError("Subtitle metadata must be an object.");if(!r.config)throw new TypeError("Subtitle metadata must include a config object.");if(typeof r.config!="object")throw new TypeError("Subtitle metadata config must be an object.");if(typeof r.config.description!="string")throw new TypeError("Subtitle metadata config description must be a string.")};var xe=1e3,Zr=2082844800,A=(r,e,t=!0)=>{let i=r*e;return t?Math.round(i):i},Ee=class extends q{timestampsMustStartAtZero=!0;writer;boxWriter;fastStart;auxTarget=new ce;auxWriter=this.auxTarget._createWriter();auxBoxWriter=new ne(this.auxWriter);ftypSize=null;mdat=null;trackDatas=[];creationTime=Math.floor(Date.now()/1e3)+Zr;finalizedChunks=[];nextFragmentNumber=1;constructor(e,t){super(e),this.writer=e._writer,this.boxWriter=new ne(this.writer);let i=this.writer instanceof X?"in-memory":!1;this.fastStart=t._options.fastStart??i,(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),t=this.output._tracks.some(i=>i.type==="video"&&i.source._codec==="avc");this.boxWriter.writeBox(It({holdsAvc:t,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=Ce(!1):this.fastStart==="fragmented"||(this.mdat=Ce(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;ve(t),d(t),d(t.decoderConfig),d(t.decoderConfig.codedWidth!==void 0),d(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},timescale:e.metadata.frameRate??57600,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;_e(t),d(t),d(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},timescale:t.decoderConfig.sampleRate,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Ae(t),d(t),d(t.config);let s={track:e,type:"subtitle",info:{config:t.config},timescale:1e3,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[],lastCueEndTimestamp:0,cueQueue:[],nextSourceId:0,cueToSourceId:new WeakMap};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),this.validateAndNormalizeTimestamp(e,0,!0),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getVideoTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=this.validateAndNormalizeTimestamp(n.track,t.timestamp,t.type==="key"),c=this.createSampleForTrack(n,o,a,(t.duration??0)/1e6,t.type);await this.registerSample(n,c)}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getAudioTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=t.type,c=this.validateAndNormalizeTimestamp(n.track,t.timestamp,a==="key"),u=this.createSampleForTrack(n,o,c,(t.duration??0)/1e6,a);await this.registerSample(n,u)}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let n=this.getSubtitleTrackData(e,i);this.validateAndNormalizeTimestamp(n.track,1e6*t.timestamp,!0),e.source._codec==="webvtt"&&(n.cueQueue.push(t),await this.processWebVTTCues(n,t.timestamp))}finally{s()}}async processWebVTTCues(e,t){for(;e.cueQueue.length>0;){let i=new Set([]);for(let u of e.cueQueue)d(u.timestamp<=t),d(e.lastCueEndTimestamp<=u.timestamp+u.duration),i.add(Math.max(u.timestamp,e.lastCueEndTimestamp)),i.add(u.timestamp+u.duration);let s=[...i].sort((u,l)=>u-l),n=s[0],o=s[1]??n;if(t=o)break;K.lastIndex=0;let f=K.test(l.text),g=l.timestamp+l.duration,x=e.cueToSourceId.get(l);if(x===void 0&&oi.timestamp).sort((i,s)=>i-s);for(let i=0;i{if(e===o)return t.type==="key";let a=o.sampleQueue[0];return a&&a.type==="key"});s>=1&&n&&(i=!0,await this.finalizeFragment())}else i=s>=.5}i&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:t.timestamp,samples:[],offset:null,moofOffset:null}),d(e.currentChunk),e.currentChunk.samples.push(t),e.timestampProcessingQueue.push(t)}async finalizeCurrentChunk(e){if(d(this.fastStart!=="fragmented"),!!e.currentChunk){if(e.finalizedChunks.push(e.currentChunk),this.finalizedChunks.push(e.currentChunk),(e.compactlyCodedChunkTable.length===0||v(e.compactlyCodedChunkTable).samplesPerChunk!==e.currentChunk.samples.length)&&e.compactlyCodedChunkTable.push({firstChunk:e.finalizedChunks.length,samplesPerChunk:e.currentChunk.samples.length}),this.fastStart==="in-memory"){e.currentChunk.offset=0;return}e.currentChunk.offset=this.writer.getPos();for(let t of e.currentChunk.samples)d(t.data),this.writer.write(t.data),t.data=null;await this.writer.flush()}}async interleaveSamples(){d(this.fastStart==="fragmented");for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.sampleQueue.length===0&&!s.track.source._closed)break e;s.sampleQueue.length>0&&s.sampleQueue[0].timestamp=2**32&&(a.largeSize=!0,u=this.boxWriter.measureBox(a)+c),a.size=u,this.boxWriter.writeBox(a)}for(let a of this.trackDatas){a.currentChunk.offset=this.writer.getPos(),a.currentChunk.moofOffset=i;for(let c of a.currentChunk.samples)this.writer.write(c.data),c.data=null}let n=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(s));let o=je(t,this.trackDatas);this.boxWriter.writeBox(o),this.writer.seek(n);for(let a of this.trackDatas)a.finalizedChunks.push(a.currentChunk),this.finalizedChunks.push(a.currentChunk),a.currentChunk=null;e&&await this.writer.flush()}async onTrackClose(e){let t=await this.mutex.acquire();if(e.type==="subtitle"&&e.source._codec==="webvtt"){let i=this.trackDatas.find(s=>s.track===e);i&&await this.processWebVTTCues(i,1/0)}this.fastStart==="fragmented"&&await this.interleaveSamples(),t()}async finalize(){let e=await this.mutex.acquire();for(let t of this.trackDatas)t.type==="subtitle"&&t.track.source._codec==="webvtt"&&await this.processWebVTTCues(t,1/0);if(this.fastStart==="fragmented"){for(let t of this.trackDatas){for(let i of t.sampleQueue)await this.addSampleToTrack(t,i);this.processTimestamps(t)}await this.finalizeFragment(!1)}else for(let t of this.trackDatas)this.processTimestamps(t),await this.finalizeCurrentChunk(t);if(this.fastStart==="in-memory"){d(this.mdat);let t;for(let s=0;s<2;s++){let n=oe(this.trackDatas,this.creationTime),o=this.boxWriter.measureBox(n);t=this.boxWriter.measureBox(this.mdat);let a=this.writer.getPos()+o+t;for(let c of this.finalizedChunks){c.offset=a;for(let{data:u}of c.samples)d(u),a+=u.byteLength,t+=u.byteLength}if(a<2**32)break;t>=2**32&&(this.mdat.largeSize=!0)}let i=oe(this.trackDatas,this.creationTime);this.boxWriter.writeBox(i),this.mdat.size=t,this.boxWriter.writeBox(this.mdat);for(let s of this.finalizedChunks)for(let n of s.samples)d(n.data),this.writer.write(n.data),n.data=null}else if(this.fastStart==="fragmented"){let t=this.writer.getPos(),i=Rt(this.trackDatas);this.boxWriter.writeBox(i);let s=this.writer.getPos()-t;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(s)}else{d(this.mdat),d(this.ftypSize!==null);let t=this.boxWriter.offsets.get(this.mdat);d(t!==void 0);let i=this.writer.getPos()-t;this.mdat.size=i,this.mdat.largeSize=i>=2**32,this.boxWriter.patchBox(this.mdat);let s=oe(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(s);let n=t-this.writer.getPos();this.boxWriter.writeBox(Ot(n))}else this.boxWriter.writeBox(s)}e()}};var ue=class{value;constructor(e){this.value=e}},Z=class{value;constructor(e){this.value=e}},de=class{value;constructor(e){this.value=e}};var qe=r=>r<256?1:r<65536?2:r<1<<24?3:r<2**32?4:r<2**40?5:6,Xe=r=>r>=-64&&r<64?1:r>=-8192&&r<8192?2:r>=-(1<<20)&&r<1<<20?3:r>=-(1<<27)&&r<1<<27?4:r>=-(2**34)&&r<2**34?5:6,jt=r=>{if(r<127)return 1;if(r<16383)return 2;if(r<(1<<21)-1)return 3;if(r<(1<<28)-1)return 4;if(r<2**35-1)return 5;if(r<2**42-1)return 6;throw new Error("EBML VINT size not supported "+r)};var Ge=2**15,Kt="https://github.com/Vanilagy/webm-muxer",qt=6,Xt=5,Jr={avc:"V_MPEG4/ISO/AVC",hevc:"V_MPEGH/ISO/HEVC",vp8:"V_VP8",vp9:"V_VP9",av1:"V_AV1",aac:"A_AAC",opus:"A_OPUS",webvtt:"S_TEXT/WEBVTT"},ei={video:1,audio:2,subtitle:17},Ie=class extends q{timestampsMustStartAtZero=!1;writer;format;helper=new Uint8Array(8);helperView=new DataView(this.helper.buffer);offsets=new WeakMap;dataOffsets=new WeakMap;trackDatas=[];segment=null;segmentInfo=null;seekHead=null;tracksElement=null;segmentDuration=null;cues=null;currentCluster=null;currentClusterMsTimestamp=null;trackDatasInCurrentCluster=new Set;duration=0;constructor(e,t){super(e),this.writer=e._writer,this.format=t,this.format._options.streamable&&(this.writer.ensureMonotonicity=!0)}writeByte(e){this.helperView.setUint8(0,e),this.writer.write(this.helper.subarray(0,1))}writeFloat32(e){this.helperView.setFloat32(0,e,!1),this.writer.write(this.helper.subarray(0,4))}writeFloat64(e){this.helperView.setFloat64(0,e,!1),this.writer.write(this.helper)}writeUnsignedInt(e,t=qe(e)){let i=0;switch(t){case 6:this.helperView.setUint8(i++,e/2**40|0);case 5:this.helperView.setUint8(i++,e/2**32|0);case 4:this.helperView.setUint8(i++,e>>24);case 3:this.helperView.setUint8(i++,e>>16);case 2:this.helperView.setUint8(i++,e>>8);case 1:this.helperView.setUint8(i++,e);break;default:throw new Error("Bad UINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeSignedInt(e,t=Xe(e)){e<0&&(e+=2**(t*8)),this.writeUnsignedInt(e,t)}writeEBMLVarInt(e,t=jt(e)){let i=0;switch(t){case 1:this.helperView.setUint8(i++,128|e);break;case 2:this.helperView.setUint8(i++,64|e>>8),this.helperView.setUint8(i++,e);break;case 3:this.helperView.setUint8(i++,32|e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 4:this.helperView.setUint8(i++,16|e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 5:this.helperView.setUint8(i++,8|e/2**32&7),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;case 6:this.helperView.setUint8(i++,4|e/2**40&3),this.helperView.setUint8(i++,e/2**32|0),this.helperView.setUint8(i++,e>>24),this.helperView.setUint8(i++,e>>16),this.helperView.setUint8(i++,e>>8),this.helperView.setUint8(i++,e);break;default:throw new Error("Bad EBML VINT size "+t)}this.writer.write(this.helper.subarray(0,i))}writeString(e){this.writer.write(new Uint8Array(e.split("").map(t=>t.charCodeAt(0))))}writeEBML(e){if(e!==null){if(e instanceof Uint8Array)this.writer.write(e);else if(Array.isArray(e))for(let t of e)this.writeEBML(t);else if(this.offsets.set(e,this.writer.getPos()),this.writeUnsignedInt(e.id),Array.isArray(e.data)){let t=this.writer.getPos(),i=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+i);let s=this.writer.getPos();if(this.dataOffsets.set(e,s),this.writeEBML(e.data),e.size!==-1){let n=this.writer.getPos()-s,o=this.writer.getPos();this.writer.seek(t),this.writeEBMLVarInt(n,i),this.writer.seek(o)}}else if(typeof e.data=="number"){let t=e.size??qe(e.data);this.writeEBMLVarInt(t),this.writeUnsignedInt(e.data,t)}else if(typeof e.data=="string")this.writeEBMLVarInt(e.data.length),this.writeString(e.data);else if(e.data instanceof Uint8Array)this.writeEBMLVarInt(e.data.byteLength,e.size),this.writer.write(e.data);else if(e.data instanceof ue)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof Z)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof de){let t=e.size??Xe(e.data.value);this.writeEBMLVarInt(t),this.writeSignedInt(e.data.value,t)}}}beforeTrackAdd(e){if(this.format instanceof J)if(e.type==="video"){if(!["vp8","vp9","av1"].includes(e.source._codec))throw new Error("WebM only supports VP8, VP9 and AV1 as video codecs. Switching to MKV removes this restriction.")}else if(e.type==="audio"){if(!["opus","vorbis"].includes(e.source._codec))throw new Error("WebM only supports Opus and Vorbis as audio codecs. Switching to MKV removes this restriction.")}else if(e.type==="subtitle"){if(e.source._codec!=="webvtt")throw new Error("WebM only supports WebVTT as subtitle codec. Switching to MKV removes this restriction.")}else throw new Error("WebM only supports video, audio and subtitle tracks. Switching to MKV removes this restriction.")}async start(){let e=await this.mutex.acquire();this.writeEBMLHeader(),this.format._options.streamable||this.createSeekHead(),this.createSegmentInfo(),this.createCues(),await this.writer.flush(),e()}writeEBMLHeader(){let e={id:440786851,data:[{id:17030,data:1},{id:17143,data:1},{id:17138,data:4},{id:17139,data:8},{id:17026,data:this.format instanceof J?"webm":"matroska"},{id:17031,data:2},{id:17029,data:2}]};this.writeEBML(e)}createSeekHead(){let e=new Uint8Array([28,83,187,107]),t=new Uint8Array([21,73,169,102]),i=new Uint8Array([22,84,174,107]),s={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:t},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:i},{id:21420,size:5,data:0}]}]};this.seekHead=s}createSegmentInfo(){let e={id:17545,data:new Z(0)};this.segmentDuration=e;let t={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:Kt},{id:22337,data:Kt},this.format._options.streamable?null:e]};this.segmentInfo=t}createTracks(){let e={id:374648427,data:[]};this.tracksElement=e;for(let t of this.trackDatas)e.data.push({id:174,data:[{id:215,data:t.track.id},{id:29637,data:t.track.id},{id:131,data:ei[t.type]},{id:134,data:Jr[t.track.source._codec]},t.type==="video"?this.videoSpecificTrackInfo(t):null,t.type==="audio"?this.audioSpecificTrackInfo(t):null,t.type==="subtitle"?this.subtitleSpecificTrackInfo(t):null]})}videoSpecificTrackInfo(e){let t=[e.info.decoderConfig.description?{id:25506,data:U(e.info.decoderConfig.description)}:null,e.track.metadata.frameRate?{id:2352003,data:1e9/e.track.metadata.frameRate}:null],i=e.info.decoderConfig.colorSpace,s={id:224,data:[{id:176,data:e.info.width},{id:186,data:e.info.height},be(i)?{id:21936,data:[{id:21937,data:W[i.matrix]},{id:21946,data:F[i.transfer]},{id:21947,data:D[i.primaries]},{id:21945,data:i.fullRange?2:1}]}:null]};return t.push(s),t}audioSpecificTrackInfo(e){return[e.info.decoderConfig.description?{id:25506,data:U(e.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new ue(e.info.sampleRate)},{id:159,data:e.info.numberOfChannels}]}]}subtitleSpecificTrackInfo(e){return[{id:25506,data:_.encode(e.info.config.description)}]}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:qt,data:[this.format._options.streamable?null:this.seekHead,this.segmentInfo,this.tracksElement]};this.segment=e,this.writeEBML(e)}createCues(){this.cues={id:475249515,data:[]}}get segmentDataOffset(){return d(this.segment),this.dataOffsets.get(this.segment)}getVideoTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;ve(t),d(t),d(t.decoderConfig),d(t.decoderConfig.codedWidth!==void 0),d(t.decoderConfig.codedHeight!==void 0);let s={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getAudioTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;_e(t),d(t),d(t.decoderConfig);let s={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}getSubtitleTrackData(e,t){let i=this.trackDatas.find(n=>n.track===e);if(i)return i;Ae(t),d(t),d(t.config);let s={track:e,type:"subtitle",info:{config:t.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(s),this.trackDatas.sort((n,o)=>n.track.id-o.track.id),s}async addEncodedVideoChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getVideoTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=t.type==="key",c=this.validateAndNormalizeTimestamp(n.track,t.timestamp,a),u=this.createInternalChunk(o,c,(t.duration??0)/1e6,t.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(n,u),n.chunkQueue.push(u),await this.interleaveChunks()}finally{s()}}async addEncodedAudioChunk(e,t,i){let s=await this.mutex.acquire();try{let n=this.getAudioTrackData(e,i),o=new Uint8Array(t.byteLength);t.copyTo(o);let a=t.type,c=a==="key",u=this.validateAndNormalizeTimestamp(n.track,t.timestamp,c),l=this.createInternalChunk(o,u,(t.duration??0)/1e6,a);n.chunkQueue.push(l),await this.interleaveChunks()}finally{s()}}async addSubtitleCue(e,t,i){let s=await this.mutex.acquire();try{let n=this.getSubtitleTrackData(e,i),o=this.validateAndNormalizeTimestamp(n.track,1e6*t.timestamp,!0),a=t.text,c=Math.floor(o*1e3);K.lastIndex=0,a=a.replace(K,g=>{let C=ge(g.slice(1,-1))-c;return`<${Te(C)}>`});let u=_.encode(a),l=`${t.settings??""} ${t.identifier??""} -${t.notes??""}`,f=this.createInternalChunk(u,n,t.duration,"key",d.trim()?v.encode(d):null);o.chunkQueue.push(f),await this.interleaveChunks()}finally{s()}}async interleaveChunks(){for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.chunkQueue.length===0&&!s.track.source._closed)break e;s.chunkQueue.length>0&&s.chunkQueue[0].timestamp=2&&i++;let c={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];bt(t.data,i+0,i+3,c)}createInternalChunk(e,t,i,s,o=null){return{data:e,type:s,timestamp:t,duration:i,additions:o}}writeBlock(e,t){this.segment||(this.createTracks(),this.createSegment());let i=Math.floor(1e3*t.timestamp),s=this.trackDatas.every(d=>{if(d.track.source._closed)return!0;if(e===d)return t.type==="key";let f=d.chunkQueue[0];return f&&f.type==="key"});(!this.currentCluster||s&&i-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(i);let o=i-this.currentClusterMsTimestamp;if(o<0)return;if(o>=qe)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${qe} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${qe} milliseconds.`);let a=new Uint8Array(4),c=new DataView(a.buffer);c.setUint8(0,128|e.track.id),c.setInt16(1,o,!1);let u=Math.floor(1e3*t.duration);if(u===0&&!t.additions){c.setUint8(3,+(t.type==="key")<<7);let d={id:163,data:[a,t.data]};this.writeEBML(d)}else{let d={id:160,data:[{id:161,data:[a,t.data]},t.type==="delta"?{id:251,data:new ne(e.lastWrittenMsTimestamp-i)}:null,t.additions?{id:30113,data:[{id:166,data:[{id:165,data:t.additions},{id:238,data:1}]}]}:null,u>0?{id:155,data:u}:null]};this.writeEBML(d)}this.duration=Math.max(this.duration,i+u),e.lastWrittenMsTimestamp=i,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:Kt,data:[{id:231,data:e}]},this.writeEBML(this.currentCluster),this.currentClusterMsTimestamp=e,this.trackDatasInCurrentCluster.clear()}finalizeCurrentCluster(){l(this.currentCluster);let e=this.writer.getPos()-this.dataOffsets.get(this.currentCluster),t=this.writer.getPos();this.writer.seek(this.offsets.get(this.currentCluster)+4),this.writeEBMLVarInt(e,Kt),this.writer.seek(t);let i=this.offsets.get(this.currentCluster)-this.segmentDataOffset;l(this.cues),this.cues.data.push({id:187,data:[{id:179,data:this.currentClusterMsTimestamp},...[...this.trackDatasInCurrentCluster].map(s=>({id:183,data:[{id:247,data:s.track.id},{id:241,data:i}]}))]})}async onTrackClose(){let e=await this.mutex.acquire();await this.interleaveChunks(),e()}async finalize(){let e=await this.mutex.acquire();this.segment||(this.createTracks(),this.createSegment());for(let t of this.trackDatas)for(;t.chunkQueue.length>0;)this.writeBlock(t,t.chunkQueue.shift());if(!this.format._options.streamable&&this.currentCluster&&this.finalizeCurrentCluster(),l(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let t=this.writer.getPos(),i=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(i,jt),this.segmentDuration.data=new q(this.duration),this.writer.seek(this.offsets.get(this.segmentDuration)),this.writeEBML(this.segmentDuration),this.seekHead.data[0].data[1].data=this.offsets.get(this.cues)-this.segmentDataOffset,this.seekHead.data[1].data[1].data=this.offsets.get(this.segmentInfo)-this.segmentDataOffset,this.seekHead.data[2].data[1].data=this.offsets.get(this.tracksElement)-this.segmentDataOffset,this.writer.seek(this.offsets.get(this.seekHead)),this.writeEBML(this.seekHead),this.writer.seek(t)}e()}};var N=class{},Xe=class extends N{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(e.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=e}_createMuxer(e){return new ve(e,this)}},Ae=class extends N{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.streamable!==void 0&&typeof e.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=e}_createMuxer(e){return new _e(e,this)}},X=class extends Ae{};var G=class{_connectedTrack=null;_closed=!1;_offsetTimestamps=!1;_ensureValidDigest(){if(!this._connectedTrack)throw new Error("Cannot call digest without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call digest before output has been started.");if(this._connectedTrack.output._finalizing)throw new Error("Cannot call digest after output has started finalizing.");if(this._closed)throw new Error("Cannot call digest after source has been closed.")}_start(){}async _flush(){}close(){if(this._closed)throw new Error("Source already closed.");if(!this._connectedTrack)throw new Error("Cannot call close without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call close before output has been started.");this._closed=!0,!this._connectedTrack.output._finalizing&&this._connectedTrack.output._muxer.onTrackClose(this._connectedTrack)}},I=class extends G{_connectedTrack=null;_codec;constructor(e){if(super(),!j.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${j.join(", ")}.`);this._codec=e}},Ge=class extends I{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,e,t)}},Jr=5,ei=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!j.includes(r.codec))throw new TypeError(`Invalid video codec '${r.codec}'. Must be one of: ${j.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.");if(r.latencyMode!==void 0&&!["quality","realtime"].includes(r.latencyMode))throw new TypeError("config.latencyMode, when provided, must be 'quality' or 'realtime'.")},ae=class{constructor(e,t){this.source=e;this.codecConfig=t;ei(t)}encoder=null;muxer=null;lastMultipleOfKeyFrameInterval=-1;lastWidth=null;lastHeight=null;async digest(e){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(e.codedWidth!==this.lastWidth||e.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${e.codedWidth}x${e.codedHeight}.`)}else this.lastWidth=e.codedWidth,this.lastHeight=e.codedHeight;this.ensureEncoder(e),l(this.encoder);let t=Math.floor(e.timestamp/1e6/Jr);this.encoder.encode(e,{keyFrame:t!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=t,this.encoder.encodeQueueSize>=4&&await new Promise(i=>this.encoder.addEventListener("dequeue",i,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new VideoEncoder({output:(t,i)=>void this.muxer.addEncodedVideoChunk(this.source._connectedTrack,t,i),error:t=>console.error("Video encode error:",t)}),this.encoder.configure({codec:Dt(this.codecConfig.codec,e.codedWidth,e.codedHeight,this.codecConfig.bitrate),width:e.codedWidth,height:e.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode,...Ht(this.codecConfig.codec)}),l(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Ye=class extends I{_encoder;constructor(e){super(e.codec),this._encoder=new ae(this,e)}digest(e){if(!(e instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},Ze=class extends I{_encoder;_canvas;constructor(e,t){if(!(e instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(t.codec),this._encoder=new ae(this,t),this._canvas=e}digest(e,t=0){if(!Number.isFinite(e)||e<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(t)||t<0)throw new TypeError("duration must be a non-negative number.");let i=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*e),duration:Math.round(1e6*t),alpha:"discard"}),s=this._encoder.digest(i);return i.close(),s}_flush(){return this._encoder.flush()}},Je=class extends I{_encoder;_abortController=null;_track;_offsetTimestamps=!0;constructor(e,t){if(!(e instanceof MediaStreamTrack)||e.kind!=="video")throw new TypeError("track must be a video MediaStreamTrack.");t={...t,latencyMode:"realtime"},super(t.codec),this._encoder=new ae(this,t),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),t=new WritableStream({write:i=>{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},O=class extends G{_connectedTrack=null;_codec;constructor(e){if(super(),!K.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${K.join(", ")}.`);this._codec=e}},et=class extends O{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,e,t)}},ti=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!K.includes(r.codec))throw new TypeError(`Invalid audio codec '${r.codec}'. Must be one of: ${K.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},ce=class{constructor(e,t){this.source=e;this.codecConfig=t;ti(t)}encoder=null;muxer=null;lastNumberOfChannels=null;lastSampleRate=null;async digest(e){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(e.numberOfChannels!==this.lastNumberOfChannels||e.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${e.numberOfChannels} channels at ${e.sampleRate} Hz.`)}else this.lastNumberOfChannels=e.numberOfChannels,this.lastSampleRate=e.sampleRate;this.ensureEncoder(e),l(this.encoder),this.encoder.encode(e),this.encoder.encodeQueueSize>=4&&await new Promise(t=>this.encoder.addEventListener("dequeue",t,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new AudioEncoder({output:(t,i)=>void this.muxer.addEncodedAudioChunk(this.source._connectedTrack,t,i),error:t=>console.error("Audio encode error:",t)}),this.encoder.configure({codec:Wt(this.codecConfig.codec,e.numberOfChannels,e.sampleRate),numberOfChannels:e.numberOfChannels,sampleRate:e.sampleRate,bitrate:this.codecConfig.bitrate,...Lt(this.codecConfig.codec)}),l(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},tt=class extends O{_encoder;constructor(e){super(e.codec),this._encoder=new ce(this,e)}digest(e){if(!(e instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},rt=class extends O{_encoder;_accumulatedFrameCount=0;constructor(e){super(e.codec),this._encoder=new ce(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let t=e.numberOfChannels,i=e.sampleRate,s=e.length,o=new Float32Array(t*s);for(let c=0;c{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},Y=class extends G{_connectedTrack=null;_codec;constructor(e){if(super(),!Ce.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${Ce.join(", ")}.`);this._codec=e}},st=class extends Y{_parser;constructor(e){super(e),this._parser=new he({codec:e,output:(t,i)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,t,i),error:t=>console.error("Subtitle parse error:",t)})}digest(e){if(typeof e!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(e),this._connectedTrack.output._muxer.mutex.currentPromise}};var ot=class{_muxer;_writer;_tracks=[];_started=!1;_finalizing=!1;_mutex=new H;constructor(e){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(!(e.format instanceof N))throw new TypeError("options.format must be an OutputFormat.");if(!(e.target instanceof W))throw new TypeError("options.target must be a Target.");if(e.target._output)throw new Error("Target is already used for another output.");e.target._output=this,this._writer=e.target._createWriter(),this._muxer=e.format._createMuxer(this)}addVideoTrack(e,t={}){if(!(e instanceof I))throw new TypeError("source must be a VideoSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");if(typeof t.rotation=="number"&&![0,90,180,270].includes(t.rotation))throw new TypeError(`Invalid video rotation: ${t.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(t.rotation)&&(t.rotation.length!==9||t.rotation.some(i=>!Number.isFinite(i))))throw new TypeError(`Invalid video transformation matrix: ${t.rotation.join()}`);if(t.frameRate!==void 0&&(!Number.isInteger(t.frameRate)||t.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${t.frameRate}. Must be a positive integer.`);this._addTrack("video",e,t)}addAudioTrack(e,t={}){if(!(e instanceof O))throw new TypeError("source must be an AudioSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",e,t)}addSubtitleTrack(e,t={}){if(!(e instanceof Y))throw new TypeError("source must be a SubtitleSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",e,t)}_addTrack(e,t,i){if(this._started)throw new Error("Cannot add track after output has started.");if(t._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:e,source:t,metadata:i};this._muxer.beforeTrackAdd(s),this._tracks.push(s),t._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let e=await this._mutex.acquire();await this._muxer.start();for(let t of this._tracks)t.source._start();e()}async finalize(){if(!this._started)throw new Error("Cannot finalize before starting.");if(this._finalizing)throw new Error("Cannot call finalize twice.");this._finalizing=!0;let e=await this._mutex.acquire(),t=this._tracks.map(i=>i.source._flush());await Promise.all(t),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),e()}};var ue=class{},nt=class extends ue{constructor(t){super();this.buffer=t}async _read(t,i){return new Uint8Array(this.buffer,t,i-t)}async _getSize(){return this.buffer.byteLength}},at=class extends ue{constructor(t){super();this.blob=t}async _read(t,i){let o=await this.blob.slice(t,i).arrayBuffer();return new Uint8Array(o)}async _getSize(){return this.blob.size}};var Z=class{input;constructor(e){this.input=e}};var Ee=class{_backing;constructor(e){this._backing=e}isVideoTrack(){return this instanceof de}isAudioTrack(){return this instanceof le}getDuration(){return this._backing.getDuration()}},de=class extends Ee{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getWidth(){return this._backing.getWidth()}getHeight(){return this._backing.getHeight()}getRotation(){return this._backing.getRotation()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}},le=class extends Ee{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getNumberOfChannels(){return this._backing.getNumberOfChannels()}getSampleRate(){return this._backing.getSampleRate()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}};var J=class{constructor(e){this.reader=e}pos=0;readRange(e,t){let{view:i,offset:s}=this.reader.getViewAndOffset(e,t);return new Uint8Array(i.buffer,s,t-e)}readU8(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+1);return this.pos++,e.getUint8(t)}readU16(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+2);return this.pos+=2,e.getUint16(t,!1)}readU24(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+3);this.pos+=3;let i=e.getUint16(t,!1),s=e.getUint8(t+2);return i*256+s}readS32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getUint32(t,!1)}readI32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU64(){let e=this.readU32(),t=this.readU32();return e*4294967296+t}readF64(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+8);return this.pos+=8,e.getFloat64(t,!1)}readFixed_16_16(){return this.readS32()/65536}readFixed_2_30(){return this.readS32()/1073741824}readAscii(e){let{view:t,offset:i}=this.reader.getViewAndOffset(this.pos,this.pos+e);this.pos+=e;let s="";for(let o=0;oe.inputTrack)}async getMimeType(){await this.readMetadata();let e="video/mp4";if(this.tracks.length>0){let t=await Promise.all(this.tracks.map(s=>s.inputTrack.getCodecMimeType())),i=[...new Set(t)];e+=`; codecs="${i.join(", ")}"`}return e}readMetadata(){return this.metadataPromise??=(async()=>{let e=await this.isobmffReader.reader.getSourceSize();for(;this.isobmffReader.posi.presentationTimestamp-s.presentationTimestamp),e.sampleTable}readContiguousBoxes(e){let t=this.isobmffReader.pos;for(;this.isobmffReader.pos-td.every((f,T)=>f===c[T]));u===-1?s.rotation=0:s.rotation=90*u}break;case"mdhd":{let s=this.currentTrack;l(s);let o=this.isobmffReader.readU8();this.isobmffReader.pos+=3,o===0?(this.isobmffReader.pos+=8,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU32()):o===1&&(this.isobmffReader.pos+=16,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU64())}break;case"hdlr":{let s=this.currentTrack;l(s),this.isobmffReader.pos+=8;let o=this.isobmffReader.readAscii(4);o==="vide"?s.info={type:"video",width:-1,height:-1,codec:null,codecDescription:null,colorSpace:null}:o==="soun"&&(s.info={type:"audio",numberOfChannels:-1,sampleRate:-1,codec:null,codecDescription:null})}break;case"stbl":{let s=this.currentTrack;l(s),s.sampleTableOffset=e,this.readContiguousBoxes(t.contentSize)}break;case"stsd":{let s=this.currentTrack;if(l(s),s.info===null||s.sampleTable)break;let o=this.isobmffReader.readU8();this.isobmffReader.pos+=3;let n=this.isobmffReader.readU32();for(let a=0;a0){if(u===1)this.isobmffReader.pos+=4*4;else if(u===2){this.isobmffReader.pos+=4,f=this.isobmffReader.readF64(),d=this.isobmffReader.readU32(),this.isobmffReader.pos+=4;let T=this.isobmffReader.readU32(),C=this.isobmffReader.readU32(),k=this.isobmffReader.readU32(),w=this.isobmffReader.readU32()}}s.info.numberOfChannels=d,s.info.sampleRate=f,this.readContiguousBoxes(e+c.totalSize-this.isobmffReader.pos)}}}break;case"avcC":{let s=this.currentTrack;l(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"hvcC":{let s=this.currentTrack;l(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"colr":{let s=this.currentTrack;if(l(s&&s.info?.type==="video"),this.isobmffReader.readAscii(4)!=="nclx")break;let n=this.isobmffReader.readU16(),a=this.isobmffReader.readU16(),c=this.isobmffReader.readU16(),u=!!(this.isobmffReader.readU8()&128);s.info.colorSpace={primaries:kt[n],transfer:gt[a],matrix:Tt[c],fullRange:u}}break;case"wave":t.totalSize>8&&this.readContiguousBoxes(t.contentSize);break;case"esds":{let s=this.currentTrack;l(s&&s.info),this.isobmffReader.pos+=4;let o=this.isobmffReader.readU8();l(o===3),this.isobmffReader.readIsomVariableInteger(),this.isobmffReader.pos+=2;let n=this.isobmffReader.readU8(),a=(n&128)!==0,c=(n&64)!==0,u=(n&32)!==0;if(a&&(this.isobmffReader.pos+=2),c){let k=this.isobmffReader.readU8();this.isobmffReader.pos+=k}u&&(this.isobmffReader.pos+=2);let d=this.isobmffReader.readU8();l(d===4),this.isobmffReader.readIsomVariableInteger();let f=this.isobmffReader.readU8();l(f===64),this.isobmffReader.pos+=12;let T=this.isobmffReader.readU8();l(T===5);let C=this.isobmffReader.readIsomVariableInteger();s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+C)}break;case"stts":{let s=this.currentTrack;if(l(s),!s.sampleTable)break;this.isobmffReader.pos+=4;let o=this.isobmffReader.readU32(),n=0,a=0;for(let c=0;c{let t=D(r.presentationTimestamps,e,i=>i.presentationTimestamp);return t===-1?-1:r.presentationTimestamps[t].sampleIndex},ii=(r,e)=>{let t=D(r.sampleTimingEntries,e,k=>k.startIndex),i=r.sampleTimingEntries[t];if(!i||i.startIndex+i.count<=e)return null;let o=i.startDecodeTimestamp+(e-i.startIndex)*i.delta,n=D(r.sampleCompositionTimeOffsets,e,k=>k.startIndex),a=r.sampleCompositionTimeOffsets[n];a&&(o+=a.offset);let c=r.sampleSizes[Math.min(e,r.sampleSizes.length-1)],u=D(r.sampleToChunk,e,k=>k.startSampleIndex),d=r.sampleToChunk[u];l(d);let f=d.startChunkIndex+Math.floor((e-d.startSampleIndex)/d.samplesPerChunk),C=r.chunkOffsets[f];if(r.sampleSizes.length===1)C+=c*(e-d.startSampleIndex);else{let k=d.startSampleIndex+(f-d.startChunkIndex)*d.samplesPerChunk;for(let w=k;wk)!==-1:!0}},si=(r,e)=>{if(!r.keySampleIndices)return e;let t=D(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t]??-1},oi=(r,e)=>{if(!r.keySampleIndices)return e+1;let t=D(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t+1]??-1};var Ve=class extends Z{};var Me=class{},dt=class extends Me{async _canReadInput(e){if(await e._reader.getSourceSize()<8)return!1;await e._reader.loadRange(4,8);let i=new J(e._reader);return i.pos=4,i.readAscii(4)==="ftyp"}_createDemuxer(e){return new Ie(e)}},lt=class extends Me{async _canReadInput(){return!1}_createDemuxer(e){return new Ve(e)}},Re=new dt,ni=Re,ai=Re,mt=new lt,Xt=mt,ci=mt,ui=[Re,Xt];var Pe=4096,ze=class{constructor(e){this.source=e}loadedSegments=[];sourceSizePromise=null;getSourceSize(){return this.sourceSizePromise?this.sourceSizePromise:this.sourceSizePromise=this.source._getSize()}async loadRange(e,t){let i=Math.floor(e/Pe)*Pe,s=Math.ceil(t/Pe)*Pe;s=Math.min(s,await this.getSourceSize());let o=this.loadedSegments.find(c=>c.start<=i);o&&(i=Math.max(i,o.end));let n=this.loadedSegments.find(c=>c.end>=s);if(n&&(s=Math.min(s,n.start)),i>=s)return;let a=await this.source._read(i,s);this.insertIntoLoadedSegments(i,a)}insertIntoLoadedSegments(e,t){let i={start:e,end:e+t.byteLength,bytes:t,view:new DataView(t.buffer)},s=this.loadedSegments.findLastIndex(d=>d.start<=e);this.loadedSegments.splice(s+1,0,i),(s===-1||this.loadedSegments[s].enda&&this.loadedSegments[a+1].start<=c;)a++,c=Math.max(c,this.loadedSegments[a].end);if(o===a)return;for(let d=o;d<=a;d++){let f=this.loadedSegments[d];if(f.start===n&&f.end===c){this.loadedSegments.splice(d+1,a-d),this.loadedSegments.splice(o,d-o);return}}let u=new Uint8Array(c-n);for(let d=o;d<=a;d++){let f=this.loadedSegments[d];u.set(f.bytes,f.start-n)}this.loadedSegments.splice(o+1,a-o),this.loadedSegments[o].end=c,this.loadedSegments[o].bytes=u,this.loadedSegments[o].view=new DataView(u.buffer)}getViewAndOffset(e,t){let i=this.loadedSegments.find(s=>s.start<=e&&t<=s.end);if(!i)throw new Error(`No segment loaded for range [${e}, ${t}).`);return{view:i.view,offset:i.bytes.byteOffset+e-i.start}}};var ft=class{_formats;_reader;_demuxerPromise=null;_format=null;constructor(e){this._formats=e.formats,this._reader=new ze(e.source)}_getDemuxer(){return this._demuxerPromise??=(async()=>{for(let e of this._formats)if(await e._canReadInput(this))return this._format=e,e._createDemuxer(this);throw new Error("Input has an unrecognizable format.")})()}async getFormat(){return await this._getDemuxer(),l(this._format),this._format}async getDuration(){return(await this._getDemuxer()).getDuration()}async getTracks(){return(await this._getDemuxer()).getTracks()}async getVideoTracks(){return(await this.getTracks()).filter(t=>t.isVideoTrack())}async getPrimaryVideoTrack(){return(await this.getTracks()).find(t=>t.isVideoTrack())??null}async getAudioTracks(){return(await this.getTracks()).filter(t=>t.isAudioTrack())}async getPrimaryAudioTrack(){return(await this.getTracks()).find(t=>t.isAudioTrack())??null}async getMimeType(){return(await this._getDemuxer()).getMimeType()}};var ht=class{constructor(e){this.videoTrack=e}getFirstChunk(){return this.videoTrack._backing.getFirstChunk()}getChunk(e){return this.videoTrack._backing.getChunk(e)}getNextChunk(e){return this.videoTrack._backing.getNextChunk(e)}getKeyChunk(e){return this.videoTrack._backing.getKeyChunk(e)}getNextKeyChunk(e){return this.videoTrack._backing.getNextKeyChunk(e)}async*chunks(e=0){let t=await this.getChunk(e);for(;t;)yield t,t=await this.getNextChunk(t)}},pt=class{constructor(e){this.videoTrack=e}decoderConfig=null;async createDecoder(e){this.decoderConfig||(this.decoderConfig=await this.videoTrack.getDecoderConfig());let t=new VideoDecoder({output:e,error:i=>console.error(i)});return t.configure(this.decoderConfig),t}async getKeyFrame(e){let t=null,i=await this.createDecoder(o=>t=o),s=await this.videoTrack._backing.getKeyChunk(e);return s?(i.decode(s),await i.flush(),i.close(),t):null}async getFrame(e){let t=null,i=await this.createDecoder(a=>{a.timestamp/1e6<=e?(t?.close(),t=a):a.close()}),s=await this.videoTrack._backing.getKeyChunk(e);if(!s)return null;let o=await this.videoTrack._backing.getChunk(e);l(o),i.decode(s);let n=s;for(;n!==o;){let a=await this.videoTrack._backing.getNextChunk(n);l(a),n=a,i.decode(a),i.decodeQueueSize>=10&&await new Promise(c=>i.addEventListener("dequeue",c,{once:!0}))}return await i.flush(),i.close(),t}async*frames(e=0){let t=[],i=!1,s=null,{promise:o,resolve:n}=Fe(),a=!1,c=await this.createDecoder(f=>{if(a){f.close();return}let T=f.timestamp/1e6;s&&(T>e?(t.push(s),i=!0):s.close()),T>=e&&(t.push(f),i=!0),s=i?null:f,t.length>0&&(n(),{promise:o,resolve:n}=Fe())}),u=await this.videoTrack._backing.getKeyChunk(e);if(!u)return;let d=!1;(async()=>{let f=u;for(;f&&!a;)c.decode(f),c.decodeQueueSize>=10&&await new Promise(C=>c.addEventListener("dequeue",C,{once:!0})),f=await this.videoTrack._backing.getNextChunk(f);await c.flush(),c.close(),d=!0,n()})();try{for(;;)if(t.length>0)yield t.shift();else if(!d)await o;else break}finally{a=!0}}};export{ui as ALL_FORMATS,K as AUDIO_CODECS,nt as ArrayBufferSource,se as ArrayBufferTarget,rt as AudioBufferSource,tt as AudioDataSource,O as AudioSource,at as BlobSource,Ze as CanvasSource,et as EncodedAudioChunkSource,ht as EncodedVideoChunkDrain,Ge as EncodedVideoChunkSource,Re as ISOBMFF,ft as Input,mt as MATROSKA,Xt as MKV,ai as MOV,ni as MP4,G as MediaSource,it as MediaStreamAudioTrackSource,Je as MediaStreamVideoTrackSource,Ae as MkvOutputFormat,Xe as Mp4OutputFormat,ot as Output,N as OutputFormat,Ce as SUBTITLE_CODECS,ue as Source,Qe as StreamTarget,Y as SubtitleSource,W as Target,st as TextSubtitleSource,j as VIDEO_CODECS,pt as VideoFrameDrain,Ye as VideoFrameSource,I as VideoSource,ci as WEBM,X as WebMOutputFormat}; +${t.notes??""}`,f=this.createInternalChunk(u,o,t.duration,"key",l.trim()?_.encode(l):null);n.chunkQueue.push(f),await this.interleaveChunks()}finally{s()}}async interleaveChunks(){for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(t=>t.track===e))return;e:for(;;){let e=null,t=1/0;for(let s of this.trackDatas){if(s.chunkQueue.length===0&&!s.track.source._closed)break e;s.chunkQueue.length>0&&s.chunkQueue[0].timestamp=2&&i++;let c={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];kt(t.data,i+0,i+3,c)}createInternalChunk(e,t,i,s,n=null){return{data:e,type:s,timestamp:t,duration:i,additions:n}}writeBlock(e,t){this.segment||(this.createTracks(),this.createSegment());let i=Math.floor(1e3*t.timestamp),s=this.trackDatas.every(l=>{if(l.track.source._closed)return!0;if(e===l)return t.type==="key";let f=l.chunkQueue[0];return f&&f.type==="key"});(!this.currentCluster||s&&i-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(i);let n=i-this.currentClusterMsTimestamp;if(n<0)return;if(n>=Ge)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${Ge} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${Ge} milliseconds.`);let a=new Uint8Array(4),c=new DataView(a.buffer);c.setUint8(0,128|e.track.id),c.setInt16(1,n,!1);let u=Math.floor(1e3*t.duration);if(u===0&&!t.additions){c.setUint8(3,+(t.type==="key")<<7);let l={id:163,data:[a,t.data]};this.writeEBML(l)}else{let l={id:160,data:[{id:161,data:[a,t.data]},t.type==="delta"?{id:251,data:new de(e.lastWrittenMsTimestamp-i)}:null,t.additions?{id:30113,data:[{id:166,data:[{id:165,data:t.additions},{id:238,data:1}]}]}:null,u>0?{id:155,data:u}:null]};this.writeEBML(l)}this.duration=Math.max(this.duration,i+u),e.lastWrittenMsTimestamp=i,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:Xt,data:[{id:231,data:e}]},this.writeEBML(this.currentCluster),this.currentClusterMsTimestamp=e,this.trackDatasInCurrentCluster.clear()}finalizeCurrentCluster(){d(this.currentCluster);let e=this.writer.getPos()-this.dataOffsets.get(this.currentCluster),t=this.writer.getPos();this.writer.seek(this.offsets.get(this.currentCluster)+4),this.writeEBMLVarInt(e,Xt),this.writer.seek(t);let i=this.offsets.get(this.currentCluster)-this.segmentDataOffset;d(this.cues),this.cues.data.push({id:187,data:[{id:179,data:this.currentClusterMsTimestamp},...[...this.trackDatasInCurrentCluster].map(s=>({id:183,data:[{id:247,data:s.track.id},{id:241,data:i}]}))]})}async onTrackClose(){let e=await this.mutex.acquire();await this.interleaveChunks(),e()}async finalize(){let e=await this.mutex.acquire();this.segment||(this.createTracks(),this.createSegment());for(let t of this.trackDatas)for(;t.chunkQueue.length>0;)this.writeBlock(t,t.chunkQueue.shift());if(!this.format._options.streamable&&this.currentCluster&&this.finalizeCurrentCluster(),d(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let t=this.writer.getPos(),i=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(i,qt),this.segmentDuration.data=new Z(this.duration),this.writer.seek(this.offsets.get(this.segmentDuration)),this.writeEBML(this.segmentDuration),this.seekHead.data[0].data[1].data=this.offsets.get(this.cues)-this.segmentDataOffset,this.seekHead.data[1].data[1].data=this.offsets.get(this.segmentInfo)-this.segmentDataOffset,this.seekHead.data[2].data[1].data=this.offsets.get(this.tracksElement)-this.segmentDataOffset,this.writer.seek(this.offsets.get(this.seekHead)),this.writeEBML(this.seekHead),this.writer.seek(t)}e()}};var Q=class{},Ye=class extends Q{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(e.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=e}_createMuxer(e){return new Ee(e,this)}},Oe=class extends Q{_options;constructor(e={}){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.streamable!==void 0&&typeof e.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=e}_createMuxer(e){return new Ie(e,this)}},J=class extends Oe{};var ee=class{_connectedTrack=null;_closed=!1;_offsetTimestamps=!1;_ensureValidDigest(){if(!this._connectedTrack)throw new Error("Cannot call digest without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call digest before output has been started.");if(this._connectedTrack.output._finalizing)throw new Error("Cannot call digest after output has started finalizing.");if(this._closed)throw new Error("Cannot call digest after source has been closed.")}_start(){}async _flush(){}close(){if(this._closed)throw new Error("Source already closed.");if(!this._connectedTrack)throw new Error("Cannot call close without connecting the source to an output track.");if(!this._connectedTrack.output._started)throw new Error("Cannot call close before output has been started.");this._closed=!0,!this._connectedTrack.output._finalizing&&this._connectedTrack.output._muxer.onTrackClose(this._connectedTrack)}},V=class extends ee{_connectedTrack=null;_codec;constructor(e){if(super(),!G.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${G.join(", ")}.`);this._codec=e}},Ze=class extends V{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,e,t)}},ti=5,ri=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!G.includes(r.codec))throw new TypeError(`Invalid video codec '${r.codec}'. Must be one of: ${G.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.");if(r.latencyMode!==void 0&&!["quality","realtime"].includes(r.latencyMode))throw new TypeError("config.latencyMode, when provided, must be 'quality' or 'realtime'.")},le=class{constructor(e,t){this.source=e;this.codecConfig=t;ri(t)}encoder=null;muxer=null;lastMultipleOfKeyFrameInterval=-1;lastWidth=null;lastHeight=null;async digest(e){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(e.codedWidth!==this.lastWidth||e.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${e.codedWidth}x${e.codedHeight}.`)}else this.lastWidth=e.codedWidth,this.lastHeight=e.codedHeight;this.ensureEncoder(e),d(this.encoder);let t=Math.floor(e.timestamp/1e6/ti);this.encoder.encode(e,{keyFrame:t!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=t,this.encoder.encodeQueueSize>=4&&await new Promise(i=>this.encoder.addEventListener("dequeue",i,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new VideoEncoder({output:(t,i)=>void this.muxer.addEncodedVideoChunk(this.source._connectedTrack,t,i),error:t=>console.error("Video encode error:",t)}),this.encoder.configure({codec:Wt(this.codecConfig.codec,e.codedWidth,e.codedHeight,this.codecConfig.bitrate),width:e.codedWidth,height:e.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode,...Qt(this.codecConfig.codec)}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Je=class extends V{_encoder;constructor(e){super(e.codec),this._encoder=new le(this,e)}digest(e){if(!(e instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},et=class extends V{_encoder;_canvas;constructor(e,t){if(!(e instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(t.codec),this._encoder=new le(this,t),this._canvas=e}digest(e,t=0){if(!Number.isFinite(e)||e<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(t)||t<0)throw new TypeError("duration must be a non-negative number.");let i=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*e),duration:Math.round(1e6*t),alpha:"discard"}),s=this._encoder.digest(i);return i.close(),s}_flush(){return this._encoder.flush()}},tt=class extends V{_encoder;_abortController=null;_track;_offsetTimestamps=!0;constructor(e,t){if(!(e instanceof MediaStreamTrack)||e.kind!=="video")throw new TypeError("track must be a video MediaStreamTrack.");t={...t,latencyMode:"realtime"},super(t.codec),this._encoder=new le(this,t),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),t=new WritableStream({write:i=>{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},R=class extends ee{_connectedTrack=null;_codec;constructor(e){if(super(),!Y.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${Y.join(", ")}.`);this._codec=e}},rt=class extends R{constructor(e){super(e)}digest(e,t){if(!(e instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,e,t)}},ii=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!Y.includes(r.codec))throw new TypeError(`Invalid audio codec '${r.codec}'. Must be one of: ${Y.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},me=class{constructor(e,t){this.source=e;this.codecConfig=t;ii(t)}encoder=null;muxer=null;lastNumberOfChannels=null;lastSampleRate=null;async digest(e){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(e.numberOfChannels!==this.lastNumberOfChannels||e.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${e.numberOfChannels} channels at ${e.sampleRate} Hz.`)}else this.lastNumberOfChannels=e.numberOfChannels,this.lastSampleRate=e.sampleRate;this.ensureEncoder(e),d(this.encoder),this.encoder.encode(e),this.encoder.encodeQueueSize>=4&&await new Promise(t=>this.encoder.addEventListener("dequeue",t,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(e){this.encoder||(this.encoder=new AudioEncoder({output:(t,i)=>void this.muxer.addEncodedAudioChunk(this.source._connectedTrack,t,i),error:t=>console.error("Audio encode error:",t)}),this.encoder.configure({codec:Ht(this.codecConfig.codec,e.numberOfChannels,e.sampleRate),numberOfChannels:e.numberOfChannels,sampleRate:e.sampleRate,bitrate:this.codecConfig.bitrate,...$t(this.codecConfig.codec)}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},it=class extends R{_encoder;constructor(e){super(e.codec),this._encoder=new me(this,e)}digest(e){if(!(e instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(e)}_flush(){return this._encoder.flush()}},st=class extends R{_encoder;_accumulatedFrameCount=0;constructor(e){super(e.codec),this._encoder=new me(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let t=e.numberOfChannels,i=e.sampleRate,s=e.length,n=new Float32Array(t*s);for(let c=0;c{this._encoder.digest(i),i.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(i=>{i instanceof DOMException&&i.name==="AbortError"||console.error("Pipe error:",i)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},te=class extends ee{_connectedTrack=null;_codec;constructor(e){if(super(),!ye.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${ye.join(", ")}.`);this._codec=e}},ot=class extends te{_parser;constructor(e){super(e),this._parser=new ke({codec:e,output:(t,i)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,t,i),error:t=>console.error("Subtitle parse error:",t)})}digest(e){if(typeof e!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(e),this._connectedTrack.output._muxer.mutex.currentPromise}};var at=class{_muxer;_writer;_tracks=[];_started=!1;_finalizing=!1;_mutex=new j;constructor(e){if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(!(e.format instanceof Q))throw new TypeError("options.format must be an OutputFormat.");if(!(e.target instanceof L))throw new TypeError("options.target must be a Target.");if(e.target._output)throw new Error("Target is already used for another output.");e.target._output=this,this._writer=e.target._createWriter(),this._muxer=e.format._createMuxer(this)}addVideoTrack(e,t={}){if(!(e instanceof V))throw new TypeError("source must be a VideoSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");if(typeof t.rotation=="number"&&![0,90,180,270].includes(t.rotation))throw new TypeError(`Invalid video rotation: ${t.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(t.rotation)&&(t.rotation.length!==9||t.rotation.some(i=>!Number.isFinite(i))))throw new TypeError(`Invalid video transformation matrix: ${t.rotation.join()}`);if(t.frameRate!==void 0&&(!Number.isInteger(t.frameRate)||t.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${t.frameRate}. Must be a positive integer.`);this._addTrack("video",e,t)}addAudioTrack(e,t={}){if(!(e instanceof R))throw new TypeError("source must be an AudioSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",e,t)}addSubtitleTrack(e,t={}){if(!(e instanceof te))throw new TypeError("source must be a SubtitleSource.");if(!t||typeof t!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",e,t)}_addTrack(e,t,i){if(this._started)throw new Error("Cannot add track after output has started.");if(t._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:e,source:t,metadata:i};this._muxer.beforeTrackAdd(s),this._tracks.push(s),t._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let e=await this._mutex.acquire();await this._muxer.start();for(let t of this._tracks)t.source._start();e()}async finalize(){if(!this._started)throw new Error("Cannot finalize before starting.");if(this._finalizing)throw new Error("Cannot call finalize twice.");this._finalizing=!0;let e=await this._mutex.acquire(),t=this._tracks.map(i=>i.source._flush());await Promise.all(t),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),e()}};var fe=class{_sizePromise=null;_getSize(){return this._sizePromise??=this._retrieveSize()}},ct=class extends fe{constructor(t){super();this.buffer=t}async _read(t,i){return new Uint8Array(this.buffer,t,i-t)}async _retrieveSize(){return this.buffer.byteLength}},ut=class extends fe{constructor(t){super();this.blob=t}async _read(t,i){let n=await this.blob.slice(t,i).arrayBuffer();return new Uint8Array(n)}async _retrieveSize(){return this.blob.size}};var re=class{input;constructor(e){this.input=e}};var Ve=class{_backing;constructor(e){this._backing=e}isVideoTrack(){return this instanceof he}isAudioTrack(){return this instanceof pe}getDuration(){return this._backing.getDuration()}},he=class extends Ve{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getWidth(){return this._backing.getWidth()}getHeight(){return this._backing.getHeight()}getRotation(){return this._backing.getRotation()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}},pe=class extends Ve{_backing;constructor(e){super(e),this._backing=e}getCodec(){return this._backing.getCodec()}getNumberOfChannels(){return this._backing.getNumberOfChannels()}getSampleRate(){return this._backing.getSampleRate()}getDecoderConfig(){return this._backing.getDecoderConfig()}async getCodecMimeType(){return(await this.getDecoderConfig()).codec}};var Re=4096,ie=class{constructor(e,t=1/0){this.source=e;this.maxStorableBytes=t}loadedSegments=[];loadingSegments=[];sourceSizePromise=null;nextAge=0;totalStoredBytes=0;async loadRange(e,t){let i=Math.floor(e/Re)*Re,s=Math.ceil(t/Re)*Re;s=Math.min(s,await this.source._getSize());let n=this.loadingSegments.find(l=>l.start<=i&&l.end>=s);if(n){await n.promise;return}if(this.loadedSegments.some(l=>l.start<=i&&l.end>=s))return;let a=this.source._read(i,s),c={start:i,end:s,promise:a};this.loadingSegments.push(c);let u=await a;yt(this.loadingSegments,c),this.insertIntoLoadedSegments(i,u)}insertIntoLoadedSegments(e,t){let i={start:e,end:e+t.byteLength,bytes:t,view:new DataView(t.buffer),age:this.nextAge++},s=E(this.loadedSegments,e,n=>n.start);(s===-1||this.loadedSegments[s].start=i.end)break;i.start<=o.start&&o.end<=i.end&&(this.loadedSegments.splice(n,1),n--)}for(;this.totalStoredBytes>this.maxStorableBytes&&this.loadedSegments.length>1;){let n=null,o=-1;for(let a=0;an.start),s=null;if(i!==-1)for(let n=i;ne)break;if(t<=o.end){s=o;break}}if(!s)throw new Error(`No segment loaded for range [${e}, ${t}).`);return s.age=this.nextAge++,{view:s.view,offset:s.bytes.byteOffset+e-s.start}}};var $=class{constructor(e){this.reader=e}pos=0;readRange(e,t){let{view:i,offset:s}=this.reader.getViewAndOffset(e,t);return new Uint8Array(i.buffer,s,t-e)}readU8(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+1);return this.pos++,e.getUint8(t)}readU16(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+2);return this.pos+=2,e.getUint16(t,!1)}readU24(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+3);this.pos+=3;let i=e.getUint16(t,!1),s=e.getUint8(t+2);return i*256+s}readS32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getUint32(t,!1)}readI32(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+4);return this.pos+=4,e.getInt32(t,!1)}readU64(){let e=this.readU32(),t=this.readU32();return e*4294967296+t}readF64(){let{view:e,offset:t}=this.reader.getViewAndOffset(this.pos,this.pos+8);return this.pos+=8,e.getFloat64(t,!1)}readFixed_16_16(){return this.readS32()/65536}readFixed_2_30(){return this.readS32()/1073741824}readAscii(e){let{view:t,offset:i}=this.reader.getViewAndOffset(this.pos,this.pos+e);this.pos+=e;let s="";for(let n=0;ne.inputTrack)}async getMimeType(){await this.readMetadata();let e="video/mp4";if(this.tracks.length>0){let t=await Promise.all(this.tracks.map(s=>s.inputTrack.getCodecMimeType())),i=[...new Set(t)];e+=`; codecs="${i.join(", ")}"`}return e}readMetadata(){return this.metadataPromise??=(async()=>{let e=await this.isobmffReader.reader.source._getSize();for(;this.isobmffReader.posi.presentationTimestamp-s.presentationTimestamp),e.sampleTable}readContiguousBoxes(e){let t=this.isobmffReader.pos;for(;this.isobmffReader.pos-tl.every((f,g)=>f===c[g]));u===-1?s.rotation=0:s.rotation=90*u}break;case"mdhd":{let s=this.currentTrack;d(s);let n=this.isobmffReader.readU8();this.isobmffReader.pos+=3,n===0?(this.isobmffReader.pos+=8,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU32()):n===1&&(this.isobmffReader.pos+=16,s.timescale=this.isobmffReader.readU32(),s.durationInTimescale=this.isobmffReader.readU64())}break;case"hdlr":{let s=this.currentTrack;d(s),this.isobmffReader.pos+=8;let n=this.isobmffReader.readAscii(4);n==="vide"?s.info={type:"video",width:-1,height:-1,codec:null,codecDescription:null,colorSpace:null}:n==="soun"&&(s.info={type:"audio",numberOfChannels:-1,sampleRate:-1,codec:null,codecDescription:null})}break;case"stbl":{let s=this.currentTrack;d(s),s.sampleTableOffset=e,this.readContiguousBoxes(t.contentSize)}break;case"stsd":{let s=this.currentTrack;if(d(s),s.info===null||s.sampleTable)break;let n=this.isobmffReader.readU8();this.isobmffReader.pos+=3;let o=this.isobmffReader.readU32();for(let a=0;a0){if(u===1)this.isobmffReader.pos+=4*4;else if(u===2){this.isobmffReader.pos+=4,f=this.isobmffReader.readF64(),l=this.isobmffReader.readU32(),this.isobmffReader.pos+=4;let g=this.isobmffReader.readU32(),x=this.isobmffReader.readU32(),C=this.isobmffReader.readU32(),k=this.isobmffReader.readU32()}}s.info.numberOfChannels=l,s.info.sampleRate=f,this.readContiguousBoxes(e+c.totalSize-this.isobmffReader.pos)}}}break;case"avcC":{let s=this.currentTrack;d(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"hvcC":{let s=this.currentTrack;d(s&&s.info),s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+t.contentSize)}break;case"colr":{let s=this.currentTrack;if(d(s&&s.info?.type==="video"),this.isobmffReader.readAscii(4)!=="nclx")break;let o=this.isobmffReader.readU16(),a=this.isobmffReader.readU16(),c=this.isobmffReader.readU16(),u=!!(this.isobmffReader.readU8()&128);s.info.colorSpace={primaries:gt[o],transfer:Tt[a],matrix:xt[c],fullRange:u}}break;case"wave":t.totalSize>8&&this.readContiguousBoxes(t.contentSize);break;case"esds":{let s=this.currentTrack;d(s&&s.info),this.isobmffReader.pos+=4;let n=this.isobmffReader.readU8();d(n===3),this.isobmffReader.readIsomVariableInteger(),this.isobmffReader.pos+=2;let o=this.isobmffReader.readU8(),a=(o&128)!==0,c=(o&64)!==0,u=(o&32)!==0;if(a&&(this.isobmffReader.pos+=2),c){let C=this.isobmffReader.readU8();this.isobmffReader.pos+=C}u&&(this.isobmffReader.pos+=2);let l=this.isobmffReader.readU8();d(l===4),this.isobmffReader.readIsomVariableInteger();let f=this.isobmffReader.readU8();d(f===64),this.isobmffReader.pos+=12;let g=this.isobmffReader.readU8();d(g===5);let x=this.isobmffReader.readIsomVariableInteger();s.info.codecDescription=this.isobmffReader.readRange(this.isobmffReader.pos,this.isobmffReader.pos+x)}break;case"stts":{let s=this.currentTrack;if(d(s),!s.sampleTable)break;this.isobmffReader.pos+=4;let n=this.isobmffReader.readU32(),o=0,a=0;for(let c=0;c{let t=E(r.presentationTimestamps,e,i=>i.presentationTimestamp);return t===-1?-1:r.presentationTimestamps[t].sampleIndex},ni=(r,e)=>{let t=E(r.sampleTimingEntries,e,k=>k.startIndex),i=r.sampleTimingEntries[t];if(!i||i.startIndex+i.count<=e)return null;let n=i.startDecodeTimestamp+(e-i.startIndex)*i.delta,o=E(r.sampleCompositionTimeOffsets,e,k=>k.startIndex),a=r.sampleCompositionTimeOffsets[o];a&&(n+=a.offset);let c=r.sampleSizes[Math.min(e,r.sampleSizes.length-1)],u=E(r.sampleToChunk,e,k=>k.startSampleIndex),l=r.sampleToChunk[u];d(l);let f=l.startChunkIndex+Math.floor((e-l.startSampleIndex)/l.samplesPerChunk),g=r.chunkOffsets[f],x=0,C=g;if(r.sampleSizes.length===1)C+=c*(e-l.startSampleIndex),x+=c*l.samplesPerChunk;else{let k=l.startSampleIndex+(f-l.startChunkIndex)*l.samplesPerChunk;for(let S=k;Sk)!==-1:!0}},oi=(r,e)=>{if(!r.keySampleIndices)return e;let t=E(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t]??-1},ai=(r,e)=>{if(!r.keySampleIndices)return e+1;let t=E(r.keySampleIndices,e,i=>i);return r.keySampleIndices[t+1]??-1};var ze=class extends re{};var Be=class{},mt=class extends Be{async _canReadInput(e){if(await e._mainReader.source._getSize()<8)return!1;await e._mainReader.loadRange(4,8);let i=new $(e._mainReader);return i.pos=4,i.readAscii(4)==="ftyp"}_createDemuxer(e){return new Me(e)}},ft=class extends Be{async _canReadInput(){return!1}_createDemuxer(e){return new ze(e)}},Ue=new mt,ci=Ue,ui=Ue,ht=new ft,Yt=ht,di=ht,li=[Ue,Yt];var pt=class{_source;_formats;_mainReader;_demuxerPromise=null;_format=null;constructor(e){this._formats=e.formats,this._source=e.source,this._mainReader=new ie(e.source)}_getDemuxer(){return this._demuxerPromise??=(async()=>{for(let e of this._formats)if(await e._canReadInput(this))return this._format=e,e._createDemuxer(this);throw new Error("Input has an unrecognizable format.")})()}async getFormat(){return await this._getDemuxer(),d(this._format),this._format}async getDuration(){return(await this._getDemuxer()).getDuration()}async getTracks(){return(await this._getDemuxer()).getTracks()}async getVideoTracks(){return(await this.getTracks()).filter(t=>t.isVideoTrack())}async getPrimaryVideoTrack(){return(await this.getTracks()).find(t=>t.isVideoTrack())??null}async getAudioTracks(){return(await this.getTracks()).filter(t=>t.isAudioTrack())}async getPrimaryAudioTrack(){return(await this.getTracks()).find(t=>t.isAudioTrack())??null}async getMimeType(){return(await this._getDemuxer()).getMimeType()}};var De=class{constructor(e){this.videoTrack=e}getFirstChunk(){return this.videoTrack._backing.getFirstChunk()}getChunk(e){return this.videoTrack._backing.getChunk(e)}getNextChunk(e){return this.videoTrack._backing.getNextChunk(e)}getKeyChunk(e){return this.videoTrack._backing.getKeyChunk(e)}getNextKeyChunk(e){return this.videoTrack._backing.getNextKeyChunk(e)}async*chunks(e,t=1/0){let i=[],{promise:s,resolve:n}=N(),{promise:o,resolve:a}=N(),c=!1,u=[],l=()=>Math.max(2,u.length);(async()=>{let f=e??await this.getFirstChunk();for(;f&&!c&&!(f.timestamp/1e6>=t);){if(i.length>l()){({promise:o,resolve:a}=N()),await o;continue}i.push(f),n(),{promise:s,resolve:n}=N(),f=await this.getNextChunk(f)}c=!0,n()})();try{for(;;)if(i.length>0){yield i.shift();let f=performance.now();for(u.push(f);u.length>0&&f-u[0]>=1e3;)u.shift();a()}else if(!c)await s;else break}finally{c=!0,a()}}},bt=class{constructor(e){this.videoTrack=e}decoderConfig=null;async createDecoder(e){this.decoderConfig||(this.decoderConfig=await this.videoTrack.getDecoderConfig());let t=new VideoDecoder({output:e,error:i=>console.error(i)});return t.configure(this.decoderConfig),t}async getKeyFrame(e){let t=null,i=await this.createDecoder(n=>t=n),s=await this.videoTrack._backing.getKeyChunk(e);return s?(i.decode(s),await i.flush(),i.close(),t):null}async getFrame(e){let t=null,i=await this.createDecoder(a=>{a.timestamp/1e6<=e?(t?.close(),t=a):a.close()}),s=await this.videoTrack._backing.getKeyChunk(e);if(!s)return null;let n=await this.videoTrack._backing.getChunk(e);d(n),i.decode(s);let o=s;for(;o!==n;){let a=await this.videoTrack._backing.getNextChunk(o);d(a),o=a,i.decode(a),i.decodeQueueSize>=10&&await new Promise(c=>i.addEventListener("dequeue",c,{once:!0}))}return await i.flush(),i.close(),t}async*frames(e=0,t=1/0){let i=[],s=!1,n=null,{promise:o,resolve:a}=N(),c=!1,u=await this.createDecoder(g=>{let x=g.timestamp/1e6;if(x>=t&&(c=!0),c){g.close();return}n&&(x>e?(i.push(n),s=!0):n.close()),x>=e&&(i.push(g),s=!0),n=s?null:g,i.length>0&&(a(),{promise:o,resolve:a}=N())}),l=await this.videoTrack._backing.getKeyChunk(e)??await this.videoTrack._backing.getFirstChunk();if(!l)return;let f=!1;(async()=>{let g=l,x=1/0;if(t<1/0){let S=await this.videoTrack._backing.getChunk(t),P=S?S.type==="key"&&S.timestamp/1e6===t?S:await this.videoTrack._backing.getNextKeyChunk(S):null;P&&(x=P.timestamp/1e6)}let k=new De(this.videoTrack).chunks(l,x);for(await k.next();g&&!c;){u.decode(g),u.decodeQueueSize>=10&&await new Promise(P=>u.addEventListener("dequeue",P,{once:!0}));let S=await k.next();if(S.done)break;g=S.value}await k.return(),await u.flush(),u.close(),!s&&n&&i.push(n),f=!0,a()})();try{for(;;)if(i.length>0)yield i.shift();else if(!f)await o;else break}finally{c=!0}}};export{li as ALL_FORMATS,Y as AUDIO_CODECS,ct as ArrayBufferSource,ce as ArrayBufferTarget,st as AudioBufferSource,it as AudioDataSource,R as AudioSource,ut as BlobSource,et as CanvasSource,rt as EncodedAudioChunkSource,De as EncodedVideoChunkDrain,Ze as EncodedVideoChunkSource,Ue as ISOBMFF,pt as Input,ht as MATROSKA,Yt as MKV,ui as MOV,ci as MP4,ee as MediaSource,nt as MediaStreamAudioTrackSource,tt as MediaStreamVideoTrackSource,Oe as MkvOutputFormat,Ye as Mp4OutputFormat,at as Output,Q as OutputFormat,ye as SUBTITLE_CODECS,fe as Source,Ke as StreamTarget,te as SubtitleSource,L as Target,ot as TextSubtitleSource,G as VIDEO_CODECS,bt as VideoFrameDrain,Je as VideoFrameSource,V as VideoSource,di as WEBM,J as WebMOutputFormat}; diff --git a/dist/metamuxer.mjs b/dist/metamuxer.mjs index 8f131ef..3c08662 100644 --- a/dist/metamuxer.mjs +++ b/dist/metamuxer.mjs @@ -162,6 +162,12 @@ var promiseWithResolvers = () => { }); return { promise, resolve, reject }; }; +var removeItem = (arr, item) => { + const index = arr.indexOf(item); + if (index !== -1) { + arr.splice(index, 1); + } +}; // src/subtitles.ts var cueBlockHeaderRegex = /(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g; @@ -3959,6 +3965,12 @@ var Output = class { // src/source.ts var Source = class { + /** @internal */ + _sizePromise = null; + /** @internal */ + _getSize() { + return this._sizePromise ??= this._retrieveSize(); + } }; var ArrayBufferSource = class extends Source { constructor(buffer) { @@ -3970,7 +3982,7 @@ var ArrayBufferSource = class extends Source { return new Uint8Array(this.buffer, start, end - start); } /** @internal */ - async _getSize() { + async _retrieveSize() { return this.buffer.byteLength; } }; @@ -3986,7 +3998,7 @@ var BlobSource = class extends Source { return new Uint8Array(buffer); } /** @internal */ - async _getSize() { + async _retrieveSize() { return this.blob.size; } }; @@ -4071,6 +4083,103 @@ var InputAudioTrack = class extends InputTrack { } }; +// src/reader.ts +var PAGE_SIZE = 4096; +var Reader = class { + constructor(source, maxStorableBytes = Infinity) { + this.source = source; + this.maxStorableBytes = maxStorableBytes; + } + loadedSegments = []; + loadingSegments = []; + sourceSizePromise = null; + nextAge = 0; + totalStoredBytes = 0; + async loadRange(start, end) { + const alignedStart = Math.floor(start / PAGE_SIZE) * PAGE_SIZE; + let alignedEnd = Math.ceil(end / PAGE_SIZE) * PAGE_SIZE; + alignedEnd = Math.min(alignedEnd, await this.source._getSize()); + const matchingLoadingSegment = this.loadingSegments.find((x) => x.start <= alignedStart && x.end >= alignedEnd); + if (matchingLoadingSegment) { + await matchingLoadingSegment.promise; + return; + } + const encasingSegmentExists = this.loadedSegments.some((x) => x.start <= alignedStart && x.end >= alignedEnd); + if (encasingSegmentExists) { + return; + } + const bytesPromise = this.source._read(alignedStart, alignedEnd); + const loadingSegment = { start: alignedStart, end: alignedEnd, promise: bytesPromise }; + this.loadingSegments.push(loadingSegment); + const bytes2 = await bytesPromise; + removeItem(this.loadingSegments, loadingSegment); + this.insertIntoLoadedSegments(alignedStart, bytes2); + } + insertIntoLoadedSegments(start, bytes2) { + const segment = { + start, + end: start + bytes2.byteLength, + bytes: bytes2, + view: new DataView(bytes2.buffer), + age: this.nextAge++ + }; + let index = binarySearchLessOrEqual(this.loadedSegments, start, (x) => x.start); + if (index === -1 || this.loadedSegments[index].start < segment.start) { + index++; + } + this.loadedSegments.splice(index, 0, segment); + this.totalStoredBytes += bytes2.byteLength; + for (let i = index + 1; i < this.loadedSegments.length; i++) { + const otherSegment = this.loadedSegments[i]; + if (otherSegment.start >= segment.end) { + break; + } + if (segment.start <= otherSegment.start && otherSegment.end <= segment.end) { + this.loadedSegments.splice(i, 1); + i--; + } + } + while (this.totalStoredBytes > this.maxStorableBytes && this.loadedSegments.length > 1) { + let oldestSegment = null; + let oldestSegmentIndex = -1; + for (let i = 0; i < this.loadedSegments.length; i++) { + const candidate = this.loadedSegments[i]; + if (!oldestSegment || candidate.age < oldestSegment.age) { + oldestSegment = candidate; + oldestSegmentIndex = i; + } + } + assert(oldestSegment); + this.totalStoredBytes -= oldestSegment.bytes.byteLength; + this.loadedSegments.splice(oldestSegmentIndex, 1); + } + } + getViewAndOffset(start, end) { + const startIndex = binarySearchLessOrEqual(this.loadedSegments, start, (x) => x.start); + let segment = null; + if (startIndex !== -1) { + for (let i = startIndex; i < this.loadedSegments.length; i++) { + const candidate = this.loadedSegments[i]; + if (candidate.start > start) { + break; + } + if (end <= candidate.end) { + segment = candidate; + break; + } + } + } + if (!segment) { + throw new Error(`No segment loaded for range [${start}, ${end}).`); + } + segment.age = this.nextAge++; + return { + view: segment.view, + offset: segment.bytes.byteOffset + start - segment.start + }; + } +}; + // src/isobmff/isobmff-reader.ts var IsobmffReader = class { constructor(reader) { @@ -4172,9 +4281,11 @@ var IsobmffDemuxer = class extends Demuxer { metadataPromise = null; movieTimescale = -1; movieDurationInTimescale = -1; + chunkReader; constructor(input) { super(input); - this.isobmffReader = new IsobmffReader(input._reader); + this.isobmffReader = new IsobmffReader(input._mainReader); + this.chunkReader = new IsobmffReader(new Reader(input._source, 64 * 2 ** 20)); } async getDuration() { await this.readMetadata(); @@ -4199,7 +4310,7 @@ var IsobmffDemuxer = class extends Demuxer { } readMetadata() { return this.metadataPromise ??= (async () => { - const sourceSize = await this.isobmffReader.reader.getSourceSize(); + const sourceSize = await this.isobmffReader.reader.source._getSize(); while (this.isobmffReader.pos < sourceSize) { await this.isobmffReader.reader.loadRange(this.isobmffReader.pos, this.isobmffReader.pos + 16); const startPos = this.isobmffReader.pos; @@ -4775,9 +4886,13 @@ var IsobmffVideoTrackBacking = class extends IsobmffTrackBacking { if (!sampleInfo) { return null; } - const data = await this.internalTrack.demuxer.isobmffReader.reader.source._read( - sampleInfo.byteOffset, - sampleInfo.byteOffset + sampleInfo.byteSize + await this.internalTrack.demuxer.chunkReader.reader.loadRange( + sampleInfo.chunkOffset, + sampleInfo.chunkOffset + sampleInfo.chunkSize + ); + const data = this.internalTrack.demuxer.chunkReader.readRange( + sampleInfo.sampleOffset, + sampleInfo.sampleOffset + sampleInfo.sampleSize ); const chunk = new EncodedVideoChunk({ data, @@ -4878,20 +4993,28 @@ var getSampleInfo = (sampleTable, sampleIndex) => { assert(chunkEntry); const chunkIndex = chunkEntry.startChunkIndex + Math.floor((sampleIndex - chunkEntry.startSampleIndex) / chunkEntry.samplesPerChunk); const chunkOffset = sampleTable.chunkOffsets[chunkIndex]; + let chunkSize = 0; let sampleOffset = chunkOffset; if (sampleTable.sampleSizes.length === 1) { sampleOffset += sampleSize * (sampleIndex - chunkEntry.startSampleIndex); + chunkSize += sampleSize * chunkEntry.samplesPerChunk; } else { const startSampleIndex = chunkEntry.startSampleIndex + (chunkIndex - chunkEntry.startChunkIndex) * chunkEntry.samplesPerChunk; - for (let i = startSampleIndex; i < sampleIndex; i++) { - sampleOffset += sampleTable.sampleSizes[i]; + for (let i = startSampleIndex; i < startSampleIndex + chunkEntry.samplesPerChunk; i++) { + const sampleSize2 = sampleTable.sampleSizes[i]; + if (i < sampleIndex) { + sampleOffset += sampleSize2; + } + chunkSize += sampleSize2; } } return { presentationTimestamp, duration: timingEntry.delta, - byteOffset: sampleOffset, - byteSize: sampleSize, + sampleOffset, + sampleSize, + chunkOffset, + chunkSize, isKeyFrame: sampleTable.keySampleIndices ? binarySearchExact(sampleTable.keySampleIndices, sampleIndex, (x) => x) !== -1 : true }; }; @@ -4920,12 +5043,12 @@ var InputFormat = class { var IsobmffInputFormat = class extends InputFormat { /** @internal */ async _canReadInput(input) { - const sourceSize = await input._reader.getSourceSize(); + const sourceSize = await input._mainReader.source._getSize(); if (sourceSize < 8) { return false; } - await input._reader.loadRange(4, 8); - const isobmffReader = new IsobmffReader(input._reader); + await input._mainReader.loadRange(4, 8); + const isobmffReader = new IsobmffReader(input._mainReader); isobmffReader.pos = 4; const fourCc = isobmffReader.readAscii(4); return fourCc === "ftyp"; @@ -4951,106 +5074,22 @@ var MKV = MATROSKA; var WEBM = MATROSKA; var ALL_FORMATS = [ISOBMFF, MKV]; -// src/reader.ts -var PAGE_SIZE = 4096; -var Reader = class { - constructor(source) { - this.source = source; - } - loadedSegments = []; - sourceSizePromise = null; - getSourceSize() { - if (this.sourceSizePromise) { - return this.sourceSizePromise; - } else { - return this.sourceSizePromise = this.source._getSize(); - } - } - async loadRange(start, end) { - let alignedStart = Math.floor(start / PAGE_SIZE) * PAGE_SIZE; - let alignedEnd = Math.ceil(end / PAGE_SIZE) * PAGE_SIZE; - alignedEnd = Math.min(alignedEnd, await this.getSourceSize()); - const thing = this.loadedSegments.find((x) => x.start <= alignedStart); - if (thing) { - alignedStart = Math.max(alignedStart, thing.end); - } - const thing2 = this.loadedSegments.find((x) => x.end >= alignedEnd); - if (thing2) { - alignedEnd = Math.min(alignedEnd, thing2.start); - } - if (alignedStart >= alignedEnd) { - return; - } - const bytes2 = await this.source._read(alignedStart, alignedEnd); - this.insertIntoLoadedSegments(alignedStart, bytes2); - } - insertIntoLoadedSegments(start, bytes2) { - const segment = { - start, - end: start + bytes2.byteLength, - bytes: bytes2, - view: new DataView(bytes2.buffer) - }; - let index = this.loadedSegments.findLastIndex((x) => x.start <= start); - this.loadedSegments.splice(index + 1, 0, segment); - if (index === -1 || this.loadedSegments[index].end < segment.start) { - index++; - } - const mergeSectionStartIndex = index; - const mergeSectionStart = this.loadedSegments[mergeSectionStartIndex].start; - let mergeSectionEndIndex = index; - let mergeSectionEnd = this.loadedSegments[mergeSectionEndIndex].end; - while (this.loadedSegments.length - 1 > mergeSectionEndIndex && this.loadedSegments[mergeSectionEndIndex + 1].start <= mergeSectionEnd) { - mergeSectionEndIndex++; - mergeSectionEnd = Math.max(mergeSectionEnd, this.loadedSegments[mergeSectionEndIndex].end); - } - if (mergeSectionStartIndex === mergeSectionEndIndex) { - return; - } - for (let i = mergeSectionStartIndex; i <= mergeSectionEndIndex; i++) { - const segment2 = this.loadedSegments[i]; - const coversEntireMergeSection = segment2.start === mergeSectionStart && segment2.end === mergeSectionEnd; - if (coversEntireMergeSection) { - this.loadedSegments.splice(i + 1, mergeSectionEndIndex - i); - this.loadedSegments.splice(mergeSectionStartIndex, i - mergeSectionStartIndex); - return; - } - } - const unifiedBytes = new Uint8Array(mergeSectionEnd - mergeSectionStart); - for (let i = mergeSectionStartIndex; i <= mergeSectionEndIndex; i++) { - const segment2 = this.loadedSegments[i]; - unifiedBytes.set(segment2.bytes, segment2.start - mergeSectionStart); - } - this.loadedSegments.splice(mergeSectionStartIndex + 1, mergeSectionEndIndex - mergeSectionStartIndex); - this.loadedSegments[mergeSectionStartIndex].end = mergeSectionEnd; - this.loadedSegments[mergeSectionStartIndex].bytes = unifiedBytes; - this.loadedSegments[mergeSectionStartIndex].view = new DataView(unifiedBytes.buffer); - } - getViewAndOffset(start, end) { - const segment = this.loadedSegments.find((x) => x.start <= start && end <= x.end); - if (!segment) { - throw new Error(`No segment loaded for range [${start}, ${end}).`); - } - return { - view: segment.view, - offset: segment.bytes.byteOffset + start - segment.start - }; - } -}; - // src/input.ts var Input = class { + /** @internal */ + _source; /** @internal */ _formats; /** @internal */ - _reader; + _mainReader; /** @internal */ _demuxerPromise = null; /** @internal */ _format = null; constructor(options) { this._formats = options.formats; - this._reader = new Reader(options.source); + this._source = options.source; + this._mainReader = new Reader(options.source); } /** @internal */ _getDemuxer() { @@ -5120,11 +5159,51 @@ var EncodedVideoChunkDrain = class { getNextKeyChunk(chunk) { return this.videoTrack._backing.getNextKeyChunk(chunk); } - async *chunks(startTimestamp = 0) { - let chunk = await this.getChunk(startTimestamp); - while (chunk) { - yield chunk; - chunk = await this.getNextChunk(chunk); + async *chunks(startChunk, endTimestamp = Infinity) { + const chunkQueue = []; + let { promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); + let { promise: queueDequeue, resolve: onQueueDequeue } = promiseWithResolvers(); + let ended = false; + const timestamps = []; + const maxQueueSize = () => Math.max(2, timestamps.length); + void (async () => { + let chunk = startChunk ?? await this.getFirstChunk(); + while (chunk && !ended) { + if (chunk.timestamp / 1e6 >= endTimestamp) { + break; + } + if (chunkQueue.length > maxQueueSize()) { + ({ promise: queueDequeue, resolve: onQueueDequeue } = promiseWithResolvers()); + await queueDequeue; + continue; + } + chunkQueue.push(chunk); + onQueueNotEmpty(); + ({ promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); + chunk = await this.getNextChunk(chunk); + } + ended = true; + onQueueNotEmpty(); + })(); + try { + while (true) { + if (chunkQueue.length > 0) { + yield chunkQueue.shift(); + const now = performance.now(); + timestamps.push(now); + while (timestamps.length > 0 && now - timestamps[0] >= 1e3) { + timestamps.shift(); + } + onQueueDequeue(); + } else if (!ended) { + await queueNotEmpty; + } else { + break; + } + } + } finally { + ended = true; + onQueueDequeue(); } } }; @@ -5187,18 +5266,21 @@ var VideoFrameDrain = class { decoder.close(); return result; } - async *frames(startTimestamp = 0) { + async *frames(startTimestamp = 0, endTimestamp = Infinity) { const frameQueue = []; let firstFrameQueued = false; let lastFrame = null; - let { promise: queueNonEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); + let { promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); let ended = false; const decoder = await this.createDecoder((frame) => { + const frameTimestamp = frame.timestamp / 1e6; + if (frameTimestamp >= endTimestamp) { + ended = true; + } if (ended) { frame.close(); return; } - const frameTimestamp = frame.timestamp / 1e6; if (lastFrame) { if (frameTimestamp > startTimestamp) { frameQueue.push(lastFrame); @@ -5214,26 +5296,44 @@ var VideoFrameDrain = class { lastFrame = firstFrameQueued ? null : frame; if (frameQueue.length > 0) { onQueueNotEmpty(); - ({ promise: queueNonEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); + ({ promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); } }); - const keyChunk = await this.videoTrack._backing.getKeyChunk(startTimestamp); + const keyChunk = await this.videoTrack._backing.getKeyChunk(startTimestamp) ?? await this.videoTrack._backing.getFirstChunk(); if (!keyChunk) { return; } let decoderIsFlushed = false; void (async () => { let currentChunk = keyChunk; + let chunksEndTimestamp = Infinity; + if (endTimestamp < Infinity) { + const endFrame = await this.videoTrack._backing.getChunk(endTimestamp); + const endKeyFrame = !endFrame ? null : endFrame.type === "key" && endFrame.timestamp / 1e6 === endTimestamp ? endFrame : await this.videoTrack._backing.getNextKeyChunk(endFrame); + if (endKeyFrame) { + chunksEndTimestamp = endKeyFrame.timestamp / 1e6; + } + } + const chunkDrain = new EncodedVideoChunkDrain(this.videoTrack); + const chunks = chunkDrain.chunks(keyChunk, chunksEndTimestamp); + await chunks.next(); while (currentChunk && !ended) { decoder.decode(currentChunk); if (decoder.decodeQueueSize >= 10) { await new Promise((resolve) => decoder.addEventListener("dequeue", resolve, { once: true })); } - const nextChunk = await this.videoTrack._backing.getNextChunk(currentChunk); - currentChunk = nextChunk; + const chunkResult = await chunks.next(); + if (chunkResult.done) { + break; + } + currentChunk = chunkResult.value; } + await chunks.return(); await decoder.flush(); decoder.close(); + if (!firstFrameQueued && lastFrame) { + frameQueue.push(lastFrame); + } decoderIsFlushed = true; onQueueNotEmpty(); })(); @@ -5242,7 +5342,7 @@ var VideoFrameDrain = class { if (frameQueue.length > 0) { yield frameQueue.shift(); } else if (!decoderIsFlushed) { - await queueNonEmpty; + await queueNotEmpty; } else { break; } diff --git a/src/input-format.ts b/src/input-format.ts index 9bd030f..ef32456 100644 --- a/src/input-format.ts +++ b/src/input-format.ts @@ -15,14 +15,14 @@ export abstract class InputFormat { class IsobmffInputFormat extends InputFormat { /** @internal */ override async _canReadInput(input: Input) { - const sourceSize = await input._reader.getSourceSize(); + const sourceSize = await input._mainReader.source._getSize(); if (sourceSize < 8) { return false; } - await input._reader.loadRange(4, 8); + await input._mainReader.loadRange(4, 8); - const isobmffReader = new IsobmffReader(input._reader); + const isobmffReader = new IsobmffReader(input._mainReader); isobmffReader.pos = 4; const fourCc = isobmffReader.readAscii(4); diff --git a/src/input.ts b/src/input.ts index ea62844..9ab177c 100644 --- a/src/input.ts +++ b/src/input.ts @@ -10,10 +10,12 @@ export type InputOptions = { }; export class Input { + /** @internal */ + _source: Source; /** @internal */ _formats: InputFormat[]; /** @internal */ - _reader: Reader; + _mainReader: Reader; /** @internal */ _demuxerPromise: Promise | null = null; /** @internal */ @@ -21,7 +23,8 @@ export class Input { constructor(options: InputOptions) { this._formats = options.formats; - this._reader = new Reader(options.source); + this._source = options.source; + this._mainReader = new Reader(options.source); } /** @internal */ diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts index 8baa7d2..ff194f5 100644 --- a/src/isobmff/isobmff-demuxer.ts +++ b/src/isobmff/isobmff-demuxer.ts @@ -18,6 +18,7 @@ import { binarySearchLessOrEqual, binarySearchExact, } from '../misc'; +import { Reader } from '../reader'; import { IsobmffReader } from './isobmff-reader'; type InternalTrack = { @@ -86,17 +87,20 @@ type SampleToChunkEntry = { const knownMatrixes = [rotationMatrix(0), rotationMatrix(90), rotationMatrix(180), rotationMatrix(270)]; export class IsobmffDemuxer extends Demuxer { - isobmffReader: IsobmffReader; + private isobmffReader: IsobmffReader; private currentTrack: InternalTrack | null = null; private tracks: InternalTrack[] = []; private metadataPromise: Promise | null = null; private movieTimescale = -1; private movieDurationInTimescale = -1; + chunkReader: IsobmffReader; + constructor(input: Input) { super(input); - this.isobmffReader = new IsobmffReader(input._reader); + this.isobmffReader = new IsobmffReader(input._mainReader); + this.chunkReader = new IsobmffReader(new Reader(input._source, 64 * 2 ** 20)); // Max 64 MiB of stored chunks } override async getDuration() { @@ -131,7 +135,7 @@ export class IsobmffDemuxer extends Demuxer { readMetadata() { return this.metadataPromise ??= (async () => { - const sourceSize = await this.isobmffReader.reader.getSourceSize(); + const sourceSize = await this.isobmffReader.reader.source._getSize(); while (this.isobmffReader.pos < sourceSize) { await this.isobmffReader.reader.loadRange(this.isobmffReader.pos, this.isobmffReader.pos + 16); @@ -832,9 +836,13 @@ class IsobmffVideoTrackBacking extends IsobmffTrackBacking implements InputVideo return null; } - const data = await this.internalTrack.demuxer.isobmffReader.reader.source._read( - sampleInfo.byteOffset, - sampleInfo.byteOffset + sampleInfo.byteSize, + await this.internalTrack.demuxer.chunkReader.reader.loadRange( + sampleInfo.chunkOffset, + sampleInfo.chunkOffset + sampleInfo.chunkSize, + ); + const data = this.internalTrack.demuxer.chunkReader.readRange( + sampleInfo.sampleOffset, + sampleInfo.sampleOffset + sampleInfo.sampleSize, ); const chunk = new EncodedVideoChunk({ @@ -934,8 +942,10 @@ const getSampleIndexForTimestamp = (sampleTable: SampleTable, timescaleUnits: nu type SampleInfo = { presentationTimestamp: number; duration: number; - byteOffset: number; - byteSize: number; + sampleOffset: number; + sampleSize: number; + chunkOffset: number; + chunkSize: number; isKeyFrame: boolean; }; @@ -968,22 +978,33 @@ const getSampleInfo = (sampleTable: SampleTable, sampleIndex: number): SampleInf + Math.floor((sampleIndex - chunkEntry.startSampleIndex) / chunkEntry.samplesPerChunk); const chunkOffset = sampleTable.chunkOffsets[chunkIndex]!; + let chunkSize = 0; + let sampleOffset = chunkOffset; if (sampleTable.sampleSizes.length === 1) { sampleOffset += sampleSize * (sampleIndex - chunkEntry.startSampleIndex); + chunkSize += sampleSize * chunkEntry.samplesPerChunk; } else { const startSampleIndex = chunkEntry.startSampleIndex + (chunkIndex - chunkEntry.startChunkIndex) * chunkEntry.samplesPerChunk; - for (let i = startSampleIndex; i < sampleIndex; i++) { - sampleOffset += sampleTable.sampleSizes[i]!; + + for (let i = startSampleIndex; i < startSampleIndex + chunkEntry.samplesPerChunk; i++) { + const sampleSize = sampleTable.sampleSizes[i]!; + + if (i < sampleIndex) { + sampleOffset += sampleSize; + } + chunkSize += sampleSize; } } return { presentationTimestamp, duration: timingEntry.delta, - byteOffset: sampleOffset, - byteSize: sampleSize, + sampleOffset, + sampleSize, + chunkOffset, + chunkSize, isKeyFrame: sampleTable.keySampleIndices ? binarySearchExact(sampleTable.keySampleIndices, sampleIndex, x => x) !== -1 : true, diff --git a/src/media-drain.ts b/src/media-drain.ts index fb9cc4d..5477ffd 100644 --- a/src/media-drain.ts +++ b/src/media-drain.ts @@ -24,11 +24,65 @@ export class EncodedVideoChunkDrain { return this.videoTrack._backing.getNextKeyChunk(chunk); } - async* chunks(startTimestamp = 0) { - let chunk = await this.getChunk(startTimestamp); // Not necessarily correct if there is no chunk at timestamp 0 - while (chunk) { - yield chunk; - chunk = await this.getNextChunk(chunk); + async* chunks(startChunk?: EncodedVideoChunk, endTimestamp = Infinity) { + const chunkQueue: EncodedVideoChunk[] = []; + + let { promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); + let { promise: queueDequeue, resolve: onQueueDequeue } = promiseWithResolvers(); + let ended = false; + + const timestamps: number[] = []; + // The queue should always be big enough to hold 1 second worth of chunks + const maxQueueSize = () => Math.max(2, timestamps.length); + + // The following is the "pump" process that keeps pumping chunks into the queue + void (async () => { + let chunk = startChunk ?? await this.getFirstChunk(); + + while (chunk && !ended) { + if (chunk.timestamp / 1e6 >= endTimestamp) { + break; + } + + if (chunkQueue.length > maxQueueSize()) { + ({ promise: queueDequeue, resolve: onQueueDequeue } = promiseWithResolvers()); + await queueDequeue; + continue; + } + + chunkQueue.push(chunk); + + onQueueNotEmpty(); + ({ promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); + + chunk = await this.getNextChunk(chunk); + } + + ended = true; + onQueueNotEmpty(); + })(); + + try { + while (true) { + if (chunkQueue.length > 0) { + yield chunkQueue.shift()!; + const now = performance.now(); + timestamps.push(now); + + while (timestamps.length > 0 && now - timestamps[0]! >= 1000) { + timestamps.shift(); + } + + onQueueDequeue(); + } else if (!ended) { + await queueNotEmpty; + } else { + break; + } + } + } finally { + ended = true; + onQueueDequeue(); } } } @@ -109,23 +163,31 @@ export class VideoFrameDrain { return result; } - async* frames(startTimestamp = 0) { + async* frames(startTimestamp = 0, endTimestamp = Infinity) { const frameQueue: VideoFrame[] = []; let firstFrameQueued = false; let lastFrame: VideoFrame | null = null; - let { promise: queueNonEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); + let { promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers(); let ended = false; const decoder = await this.createDecoder((frame) => { + const frameTimestamp = frame.timestamp / 1e6; + + if (frameTimestamp >= endTimestamp) { + ended = true; + } + if (ended) { frame.close(); return; } - const frameTimestamp = frame.timestamp / 1e6; - if (lastFrame) { if (frameTimestamp > startTimestamp) { + // We don't know ahead of time what the first frame is. This is because the first frame is the last + // frame whose timestamp is less than or equal to the start timestamp. Therefore we need to wait + // for the first frame after the start timestamp, and then we'll know that the previous frame was + // the first frame. frameQueue.push(lastFrame); firstFrameQueued = true; } else { @@ -142,11 +204,12 @@ export class VideoFrameDrain { if (frameQueue.length > 0) { onQueueNotEmpty(); - ({ promise: queueNonEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); + ({ promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); } }); - const keyChunk = await this.videoTrack._backing.getKeyChunk(startTimestamp); + const keyChunk = await this.videoTrack._backing.getKeyChunk(startTimestamp) + ?? await this.videoTrack._backing.getFirstChunk(); if (!keyChunk) { return; } @@ -157,6 +220,28 @@ export class VideoFrameDrain { void (async () => { let currentChunk: EncodedVideoChunk | null = keyChunk; + let chunksEndTimestamp = Infinity; + if (endTimestamp < Infinity) { + // When an end timestamp is set, we cannot simply use that for the chunk iterator due to out-of-order + // frames (B-frames). Instead, we'll need to keep decoding chunks until we get a frame that exceeds + // this end time. However, we can still put a bound on it: Since key frames are by definition never + // out of order, we can stop at the first key frame after the end timestamp. + const endFrame = await this.videoTrack._backing.getChunk(endTimestamp); + const endKeyFrame = !endFrame + ? null + : endFrame.type === 'key' && endFrame.timestamp / 1e6 === endTimestamp + ? endFrame + : await this.videoTrack._backing.getNextKeyChunk(endFrame); + + if (endKeyFrame) { + chunksEndTimestamp = endKeyFrame.timestamp / 1e6; + } + } + + const chunkDrain = new EncodedVideoChunkDrain(this.videoTrack); + const chunks = chunkDrain.chunks(keyChunk, chunksEndTimestamp); + await chunks.next(); + while (currentChunk && !ended) { decoder.decode(currentChunk); @@ -164,13 +249,23 @@ export class VideoFrameDrain { await new Promise(resolve => decoder.addEventListener('dequeue', resolve, { once: true })); } - const nextChunk = await this.videoTrack._backing.getNextChunk(currentChunk); - currentChunk = nextChunk; + const chunkResult = await chunks.next(); + if (chunkResult.done) { + break; + } + + currentChunk = chunkResult.value; } + await chunks.return(); + await decoder.flush(); decoder.close(); + if (!firstFrameQueued && lastFrame) { + frameQueue.push(lastFrame); + } + decoderIsFlushed = true; onQueueNotEmpty(); // To unstuck the generator })(); @@ -180,7 +275,7 @@ export class VideoFrameDrain { if (frameQueue.length > 0) { yield frameQueue.shift()!; } else if (!decoderIsFlushed) { - await queueNonEmpty; + await queueNotEmpty; } else { break; } diff --git a/src/misc.ts b/src/misc.ts index 21a498a..34a8b34 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -204,3 +204,10 @@ export const promiseWithResolvers = () => { return { promise, resolve: resolve!, reject: reject! }; }; + +export const removeItem = (arr: T[], item: T) => { + const index = arr.indexOf(item); + if (index !== -1) { + arr.splice(index, 1); + } +}; diff --git a/src/reader.ts b/src/reader.ts index 5d3265c..783c334 100644 --- a/src/reader.ts +++ b/src/reader.ts @@ -1,3 +1,4 @@ +import { assert, binarySearchLessOrEqual, removeItem } from './misc'; import { Source } from './source'; const PAGE_SIZE = 4096; @@ -7,126 +8,129 @@ type ReadSegment = { end: number; bytes: Uint8Array; view: DataView; + age: number; +}; + +type LoadingSegment = { + start: number; + end: number; + promise: Promise; }; export class Reader { loadedSegments: ReadSegment[] = []; + loadingSegments: LoadingSegment[] = []; sourceSizePromise: Promise | null = null; + nextAge = 0; + totalStoredBytes = 0; - constructor(public source: Source) {} - - getSourceSize() { - if (this.sourceSizePromise) { - return this.sourceSizePromise; - } else { - return this.sourceSizePromise = this.source._getSize(); - } - } + constructor(public source: Source, public maxStorableBytes = Infinity) {} async loadRange(start: number, end: number) { // Read rounded to the nearest page - let alignedStart = Math.floor(start / PAGE_SIZE) * PAGE_SIZE; + const alignedStart = Math.floor(start / PAGE_SIZE) * PAGE_SIZE; let alignedEnd = Math.ceil(end / PAGE_SIZE) * PAGE_SIZE; - alignedEnd = Math.min(alignedEnd, await this.getSourceSize()); + alignedEnd = Math.min(alignedEnd, await this.source._getSize()); - const thing = this.loadedSegments.find(x => x.start <= alignedStart); - if (thing) { - alignedStart = Math.max(alignedStart, thing.end); + const matchingLoadingSegment = this.loadingSegments.find(x => x.start <= alignedStart && x.end >= alignedEnd); + if (matchingLoadingSegment) { + // Simply wait for the existing promise to finish to avoid loading the same range twice + await matchingLoadingSegment.promise; + return; } - const thing2 = this.loadedSegments.find(x => x.end >= alignedEnd); - if (thing2) { - alignedEnd = Math.min(alignedEnd, thing2.start); - } - - if (alignedStart >= alignedEnd) { + const encasingSegmentExists = this.loadedSegments.some(x => x.start <= alignedStart && x.end >= alignedEnd); + if (encasingSegmentExists) { // Nothing to load return; } - const bytes = await this.source._read(alignedStart, alignedEnd); + const bytesPromise = this.source._read(alignedStart, alignedEnd); + const loadingSegment: LoadingSegment = { start: alignedStart, end: alignedEnd, promise: bytesPromise }; + this.loadingSegments.push(loadingSegment); + + const bytes = await bytesPromise; + removeItem(this.loadingSegments, loadingSegment); + this.insertIntoLoadedSegments(alignedStart, bytes); } private insertIntoLoadedSegments(start: number, bytes: Uint8Array) { - /* - let index = -1; - let low = 0; - let high = this.loadedSegments.length - 1; - - while (low <= high) { - let mid = Math.floor(low + (high - low + 1) / 2); - let midVal = this.loadedSegments[mid].start; - - if (midVal >= start) { - index = mid; - high = mid - 1; - } else { - low = mid + 1; - } - } - */ - const segment: ReadSegment = { start, end: start + bytes.byteLength, bytes, view: new DataView(bytes.buffer), + age: this.nextAge++, }; - let index = this.loadedSegments.findLastIndex(x => x.start <= start); - this.loadedSegments.splice(index + 1, 0, segment); - if (index === -1 || this.loadedSegments[index]!.end < segment.start) { + let index = binarySearchLessOrEqual(this.loadedSegments, start, x => x.start); + if (index === -1 || this.loadedSegments[index]!.start < segment.start) { index++; } - const mergeSectionStartIndex = index; - const mergeSectionStart = this.loadedSegments[mergeSectionStartIndex]!.start; - let mergeSectionEndIndex = index; - let mergeSectionEnd = this.loadedSegments[mergeSectionEndIndex]!.end; + // Insert the segment at the right place so that the array remains sorted by start offset + this.loadedSegments.splice(index, 0, segment); + this.totalStoredBytes += bytes.byteLength; - while ( - this.loadedSegments.length - 1 > mergeSectionEndIndex - && this.loadedSegments[mergeSectionEndIndex + 1]!.start <= mergeSectionEnd - ) { - mergeSectionEndIndex++; - mergeSectionEnd = Math.max(mergeSectionEnd, this.loadedSegments[mergeSectionEndIndex]!.end); - } + // Remove all other segments from the array that are completely covered by the newly-inserted segment + for (let i = index + 1; i < this.loadedSegments.length; i++) { + const otherSegment = this.loadedSegments[i]!; + if (otherSegment.start >= segment.end) { + break; + } - if (mergeSectionStartIndex === mergeSectionEndIndex) { - return; - } - - for (let i = mergeSectionStartIndex; i <= mergeSectionEndIndex; i++) { - const segment = this.loadedSegments[i]!; - const coversEntireMergeSection = segment.start === mergeSectionStart && segment.end === mergeSectionEnd; - - if (coversEntireMergeSection) { - this.loadedSegments.splice(i + 1, mergeSectionEndIndex - i); - this.loadedSegments.splice(mergeSectionStartIndex, i - mergeSectionStartIndex); - - return; + if (segment.start <= otherSegment.start && otherSegment.end <= segment.end) { + this.loadedSegments.splice(i, 1); + i--; } } - const unifiedBytes = new Uint8Array(mergeSectionEnd - mergeSectionStart); - for (let i = mergeSectionStartIndex; i <= mergeSectionEndIndex; i++) { - const segment = this.loadedSegments[i]!; - unifiedBytes.set(segment.bytes, segment.start - mergeSectionStart); - } + // If we overshoot the max amount of permitted bytes, let's start evicting the oldest segments + while (this.totalStoredBytes > this.maxStorableBytes && this.loadedSegments.length > 1) { + let oldestSegment: ReadSegment | null = null; + let oldestSegmentIndex = -1; - this.loadedSegments.splice(mergeSectionStartIndex + 1, mergeSectionEndIndex - mergeSectionStartIndex); - this.loadedSegments[mergeSectionStartIndex]!.end = mergeSectionEnd; - this.loadedSegments[mergeSectionStartIndex]!.bytes = unifiedBytes; - this.loadedSegments[mergeSectionStartIndex]!.view = new DataView(unifiedBytes.buffer); + for (let i = 0; i < this.loadedSegments.length; i++) { + const candidate = this.loadedSegments[i]!; + if (!oldestSegment || candidate.age < oldestSegment.age) { + oldestSegment = candidate; + oldestSegmentIndex = i; + } + } + + assert(oldestSegment); + + this.totalStoredBytes -= oldestSegment.bytes.byteLength; + this.loadedSegments.splice(oldestSegmentIndex, 1); + } } getViewAndOffset(start: number, end: number) { - const segment = this.loadedSegments.find(x => x.start <= start && end <= x.end); + const startIndex = binarySearchLessOrEqual(this.loadedSegments, start, x => x.start); + let segment: ReadSegment | null = null; + + if (startIndex !== -1) { + for (let i = startIndex; i < this.loadedSegments.length; i++) { + const candidate = this.loadedSegments[i]!; + + if (candidate.start > start) { + break; + } + + if (end <= candidate.end) { + segment = candidate; + break; + } + } + } + if (!segment) { throw new Error(`No segment loaded for range [${start}, ${end}).`); } + segment.age = this.nextAge++; + return { view: segment.view, offset: segment.bytes.byteOffset + start - segment.start, diff --git a/src/source.ts b/src/source.ts index 9cc1010..ebad958 100644 --- a/src/source.ts +++ b/src/source.ts @@ -2,7 +2,15 @@ export abstract class Source { /** @internal */ abstract _read(start: number, end: number): Promise; /** @internal */ - abstract _getSize(): Promise; + abstract _retrieveSize(): Promise; + + /** @internal */ + _sizePromise: Promise | null = null; + + /** @internal */ + _getSize() { + return this._sizePromise ??= this._retrieveSize(); + } } export class ArrayBufferSource extends Source { @@ -16,7 +24,7 @@ export class ArrayBufferSource extends Source { } /** @internal */ - override async _getSize() { + override async _retrieveSize() { return this.buffer.byteLength; } } @@ -34,7 +42,7 @@ export class BlobSource extends Source { } /** @internal */ - override async _getSize() { + override async _retrieveSize() { return this.blob.size; } }