diff --git a/.gitignore b/.gitignore index 9244b7a..563ba71 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /node_modules -/build -tsdoc-metadata.json \ No newline at end of file +/build \ No newline at end of file diff --git a/api-extractor.json b/api-extractor.json index 6ebda5d..90cc917 100644 --- a/api-extractor.json +++ b/api-extractor.json @@ -12,7 +12,9 @@ "dtsRollup": { "enabled": true }, - "tsdocMetadata": {}, + "tsdocMetadata": { + "enabled": false + }, "messages": { "compilerMessageReporting": { "default": { diff --git a/dev/index.html b/dev/index.html index 653c075..e534e57 100644 --- a/dev/index.html +++ b/dev/index.html @@ -32,8 +32,8 @@ } const canvas = document.createElement('canvas'); - canvas.width = 1280; - canvas.height = 720; + canvas.width = 3840; + canvas.height = 3840; const context = canvas.getContext('2d'); let format = new Metamuxer.WebMOutputFormat({ streamable: true }); @@ -80,7 +80,7 @@ */ let videoSource = new Metamuxer.CanvasSource(canvas, { - codec: 'avc', + codec: 'av1', bitrate: 1e6 }); let audioSource = new Metamuxer.AudioBufferSource({ diff --git a/dist/metamuxer.js b/dist/metamuxer.js index 9bab4dc..4c328d4 100644 --- a/dist/metamuxer.js +++ b/dist/metamuxer.js @@ -1460,76 +1460,211 @@ var Metamuxer = (() => { }; // src/codec.ts - var buildVideoCodecString = (codec, width, height) => { + var AVC_LEVEL_TABLE = [ + { maxMacroblocks: 99, maxBitrate: 64e3, level: 10 }, + // Level 1 + { maxMacroblocks: 396, maxBitrate: 192e3, level: 11 }, + // Level 1.1 + { maxMacroblocks: 396, maxBitrate: 384e3, level: 12 }, + // Level 1.2 + { maxMacroblocks: 396, maxBitrate: 768e3, level: 13 }, + // Level 1.3 + { maxMacroblocks: 396, maxBitrate: 2e6, level: 20 }, + // Level 2 + { maxMacroblocks: 792, maxBitrate: 4e6, level: 21 }, + // Level 2.1 + { maxMacroblocks: 1620, maxBitrate: 4e6, level: 22 }, + // Level 2.2 + { maxMacroblocks: 1620, maxBitrate: 1e7, level: 30 }, + // Level 3 + { maxMacroblocks: 3600, maxBitrate: 14e6, level: 31 }, + // Level 3.1 + { maxMacroblocks: 5120, maxBitrate: 2e7, level: 32 }, + // Level 3.2 + { maxMacroblocks: 8192, maxBitrate: 2e7, level: 40 }, + // Level 4 + { maxMacroblocks: 8192, maxBitrate: 5e7, level: 41 }, + // Level 4.1 + { maxMacroblocks: 8704, maxBitrate: 5e7, level: 42 }, + // Level 4.2 + { maxMacroblocks: 22080, maxBitrate: 135e6, level: 50 }, + // Level 5 + { maxMacroblocks: 36864, maxBitrate: 24e7, level: 51 }, + // Level 5.1 + { maxMacroblocks: 36864, maxBitrate: 24e7, level: 52 }, + // Level 5.2 + { maxMacroblocks: 139264, maxBitrate: 24e7, level: 60 }, + // Level 6 + { maxMacroblocks: 139264, maxBitrate: 48e7, level: 61 }, + // Level 6.1 + { maxMacroblocks: 139264, maxBitrate: 8e8, level: 62 } + // Level 6.2 + ]; + var HEVC_LEVEL_TABLE = [ + { maxPictureSize: 36864, maxBitrate: 128e3, tier: "L", level: 30 }, + // Level 1 (Low Tier) + { maxPictureSize: 122880, maxBitrate: 15e5, tier: "L", level: 60 }, + // Level 2 (Low Tier) + { maxPictureSize: 245760, maxBitrate: 3e6, tier: "L", level: 63 }, + // Level 2.1 (Low Tier) + { maxPictureSize: 552960, maxBitrate: 6e6, tier: "L", level: 90 }, + // Level 3 (Low Tier) + { maxPictureSize: 983040, maxBitrate: 1e7, tier: "L", level: 93 }, + // Level 3.1 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 12e6, tier: "L", level: 120 }, + // Level 4 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 3e7, tier: "H", level: 120 }, + // Level 4 (High Tier) + { maxPictureSize: 2228224, maxBitrate: 2e7, tier: "L", level: 123 }, + // Level 4.1 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 5e7, tier: "H", level: 123 }, + // Level 4.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 25e6, tier: "L", level: 150 }, + // Level 5 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 1e8, tier: "H", level: 150 }, + // Level 5 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 4e7, tier: "L", level: 153 }, + // Level 5.1 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 16e7, tier: "H", level: 153 }, + // Level 5.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 6e7, tier: "L", level: 156 }, + // Level 5.2 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 24e7, tier: "H", level: 156 }, + // Level 5.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "L", level: 180 }, + // Level 6 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 180 }, + // Level 6 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 12e7, tier: "L", level: 183 }, + // Level 6.1 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 48e7, tier: "H", level: 183 }, + // Level 6.1 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "L", level: 186 }, + // Level 6.2 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 186 } + // Level 6.2 (High Tier) + ]; + var VP9_LEVEL_TABLE = [ + { maxPictureSize: 36864, maxBitrate: 2e5, level: 10 }, + // Level 1 + { maxPictureSize: 73728, maxBitrate: 8e5, level: 11 }, + // Level 1.1 + { maxPictureSize: 122880, maxBitrate: 18e5, level: 20 }, + // Level 2 + { maxPictureSize: 245760, maxBitrate: 36e5, level: 21 }, + // Level 2.1 + { maxPictureSize: 552960, maxBitrate: 72e5, level: 30 }, + // Level 3 + { maxPictureSize: 983040, maxBitrate: 12e6, level: 31 }, + // Level 3.1 + { maxPictureSize: 2228224, maxBitrate: 18e6, level: 40 }, + // Level 4 + { maxPictureSize: 2228224, maxBitrate: 3e7, level: 41 }, + // Level 4.1 + { maxPictureSize: 8912896, maxBitrate: 6e7, level: 50 }, + // Level 5 + { maxPictureSize: 8912896, maxBitrate: 12e7, level: 51 }, + // Level 5.1 + { maxPictureSize: 8912896, maxBitrate: 18e7, level: 52 }, + // Level 5.2 + { maxPictureSize: 35651584, maxBitrate: 18e7, level: 60 }, + // Level 6 + { maxPictureSize: 35651584, maxBitrate: 24e7, level: 61 }, + // Level 6.1 + { maxPictureSize: 35651584, maxBitrate: 48e7, level: 62 } + // Level 6.2 + ]; + var AV1_LEVEL_TABLE = [ + { maxPictureSize: 147456, maxBitrate: 15e5, tier: "M", level: 0 }, + // Level 2.0 (Main Tier) + { maxPictureSize: 278784, maxBitrate: 3e6, tier: "M", level: 1 }, + // Level 2.1 (Main Tier) + { maxPictureSize: 665856, maxBitrate: 6e6, tier: "M", level: 4 }, + // Level 3.0 (Main Tier) + { maxPictureSize: 1065024, maxBitrate: 1e7, tier: "M", level: 5 }, + // Level 3.1 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 12e6, tier: "M", level: 8 }, + // Level 4.0 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 3e7, tier: "H", level: 8 }, + // Level 4.0 (High Tier) + { maxPictureSize: 2359296, maxBitrate: 2e7, tier: "M", level: 9 }, + // Level 4.1 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 5e7, tier: "H", level: 9 }, + // Level 4.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 3e7, tier: "M", level: 12 }, + // Level 5.0 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 1e8, tier: "H", level: 12 }, + // Level 5.0 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 4e7, tier: "M", level: 13 }, + // Level 5.1 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 16e7, tier: "H", level: 13 }, + // Level 5.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 6e7, tier: "M", level: 14 }, + // Level 5.2 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 24e7, tier: "H", level: 14 }, + // Level 5.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "M", level: 15 }, + // Level 5.3 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 15 }, + // Level 5.3 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "M", level: 16 }, + // Level 6.0 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 16 }, + // Level 6.0 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 1e8, tier: "M", level: 17 }, + // Level 6.1 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 48e7, tier: "H", level: 17 }, + // Level 6.1 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 16e7, tier: "M", level: 18 }, + // Level 6.2 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 18 }, + // Level 6.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 16e7, tier: "M", level: 19 }, + // Level 6.3 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 19 } + // Level 6.3 (High Tier) + ]; + var buildVideoCodecString = (codec, width, height, bitrate) => { if (codec === "avc") { - let profileIndication = 100; - if (width <= 768 && height <= 432) { - profileIndication = 66; - } else if (width <= 1920 && height <= 1080) { - profileIndication = 77; - } - const profileCompatibility = 0; - const levelIndication = width > 1920 || height > 1080 ? 50 : 41; + const profileIndication = 100; + const totalMacroblocks = Math.ceil(width / 16) * Math.ceil(height / 16); + const levelInfo = AVC_LEVEL_TABLE.find( + (level) => totalMacroblocks <= level.maxMacroblocks && bitrate <= level.maxBitrate + ) ?? last(AVC_LEVEL_TABLE); + const levelIndication = levelInfo ? levelInfo.level : 0; const hexProfileIndication = profileIndication.toString(16).padStart(2, "0"); - const hexProfileCompatibility = profileCompatibility.toString(16).padStart(2, "0"); + const hexProfileCompatibility = "00"; const hexLevelIndication = levelIndication.toString(16).padStart(2, "0"); return `avc1.${hexProfileIndication}${hexProfileCompatibility}${hexLevelIndication}`; } else if (codec === "hevc") { let profileSpace = 0; let profileIdc = 1; - const compatibilityFlags = Array(32).fill(0); - compatibilityFlags[profileIdc] = 1; - const compatibilityHex = parseInt(compatibilityFlags.reverse().join(""), 2).toString(16).replace(/^0+/, ""); - let tier = "L"; - let level = 120; - if (width <= 1280 && height <= 720) { - level = 93; - } else if (width <= 1920 && height <= 1080) { - level = 120; - } else if (width <= 3840 && height <= 2160) { - level = 150; - } else { - tier = "H"; - level = 180; - } + const compatibilityFlags = "6"; + const pictureSize = width * height; + const levelInfo = HEVC_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(HEVC_LEVEL_TABLE); const constraintFlags = "B0"; const profilePrefix = profileSpace === 0 ? "" : String.fromCharCode(65 + profileSpace - 1); - return `hev1.${profilePrefix}${profileIdc}.${compatibilityHex}.${tier}${level}.${constraintFlags}`; + return `hev1.${profilePrefix}${profileIdc}.${compatibilityFlags}.${levelInfo.tier}${levelInfo.level}.${constraintFlags}`; } else if (codec === "vp8") { return "vp8"; } else if (codec === "vp9") { const profile = "00"; - let level; - if (width <= 854 && height <= 480) { - level = "21"; - } else if (width <= 1280 && height <= 720) { - level = "31"; - } else if (width <= 1920 && height <= 1080) { - level = "41"; - } else if (width <= 3840 && height <= 2160) { - level = "51"; - } else { - level = "61"; - } + const pictureSize = width * height; + const levelInfo = VP9_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(VP9_LEVEL_TABLE); const bitDepth = "08"; - return `vp09.${profile}.${level}.${bitDepth}`; + return `vp09.${profile}.${levelInfo.level}.${bitDepth}`; } else if (codec === "av1") { const profile = 0; - let level; - if (width <= 854 && height <= 480) { - level = "01"; - } else if (width <= 1280 && height <= 720) { - level = "03"; - } else if (width <= 1920 && height <= 1080) { - level = "04"; - } else if (width <= 3840 && height <= 2160) { - level = "07"; - } else { - level = "09"; - } - const tier = "M"; + const pictureSize = width * height; + const levelInfo = AV1_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(AV1_LEVEL_TABLE); const bitDepth = "08"; - return `av01.${profile}.${level}${tier}.${bitDepth}`; + return `av01.${profile}.${levelInfo.level.toString().padStart(2, "0")}${levelInfo.tier}.${bitDepth}`; } throw new TypeError(`Unhandled codec '${codec}'.`); }; @@ -3119,7 +3254,7 @@ ${cue.notes ?? ""}`; error: (error) => console.error("Video encode error:", error) }); this.encoder.configure({ - codec: buildVideoCodecString(this.codecConfig.codec, videoFrame.codedWidth, videoFrame.codedHeight), + codec: buildVideoCodecString(this.codecConfig.codec, videoFrame.codedWidth, videoFrame.codedHeight, this.codecConfig.bitrate), width: videoFrame.codedWidth, height: videoFrame.codedHeight, bitrate: this.codecConfig.bitrate, diff --git a/dist/metamuxer.min.js b/dist/metamuxer.min.js index fd098e5..c89b121 100644 --- a/dist/metamuxer.min.js +++ b/dist/metamuxer.min.js @@ -1,10 +1,10 @@ -"use strict";var Metamuxer=(()=>{var ze=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var dt=Object.prototype.hasOwnProperty;var mt=(t,i)=>{for(var e in i)ze(t,e,{get:i[e],enumerable:!0})},ft=(t,i,e,r)=>{if(i&&typeof i=="object"||typeof i=="function")for(let s of ct(i))!dt.call(t,s)&&s!==e&&ze(t,s,{get:()=>i[s],enumerable:!(r=lt(i,s))||r.enumerable});return t};var pt=t=>ft(ze({},"__esModule",{value:!0}),t);var kr={};mt(kr,{AUDIO_CODECS:()=>Y,ArrayBufferTarget:()=>L,AudioBufferSource:()=>Ee,AudioDataSource:()=>Oe,AudioSource:()=>O,CanvasSource:()=>ve,EncodedAudioChunkSource:()=>_e,EncodedVideoChunkSource:()=>xe,MediaSource:()=>W,MediaStreamAudioTrackSource:()=>Ve,MediaStreamVideoTrackSource:()=>Ae,MkvOutputFormat:()=>se,Mp4OutputFormat:()=>ke,Output:()=>Ie,OutputFormat:()=>M,SUBTITLE_CODECS:()=>ye,StreamTarget:()=>he,SubtitleSource:()=>R,Target:()=>V,TextSubtitleSource:()=>Me,VIDEO_CODECS:()=>G,VideoFrameSource:()=>Se,VideoSource:()=>_,WebMOutputFormat:()=>D});function c(t){if(!t)throw new Error("Assertion failed.")}var N=t=>t&&t[t.length-1],I=t=>t>=0&&t<2**32,z=(t,i,e)=>{let r=0;for(let s=i;s>n;r<<=1,r|=u}return r},Qe=(t,i,e,r)=>{for(let s=i;s>e-s-1<t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t.buffer,t.byteOffset,t.byteLength),x=new TextEncoder,H={bt709:1,bt470bg:5,smpte170m:6},Q={bt709:1,smpte170m:6,"iec61966-2-1":13},$={rgb:0,bt709:1,bt470bg:5,smpte170m:6},ne=t=>!!t&&!!t.primaries&&!!t.transfer&&!!t.matrix&&t.fullRange!==void 0,Pe=t=>t instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&t instanceof SharedArrayBuffer||ArrayBuffer.isView(t)&&!(t instanceof DataView),B=class{constructor(){this.currentPromise=Promise.resolve()}async acquire(){let i,e=new Promise(s=>{i=s}),r=this.currentPromise;return this.currentPromise=e,await r,i}};var Z=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,ht=/^WEBVTT(.|\n)*?\n{2}/,j=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,ue=class{constructor(i){this.preambleText=null;this.preambleEmitted=!1;this.options=i}parse(i){i=i.replaceAll(`\r +"use strict";var Metamuxer=(()=>{var Pe=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var pt=Object.getOwnPropertyNames;var ht=Object.prototype.hasOwnProperty;var bt=(t,i)=>{for(var e in i)Pe(t,e,{get:i[e],enumerable:!0})},xt=(t,i,e,r)=>{if(i&&typeof i=="object"||typeof i=="function")for(let s of pt(i))!ht.call(t,s)&&s!==e&&Pe(t,s,{get:()=>i[s],enumerable:!(r=ft(i,s))||r.enumerable});return t};var wt=t=>xt(Pe({},"__esModule",{value:!0}),t);var vr={};bt(vr,{AUDIO_CODECS:()=>Y,ArrayBufferTarget:()=>K,AudioBufferSource:()=>Ee,AudioDataSource:()=>Oe,AudioSource:()=>E,CanvasSource:()=>ve,EncodedAudioChunkSource:()=>Ae,EncodedVideoChunkSource:()=>Se,MediaSource:()=>W,MediaStreamAudioTrackSource:()=>Me,MediaStreamVideoTrackSource:()=>_e,MkvOutputFormat:()=>se,Mp4OutputFormat:()=>ke,Output:()=>ze,OutputFormat:()=>z,SUBTITLE_CODECS:()=>ge,StreamTarget:()=>he,SubtitleSource:()=>R,Target:()=>V,TextSubtitleSource:()=>Ve,VIDEO_CODECS:()=>G,VideoFrameSource:()=>ye,VideoSource:()=>O,WebMOutputFormat:()=>D});function d(t){if(!t)throw new Error("Assertion failed.")}var S=t=>t&&t[t.length-1],P=t=>t>=0&&t<2**32,B=(t,i,e)=>{let r=0;for(let s=i;s>n;r<<=1,r|=u}return r},Qe=(t,i,e,r)=>{for(let s=i;s>e-s-1<t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t.buffer,t.byteOffset,t.byteLength),y=new TextEncoder,H={bt709:1,bt470bg:5,smpte170m:6},Q={bt709:1,smpte170m:6,"iec61966-2-1":13},$={rgb:0,bt709:1,bt470bg:5,smpte170m:6},ne=t=>!!t&&!!t.primaries&&!!t.transfer&&!!t.matrix&&t.fullRange!==void 0,Be=t=>t instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&t instanceof SharedArrayBuffer||ArrayBuffer.isView(t)&&!(t instanceof DataView),N=class{constructor(){this.currentPromise=Promise.resolve()}async acquire(){let i,e=new Promise(s=>{i=s}),r=this.currentPromise;return this.currentPromise=e,await r,i}};var Z=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,Tt=/^WEBVTT(.|\n)*?\n{2}/,j=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,ue=class{constructor(i){this.preambleText=null;this.preambleEmitted=!1;this.options=i}parse(i){i=i.replaceAll(`\r `,` `).replaceAll("\r",` -`),Z.lastIndex=0;let e;if(!this.preambleText){if(!ht.test(i)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}e=Z.exec(i);let r=i.slice(0,e?.index??i.length).trimEnd();if(!r){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=r,e&&(i=i.slice(e.index),Z.lastIndex=0)}for(;e=Z.exec(i);){let r=i.slice(0,e.index),s=e[1],o=e.index+e[0].length,a=i.indexOf(` -`,o)+1,n=i.slice(o,a).trim(),u=i.indexOf(` +`),Z.lastIndex=0;let e;if(!this.preambleText){if(!Tt.test(i)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}e=Z.exec(i);let r=i.slice(0,e?.index??i.length).trimEnd();if(!r){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=r,e&&(i=i.slice(e.index),Z.lastIndex=0)}for(;e=Z.exec(i);){let r=i.slice(0,e.index),s=e[1],a=e.index+e[0].length,o=i.indexOf(` +`,a)+1,n=i.slice(a,o).trim(),u=i.indexOf(` -`,o);u===-1&&(u=i.length);let d=le(e[2]),f=le(e[3])-d,w=i.slice(a,u).trim();i=i.slice(u).trimStart(),Z.lastIndex=0;let E={timestamp:d/1e3,duration:f/1e3,text:w,identifier:s,settings:n,notes:r},g={};this.preambleEmitted||(g.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(E,g)}}},bt=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,le=t=>{let i=bt.exec(t);if(!i)throw new Error("Expected match.");return 60*60*1e3*Number(i[1]||"0")+60*1e3*Number(i[2])+1e3*Number(i[3])+Number(i[4])},ce=t=>{let i=Math.floor(t/36e5),e=Math.floor(t%(60*60*1e3)/(60*1e3)),r=Math.floor(t%(60*1e3)/1e3),s=t%1e3;return i.toString().padStart(2,"0")+":"+e.toString().padStart(2,"0")+":"+r.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var J=class{constructor(i){this.writer=i;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap}writeU32(i){this.helperView.setUint32(0,i,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(i){this.helperView.setUint32(0,Math.floor(i/2**32),!1),this.helperView.setUint32(4,i,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(i){for(let e=0;e[(t%256+256)%256],h=t=>(A.setUint16(0,t,!1),[p[0],p[1]]),Tt=t=>(A.setInt16(0,t,!1),[p[0],p[1]]),je=t=>(A.setUint32(0,t,!1),[p[1],p[2],p[3]]),l=t=>(A.setUint32(0,t,!1),[p[0],p[1],p[2],p[3]]),qe=t=>(A.setInt32(0,t,!1),[p[0],p[1],p[2],p[3]]),U=t=>(A.setUint32(0,Math.floor(t/2**32),!1),A.setUint32(4,t,!1),[p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]]),We=t=>(A.setInt16(0,2**8*t,!1),[p[0],p[1]]),v=t=>(A.setInt32(0,2**16*t,!1),[p[0],p[1],p[2],p[3]]),Ue=t=>(A.setInt32(0,2**30*t,!1),[p[0],p[1],p[2],p[3]]),De=(t,i)=>{let e=[],r=t;do{let s=r&127;r>>=7,e.length>0&&(s|=128),e.push(s),i!==void 0&&i--}while(r>0||i);return e.reverse()},y=(t,i=!1)=>{let e=Array(t.length).fill(null).map((r,s)=>t.charCodeAt(s));return i&&e.push(0),e},Re=t=>{let i=null;for(let e of t)(!i||e.timestamp>i.timestamp)&&(i=e);return i},Ke=t=>{let i=t*(Math.PI/180),e=Math.cos(i),r=Math.sin(i);return[e,r,0,-r,e,0,0,0,1]},Le=Ke(0),Xe=t=>[v(t[0]),v(t[1]),Ue(t[2]),v(t[3]),v(t[4]),Ue(t[5]),v(t[6]),v(t[7]),Ue(t[8])],b=(t,i,e)=>({type:t,contents:i&&new Uint8Array(i.flat(10)),children:e}),T=(t,i,e,r,s)=>b(t,[C(i),je(e),r??[]],s),Ge=t=>{let i=512;return t.fragmented?b("ftyp",[y("iso5"),l(i),y("iso5"),y("iso6"),y("mp41")]):b("ftyp",[y("isom"),l(i),y("isom"),t.holdsAvc?y("avc1"):[],y("mp41")])},me=t=>({type:"mdat",largeSize:t}),Ye=t=>({type:"free",size:t}),ee=(t,i,e=!1)=>b("moov",void 0,[wt(i,t),...t.map(r=>Ct(r,i)),e?Zt(t):null]),wt=(t,i)=>{let e=S(Math.max(0,...i.filter(a=>a.samples.length>0).map(a=>{let n=Re(a.samples);return n.timestamp+n.duration})),de),r=Math.max(0,...i.map(a=>a.track.id))+1,s=!I(t)||!I(e),o=s?U:l;return T("mvhd",+s,0,[o(t),o(t),l(de),o(e),v(1),We(1),Array(10).fill(0),Xe(Le),Array(24).fill(0),l(r)])},Ct=(t,i)=>b("trak",void 0,[gt(t,i),kt(t,i)]),gt=(t,i)=>{let e=Re(t.samples),r=S(e?e.timestamp+e.duration:0,de),s=!I(i)||!I(r),o=s?U:l,a;if(t.type==="video"){let n=t.track.metadata.rotation;a=n===void 0||typeof n=="number"?Ke(n??0):n}else a=Le;return T("tkhd",+s,3,[o(i),o(i),l(t.track.id),l(0),o(r),Array(8).fill(0),h(0),h(t.track.id),We(t.type==="audio"?1:0),h(0),Xe(a),v(t.type==="video"?t.info.width:0),v(t.type==="video"?t.info.height:0)])},kt=(t,i)=>b("mdia",void 0,[yt(t,i),vt(t),At(t)]),yt=(t,i)=>{let e=Re(t.samples),r=S(e?e.timestamp+e.duration:0,t.timescale),s=!I(i)||!I(r),o=s?U:l;return T("mdhd",+s,0,[o(i),o(i),l(t.timescale),o(r),h(21956),h(0)])},xt={video:"vide",audio:"soun",subtitle:"text"},St={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},vt=t=>T("hdlr",0,0,[y("mhlr"),y(xt[t.type]),l(0),l(0),l(0),y(St[t.type],!0)]),At=t=>b("minf",void 0,[Vt[t.type](),Mt(),Pt(t)]),_t=()=>T("vmhd",0,1,[h(0),h(0),h(0),h(0)]),Ot=()=>T("smhd",0,0,[h(0),h(0)]),Et=()=>T("nmhd",0,0),Vt={video:_t,audio:Ot,subtitle:Et},Mt=()=>b("dinf",void 0,[It()]),It=()=>T("dref",0,0,[l(1)],[zt()]),zt=()=>T("url ",0,1),Pt=t=>{let i=t.compositionTimeOffsetTable.length>1||t.compositionTimeOffsetTable.some(e=>e.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[Ut(t),qt(t),Kt(t),Lt(t),Xt(t),Gt(t),i?Yt(t):null])},Ut=t=>{let i;return t.type==="video"?i=Dt(nr[t.track.source._codec],t):t.type==="audio"?i=Nt(lr[t.track.source._codec],t):t.type==="subtitle"&&(i=$t(dr[t.track.source._codec],t)),c(i),T("stsd",0,0,[l(1)],[i])},Dt=(t,i)=>b(t,[Array(6).fill(0),h(1),h(0),h(0),Array(12).fill(0),h(i.info.width),h(i.info.height),l(4718592),l(4718592),l(0),h(1),Array(32).fill(0),h(24),Tt(65535)],[ur[i.track.source._codec](i),ne(i.info.decoderConfig.colorSpace)?Wt(i):null]),Wt=t=>b("colr",[y("nclx"),h(H[t.info.decoderConfig.colorSpace.primaries]),h(Q[t.info.decoderConfig.colorSpace.transfer]),h($[t.info.decoderConfig.colorSpace.matrix]),C((t.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),Rt=t=>t.info.decoderConfig&&b("avcC",[...P(t.info.decoderConfig.description)]),Ft=t=>t.info.decoderConfig&&b("hvcC",[...P(t.info.decoderConfig.description)]),$e=t=>{if(!t.info.decoderConfig)return null;let i=t.info.decoderConfig;c(i.colorSpace);let e=i.codec.split("."),r=Number(e[1]),s=Number(e[2]),n=(Number(e[3])<<4)+(0<<1)+Number(i.colorSpace.fullRange);return T("vpcC",1,0,[C(r),C(s),C(n),C(2),C(2),C(2),h(0)])},Bt=()=>{let e=(1<<7)+1;return b("av1C",[e,0,0,0])},Nt=(t,i)=>b(t,[Array(6).fill(0),h(1),h(0),h(0),l(0),h(i.info.numberOfChannels),h(16),h(0),h(0),v(i.info.sampleRate)],[cr[i.track.source._codec](i)]),Ht=t=>{let e=[...P(t.info.decoderConfig.description??new ArrayBuffer(0))];return e=[...C(64),...C(21),...je(0),...l(0),...l(0),...C(5),...De(e.length),...e],e=[...h(1),...C(0),...C(4),...De(e.length),...e,...C(6),...C(1),...C(2)],e=[...C(3),...De(e.length),...e],T("esds",0,0,e)},Qt=t=>{let i=3840,e=0,r=t.info.decoderConfig?.description;if(r){c(r.byteLength<18);let s=ArrayBuffer.isView(r)?new DataView(r.buffer,r.byteOffset,r.byteLength):new DataView(r);i=s.getUint16(10,!0),e=s.getInt16(14,!0)}return b("dOps",[C(0),C(t.info.numberOfChannels),h(i),l(t.info.sampleRate),We(e),C(0)])},$t=(t,i)=>b(t,[Array(6).fill(0),h(1)],[mr[i.track.source._codec](i)]),jt=t=>b("vttC",[...x.encode(t.info.config.description)]);var qt=t=>T("stts",0,0,[l(t.timeToSampleTable.length),t.timeToSampleTable.map(i=>[l(i.sampleCount),l(i.sampleDelta)])]),Kt=t=>{if(t.samples.every(e=>e.type==="key"))return null;let i=[...t.samples.entries()].filter(([,e])=>e.type==="key");return T("stss",0,0,[l(i.length),i.map(([e])=>l(e+1))])},Lt=t=>T("stsc",0,0,[l(t.compactlyCodedChunkTable.length),t.compactlyCodedChunkTable.map(i=>[l(i.firstChunk),l(i.samplesPerChunk),l(1)])]),Xt=t=>T("stsz",0,0,[l(0),l(t.samples.length),t.samples.map(i=>l(i.size))]),Gt=t=>t.finalizedChunks.length>0&&N(t.finalizedChunks).offset>=2**32?T("co64",0,0,[l(t.finalizedChunks.length),t.finalizedChunks.map(i=>U(i.offset))]):T("stco",0,0,[l(t.finalizedChunks.length),t.finalizedChunks.map(i=>l(i.offset))]),Yt=t=>T("ctts",0,0,[l(t.compositionTimeOffsetTable.length),t.compositionTimeOffsetTable.map(i=>[l(i.sampleCount),l(i.sampleCompositionTimeOffset)])]),Zt=t=>b("mvex",void 0,t.map(Jt)),Jt=t=>T("trex",0,0,[l(t.track.id),l(1),l(0),l(0),l(0)]),Fe=(t,i)=>b("moof",void 0,[er(t),...i.map(tr)]),er=t=>T("mfhd",0,0,[l(t)]),Ze=t=>{let i=0,e=0,r=0,s=0,o=t.type==="delta";return e|=+o,o?i|=1:i|=2,i<<24|e<<16|r<<8|s},tr=t=>b("traf",void 0,[rr(t),ir(t),sr(t)]),rr=t=>{c(t.currentChunk);let i=0;i|=8,i|=16,i|=32,i|=131072;let e=t.currentChunk.samples[1]??t.currentChunk.samples[0],r={duration:e.timescaleUnitsToNextSample,size:e.size,flags:Ze(e)};return T("tfhd",0,i,[l(t.track.id),l(r.duration),l(r.size),l(r.flags)])},ir=t=>(c(t.currentChunk),T("tfdt",1,0,[U(S(t.currentChunk.startTimestamp,t.timescale))])),sr=t=>{c(t.currentChunk);let i=t.currentChunk.samples.map(k=>k.timescaleUnitsToNextSample),e=t.currentChunk.samples.map(k=>k.size),r=t.currentChunk.samples.map(Ze),s=t.currentChunk.samples.map(k=>S(k.timestamp-k.decodeTimestamp,t.timescale)),o=new Set(i),a=new Set(e),n=new Set(r),u=new Set(s),d=n.size===2&&r[0]!==r[1],m=o.size>1,f=a.size>1,w=!d&&n.size>1,E=u.size>1||[...u].some(k=>k!==0),g=0;return g|=1,g|=4*+d,g|=256*+m,g|=512*+f,g|=1024*+w,g|=2048*+E,T("trun",1,g,[l(t.currentChunk.samples.length),l(t.currentChunk.offset-t.currentChunk.moofOffset||0),d?l(r[0]):[],t.currentChunk.samples.map((k,F)=>[m?l(i[F]):[],f?l(e[F]):[],w?l(r[F]):[],E?qe(s[F]):[]])])},Je=t=>b("mfra",void 0,[...t.map(or),ar()]),or=(t,i)=>T("tfra",1,0,[l(t.track.id),l(63),l(t.finalizedChunks.length),t.finalizedChunks.map(r=>[U(S(r.startTimestamp,t.timescale)),U(r.moofOffset),l(i+1),l(1),l(1)])]),ar=()=>T("mfro",0,0,[l(0)]),et=()=>b("vtte"),tt=(t,i,e,r,s)=>b("vttc",void 0,[s!==null?b("vsid",[qe(s)]):null,e!==null?b("iden",[...x.encode(e)]):null,i!==null?b("ctim",[...x.encode(ce(i))]):null,r!==null?b("sttg",[...x.encode(r)]):null,b("payl",[...x.encode(t)])]),rt=t=>b("vtta",[...x.encode(t)]),nr={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},ur={avc:Rt,hevc:Ft,vp8:$e,vp9:$e,av1:Bt},lr={aac:"mp4a",opus:"Opus"},cr={aac:Ht,opus:Qt},dr={webvtt:"wvtt"},mr={webvtt:jt};var q=class{constructor(i){this.mutex=new B;this.trackTimestampInfo=new WeakMap;this.output=i}beforeTrackAdd(i){}onTrackClose(i){}validateAndNormalizeTimestamp(i,e,r){let s=e/1e6,o=this.trackTimestampInfo.get(i);if(!o){if(!r)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:i.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:i.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(i,o)}if(i.source._offsetTimestamps&&(s-=o.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(ss.start-o.start);e.push({start:r[0].start,size:r[0].data.byteLength});for(let s=1;sd.start<=r&&rpr){for(let d=0;d=e.written[a+1].start;)e.written[a].end=Math.max(e.written[a].end,e.written[a+1].end),e.written.splice(a+1,1)}createChunk(e){let s={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(s),this.chunks.sort((o,a)=>o.start-a.start),this.chunks.indexOf(s)}queueChunksForFlush(e=!1){c(this.writer);for(let r=0;r{if(t==="avc"){let r=100;i<=768&&e<=432?r=66:i<=1920&&e<=1080&&(r=77);let s=0,o=i>1920||e>1080?50:41,a=r.toString(16).padStart(2,"0"),n=s.toString(16).padStart(2,"0"),u=o.toString(16).padStart(2,"0");return`avc1.${a}${n}${u}`}else if(t==="hevc"){let r=0,s=1,o=Array(32).fill(0);o[s]=1;let a=parseInt(o.reverse().join(""),2).toString(16).replace(/^0+/,""),n="L",u=120;return i<=1280&&e<=720?u=93:i<=1920&&e<=1080?u=120:i<=3840&&e<=2160?u=150:(n="H",u=180),`hev1.${r===0?"":String.fromCharCode(65+r-1)}${s}.${a}.${n}${u}.B0`}else{if(t==="vp8")return"vp8";if(t==="vp9"){let r="00",s;return i<=854&&e<=480?s="21":i<=1280&&e<=720?s="31":i<=1920&&e<=1080?s="41":i<=3840&&e<=2160?s="51":s="61",`vp09.${r}.${s}.08`}else if(t==="av1"){let s;return i<=854&&e<=480?s="01":i<=1280&&e<=720?s="03":i<=1920&&e<=1080?s="04":i<=3840&&e<=2160?s="07":s="09",`av01.0.${s}M.08`}}throw new TypeError(`Unhandled codec '${t}'.`)},st=(t,i,e)=>{if(t==="aac")return i>=2&&e<=24e3?"mp4a.40.29":e<=24e3?"mp4a.40.5":"mp4a.40.2";if(t==="opus")return"opus";if(t==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${t}'.`)},be=t=>{if(!t)throw new TypeError("Video chunk metadata must be provided.");if(typeof t!="object")throw new TypeError("Video chunk metadata must be an object.");if(!t.decoderConfig)throw new TypeError("Video chunk metadata must include a decoder configuration.");if(typeof t.decoderConfig!="object")throw new TypeError("Video chunk metadata decoder configuration must be an object.");if(typeof t.decoderConfig.codec!="string")throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(t.decoderConfig.codedWidth)||t.decoderConfig.codedWidth<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");if(!Number.isInteger(t.decoderConfig.codedHeight)||t.decoderConfig.codedHeight<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");if(t.decoderConfig.description!==void 0&&!Pe(t.decoderConfig.description))throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(t.decoderConfig.colorSpace!==void 0){let{colorSpace:i}=t.decoderConfig;if(typeof i!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let e=Object.keys(H);if(i.primaries!=null&&!e.includes(i.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${e.join(", ")}.`);let r=Object.keys(Q);if(i.transfer!=null&&!r.includes(i.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${r.join(", ")}.`);let s=Object.keys($);if(i.matrix!=null&&!s.includes(i.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(i.fullRange!=null&&typeof i.fullRange!="boolean")throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.")}if((t.decoderConfig.codec.startsWith("avc1")||t.decoderConfig.codec.startsWith("avc3"))&&!t.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((t.decoderConfig.codec.startsWith("hev1")||t.decoderConfig.codec.startsWith("hvc1"))&&!t.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((t.decoderConfig.codec==="vp8"||t.decoderConfig.codec.startsWith("vp09"))&&t.decoderConfig.colorSpace===void 0)throw new TypeError("Video chunk metadata decoder configuration for VP8/VP9 must include a colorSpace.")},Te=t=>{if(!t)throw new TypeError("Audio chunk metadata must be provided.");if(typeof t!="object")throw new TypeError("Audio chunk metadata must be an object.");if(!t.decoderConfig)throw new TypeError("Audio chunk metadata must include a decoder configuration.");if(typeof t.decoderConfig!="object")throw new TypeError("Audio chunk metadata decoder configuration must be an object.");if(typeof t.decoderConfig.codec!="string")throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(t.decoderConfig.sampleRate)||t.decoderConfig.sampleRate<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");if(!Number.isInteger(t.decoderConfig.numberOfChannels)||t.decoderConfig.numberOfChannels<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");if(t.decoderConfig.description!==void 0&&!Pe(t.decoderConfig.description))throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(t.decoderConfig.codec==="opus"&&t.decoderConfig.description&&t.decoderConfig.description.byteLength<18)throw new TypeError("Invalid decoder description provided for Opus; must be at least 18 bytes long.")},we=t=>{if(!t)throw new TypeError("Subtitle metadata must be provided.");if(typeof t!="object")throw new TypeError("Subtitle metadata must be an object.");if(!t.config)throw new TypeError("Subtitle metadata must include a config object.");if(typeof t.config!="object")throw new TypeError("Subtitle metadata config must be an object.");if(typeof t.config.description!="string")throw new TypeError("Subtitle metadata config description must be a string.")};var de=1e3,hr=2082844800,S=(t,i,e=!0)=>{let r=t*i;return e?Math.round(r):r},Ce=class extends q{constructor(e,r){super(e);this.timestampsMustStartAtZero=!0;this.auxTarget=new L;this.auxWriter=this.auxTarget._createWriter();this.auxBoxWriter=new J(this.auxWriter);this.ftypSize=null;this.mdat=null;this.trackDatas=[];this.creationTime=Math.floor(Date.now()/1e3)+hr;this.finalizedChunks=[];this.nextFragmentNumber=1;this.writer=e._writer,this.boxWriter=new J(this.writer),this.fastStart=r._options.fastStart??(this.writer instanceof K?"in-memory":!1),(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),r=this.output._tracks.some(s=>s.type==="video"&&s.source._codec==="avc");this.boxWriter.writeBox(Ge({holdsAvc:r,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=me(!1):this.fastStart==="fragmented"||(this.mdat=me(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,r){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;be(r),c(r),c(r.decoderConfig),c(r.decoderConfig.codedWidth!==void 0),c(r.decoderConfig.codedHeight!==void 0);let o={track:e,type:"video",info:{width:r.decoderConfig.codedWidth,height:r.decoderConfig.codedHeight,decoderConfig:r.decoderConfig},timescale:e.metadata.frameRate??57600,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getAudioTrackData(e,r){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;Te(r),c(r),c(r.decoderConfig);let o={track:e,type:"audio",info:{numberOfChannels:r.decoderConfig.numberOfChannels,sampleRate:r.decoderConfig.sampleRate,decoderConfig:r.decoderConfig},timescale:r.decoderConfig.sampleRate,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getSubtitleTrackData(e,r){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;we(r),c(r),c(r.config);let o={track:e,type:"subtitle",info:{config:r.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(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),this.validateAndNormalizeTimestamp(e,0,!0),o}async addEncodedVideoChunk(e,r,s){let o=await this.mutex.acquire();try{let a=this.getVideoTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,r.timestamp,r.type==="key"),d=this.createSampleForTrack(a,n,u,(r.duration??0)/1e6,r.type);await this.registerSample(a,d)}finally{o()}}async addEncodedAudioChunk(e,r,s){let o=await this.mutex.acquire();try{let a=this.getAudioTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,r.timestamp,r.type==="key"),d=this.createSampleForTrack(a,n,u,(r.duration??0)/1e6,r.type);await this.registerSample(a,d)}finally{o()}}async addSubtitleCue(e,r,s){let o=await this.mutex.acquire();try{let a=this.getSubtitleTrackData(e,s);this.validateAndNormalizeTimestamp(a.track,1e6*r.timestamp,!0),e.source._codec==="webvtt"&&(a.cueQueue.push(r),await this.processWebVTTCues(a,r.timestamp))}finally{o()}}async processWebVTTCues(e,r){for(;e.cueQueue.length>0;){let s=new Set([]);for(let m of e.cueQueue)c(m.timestamp<=r),c(e.lastCueEndTimestamp<=m.timestamp+m.duration),s.add(Math.max(m.timestamp,e.lastCueEndTimestamp)),s.add(m.timestamp+m.duration);let o=[...s].sort((m,f)=>m-f),a=o[0],n=o[1]??a;if(r=n)break;j.lastIndex=0;let w=j.test(f.text),E=f.timestamp+f.duration,g=e.cueToSourceId.get(f);if(g===void 0&&ns.timestamp).sort((s,o)=>s-o);for(let s=0;s{if(e===n)return r.type==="key";let u=n.sampleQueue[0];return u&&u.type==="key"});o>=1&&a&&(s=!0,await this.finalizeFragment())}else s=o>=.5}s&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:r.timestamp,samples:[],offset:null,moofOffset:null}),c(e.currentChunk),e.currentChunk.samples.push(r),e.timestampProcessingQueue.push(r)}async finalizeCurrentChunk(e){if(c(this.fastStart!=="fragmented"),!!e.currentChunk){if(e.finalizedChunks.push(e.currentChunk),this.finalizedChunks.push(e.currentChunk),(e.compactlyCodedChunkTable.length===0||N(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 r of e.currentChunk.samples)c(r.data),this.writer.write(r.data),r.data=null;await this.writer.flush()}}async interleaveSamples(){c(this.fastStart==="fragmented");for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(r=>r.track===e))return;e:for(;;){let e=null,r=1/0;for(let o of this.trackDatas){if(o.sampleQueue.length===0&&!o.track.source._closed)break e;o.sampleQueue.length>0&&o.sampleQueue[0].timestamp=2**32&&(u.largeSize=!0,m=this.boxWriter.measureBox(u)+d),u.size=m,this.boxWriter.writeBox(u)}for(let u of this.trackDatas){u.currentChunk.offset=this.writer.getPos(),u.currentChunk.moofOffset=s;for(let d of u.currentChunk.samples)this.writer.write(d.data),d.data=null}let a=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(o));let n=Fe(r,this.trackDatas);this.boxWriter.writeBox(n),this.writer.seek(a);for(let u of this.trackDatas)u.finalizedChunks.push(u.currentChunk),this.finalizedChunks.push(u.currentChunk),u.currentChunk=null;e&&await this.writer.flush()}async onTrackClose(e){let r=await this.mutex.acquire();if(e.type==="subtitle"&&e.source._codec==="webvtt"){let s=this.trackDatas.find(o=>o.track===e);s&&await this.processWebVTTCues(s,1/0)}this.fastStart==="fragmented"&&await this.interleaveSamples(),r()}async finalize(){let e=await this.mutex.acquire();for(let r of this.trackDatas)r.type==="subtitle"&&r.track.source._codec==="webvtt"&&await this.processWebVTTCues(r,1/0);if(this.fastStart==="fragmented"){for(let r of this.trackDatas){for(let s of r.sampleQueue)await this.addSampleToTrack(r,s);this.processTimestamps(r)}await this.finalizeFragment(!1)}else for(let r of this.trackDatas)this.processTimestamps(r),await this.finalizeCurrentChunk(r);if(this.fastStart==="in-memory"){c(this.mdat);let r;for(let o=0;o<2;o++){let a=ee(this.trackDatas,this.creationTime),n=this.boxWriter.measureBox(a);r=this.boxWriter.measureBox(this.mdat);let u=this.writer.getPos()+n+r;for(let d of this.finalizedChunks){d.offset=u;for(let{data:m}of d.samples)c(m),u+=m.byteLength,r+=m.byteLength}if(u<2**32)break;r>=2**32&&(this.mdat.largeSize=!0)}let s=ee(this.trackDatas,this.creationTime);this.boxWriter.writeBox(s),this.mdat.size=r,this.boxWriter.writeBox(this.mdat);for(let o of this.finalizedChunks)for(let a of o.samples)c(a.data),this.writer.write(a.data),a.data=null}else if(this.fastStart==="fragmented"){let r=this.writer.getPos(),s=Je(this.trackDatas);this.boxWriter.writeBox(s);let o=this.writer.getPos()-r;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(o)}else{c(this.mdat),c(this.ftypSize!==null);let r=this.boxWriter.offsets.get(this.mdat);c(r!==void 0);let s=this.writer.getPos()-r;this.mdat.size=s,this.mdat.largeSize=s>=2**32,this.boxWriter.patchBox(this.mdat);let o=ee(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(o);let a=r-this.writer.getPos();this.boxWriter.writeBox(Ye(a))}else this.boxWriter.writeBox(o)}e()}};var re=class{constructor(i){this.value=i}},X=class{constructor(i){this.value=i}},ie=class{constructor(i){this.value=i}};var Be=t=>t<256?1:t<65536?2:t<1<<24?3:t<2**32?4:t<2**40?5:6,Ne=t=>t>=-64&&t<64?1:t>=-8192&&t<8192?2:t>=-(1<<20)&&t<1<<20?3:t>=-(1<<27)&&t<1<<27?4:t>=-(2**34)&&t<2**34?5:6,ot=t=>{if(t<127)return 1;if(t<16383)return 2;if(t<(1<<21)-1)return 3;if(t<(1<<28)-1)return 4;if(t<2**35-1)return 5;if(t<2**42-1)return 6;throw new Error("EBML VINT size not supported "+t)};var He=2**15,at="https://github.com/Vanilagy/webm-muxer",nt=6,ut=5,br={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"},Tr={video:1,audio:2,subtitle:17},ge=class extends q{constructor(e,r){super(e);this.timestampsMustStartAtZero=!1;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap;this.dataOffsets=new WeakMap;this.trackDatas=[];this.segment=null;this.segmentInfo=null;this.seekHead=null;this.tracksElement=null;this.segmentDuration=null;this.cues=null;this.currentCluster=null;this.currentClusterMsTimestamp=null;this.trackDatasInCurrentCluster=new Set;this.duration=0;this.writer=e._writer,this.format=r,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,r=Be(e)){let s=0;switch(r){case 6:this.helperView.setUint8(s++,e/2**40|0);case 5:this.helperView.setUint8(s++,e/2**32|0);case 4:this.helperView.setUint8(s++,e>>24);case 3:this.helperView.setUint8(s++,e>>16);case 2:this.helperView.setUint8(s++,e>>8);case 1:this.helperView.setUint8(s++,e);break;default:throw new Error("Bad UINT size "+r)}this.writer.write(this.helper.subarray(0,s))}writeSignedInt(e,r=Ne(e)){e<0&&(e+=2**(r*8)),this.writeUnsignedInt(e,r)}writeEBMLVarInt(e,r=ot(e)){let s=0;switch(r){case 1:this.helperView.setUint8(s++,128|e);break;case 2:this.helperView.setUint8(s++,64|e>>8),this.helperView.setUint8(s++,e);break;case 3:this.helperView.setUint8(s++,32|e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 4:this.helperView.setUint8(s++,16|e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 5:this.helperView.setUint8(s++,8|e/2**32&7),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 6:this.helperView.setUint8(s++,4|e/2**40&3),this.helperView.setUint8(s++,e/2**32|0),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;default:throw new Error("Bad EBML VINT size "+r)}this.writer.write(this.helper.subarray(0,s))}writeString(e){this.writer.write(new Uint8Array(e.split("").map(r=>r.charCodeAt(0))))}writeEBML(e){if(e!==null){if(e instanceof Uint8Array)this.writer.write(e);else if(Array.isArray(e))for(let r of e)this.writeEBML(r);else if(this.offsets.set(e,this.writer.getPos()),this.writeUnsignedInt(e.id),Array.isArray(e.data)){let r=this.writer.getPos(),s=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+s);let o=this.writer.getPos();if(this.dataOffsets.set(e,o),this.writeEBML(e.data),e.size!==-1){let a=this.writer.getPos()-o,n=this.writer.getPos();this.writer.seek(r),this.writeEBMLVarInt(a,s),this.writer.seek(n)}}else if(typeof e.data=="number"){let r=e.size??Be(e.data);this.writeEBMLVarInt(r),this.writeUnsignedInt(e.data,r)}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 re)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof X)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof ie){let r=e.size??Ne(e.data.value);this.writeEBMLVarInt(r),this.writeSignedInt(e.data.value,r)}}}beforeTrackAdd(e){if(this.format instanceof D)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 D?"webm":"matroska"},{id:17031,data:2},{id:17029,data:2}]};this.writeEBML(e)}createSeekHead(){let e=new Uint8Array([28,83,187,107]),r=new Uint8Array([21,73,169,102]),s=new Uint8Array([22,84,174,107]),o={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:r},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:s},{id:21420,size:5,data:0}]}]};this.seekHead=o}createSegmentInfo(){let e={id:17545,data:new X(0)};this.segmentDuration=e;let r={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:at},{id:22337,data:at},this.format._options.streamable?null:e]};this.segmentInfo=r}createTracks(){let e={id:374648427,data:[]};this.tracksElement=e;for(let r of this.trackDatas)e.data.push({id:174,data:[{id:215,data:r.track.id},{id:29637,data:r.track.id},{id:131,data:Tr[r.type]},{id:134,data:br[r.track.source._codec]},...r.type==="video"?[r.info.decoderConfig.description?{id:25506,data:P(r.info.decoderConfig.description)}:null,r.track.metadata.frameRate?{id:2352003,data:1e9/r.track.metadata.frameRate}:null,{id:224,data:[{id:176,data:r.info.width},{id:186,data:r.info.height},(()=>{if(r.info.decoderConfig.colorSpace){let s=r.info.decoderConfig.colorSpace;return ne(s)?{id:21936,data:[{id:21937,data:$[s.matrix]},{id:21946,data:Q[s.transfer]},{id:21947,data:H[s.primaries]},{id:21945,data:[1,2][Number(s.fullRange)]}]}:null}return null})()]}]:[],...r.type==="audio"?[r.info.decoderConfig.description?{id:25506,data:P(r.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new re(r.info.sampleRate)},{id:159,data:r.info.numberOfChannels}]}]:[],...r.type==="subtitle"?[{id:25506,data:x.encode(r.info.config.description)}]:[]]})}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:nt,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 c(this.segment),this.dataOffsets.get(this.segment)}getVideoTrackData(e,r){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;be(r),c(r),c(r.decoderConfig),c(r.decoderConfig.codedWidth!==void 0),c(r.decoderConfig.codedHeight!==void 0);let o={track:e,type:"video",info:{width:r.decoderConfig.codedWidth,height:r.decoderConfig.codedHeight,decoderConfig:r.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getAudioTrackData(e,r){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;Te(r),c(r),c(r.decoderConfig);let o={track:e,type:"audio",info:{numberOfChannels:r.decoderConfig.numberOfChannels,sampleRate:r.decoderConfig.sampleRate,decoderConfig:r.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getSubtitleTrackData(e,r){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;we(r),c(r),c(r.config);let o={track:e,type:"subtitle",info:{config:r.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}async addEncodedVideoChunk(e,r,s){let o=await this.mutex.acquire();try{let a=this.getVideoTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,r.timestamp,r.type==="key"),d=this.createInternalChunk(n,u,(r.duration??0)/1e6,r.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(a,d),a.chunkQueue.push(d),await this.interleaveChunks()}finally{o()}}async addEncodedAudioChunk(e,r,s){let o=await this.mutex.acquire();try{let a=this.getAudioTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,r.timestamp,r.type==="key"),d=this.createInternalChunk(n,u,(r.duration??0)/1e6,r.type);a.chunkQueue.push(d),await this.interleaveChunks()}finally{o()}}async addSubtitleCue(e,r,s){let o=await this.mutex.acquire();try{let a=this.getSubtitleTrackData(e,s),n=this.validateAndNormalizeTimestamp(a.track,1e6*r.timestamp,!0),u=r.text,d=Math.floor(n*1e3);j.lastIndex=0,u=u.replace(j,E=>{let k=le(E.slice(1,-1))-d;return`<${ce(k)}>`});let m=x.encode(u),f=`${r.settings??""} +`,a);u===-1&&(u=i.length);let c=le(e[2]),f=le(e[3])-c,w=i.slice(o,u).trim();i=i.slice(u).trimStart(),Z.lastIndex=0;let M={timestamp:c/1e3,duration:f/1e3,text:w,identifier:s,settings:n,notes:r},C={};this.preambleEmitted||(C.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(M,C)}}},Ct=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,le=t=>{let i=Ct.exec(t);if(!i)throw new Error("Expected match.");return 60*60*1e3*Number(i[1]||"0")+60*1e3*Number(i[2])+1e3*Number(i[3])+Number(i[4])},ce=t=>{let i=Math.floor(t/36e5),e=Math.floor(t%(60*60*1e3)/(60*1e3)),r=Math.floor(t%(60*1e3)/1e3),s=t%1e3;return i.toString().padStart(2,"0")+":"+e.toString().padStart(2,"0")+":"+r.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var J=class{constructor(i){this.writer=i;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap}writeU32(i){this.helperView.setUint32(0,i,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(i){this.helperView.setUint32(0,Math.floor(i/2**32),!1),this.helperView.setUint32(4,i,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(i){for(let e=0;e[(t%256+256)%256],h=t=>(A.setUint16(0,t,!1),[p[0],p[1]]),kt=t=>(A.setInt16(0,t,!1),[p[0],p[1]]),je=t=>(A.setUint32(0,t,!1),[p[1],p[2],p[3]]),l=t=>(A.setUint32(0,t,!1),[p[0],p[1],p[2],p[3]]),Le=t=>(A.setInt32(0,t,!1),[p[0],p[1],p[2],p[3]]),U=t=>(A.setUint32(0,Math.floor(t/2**32),!1),A.setUint32(4,t,!1),[p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]]),De=t=>(A.setInt16(0,2**8*t,!1),[p[0],p[1]]),_=t=>(A.setInt32(0,2**16*t,!1),[p[0],p[1],p[2],p[3]]),Ie=t=>(A.setInt32(0,2**30*t,!1),[p[0],p[1],p[2],p[3]]),Ue=(t,i)=>{let e=[],r=t;do{let s=r&127;r>>=7,e.length>0&&(s|=128),e.push(s),i!==void 0&&i--}while(r>0||i);return e.reverse()},g=(t,i=!1)=>{let e=Array(t.length).fill(null).map((r,s)=>t.charCodeAt(s));return i&&e.push(0),e},We=t=>{let i=null;for(let e of t)(!i||e.timestamp>i.timestamp)&&(i=e);return i},qe=t=>{let i=t*(Math.PI/180),e=Math.cos(i),r=Math.sin(i);return[e,r,0,-r,e,0,0,0,1]},Ke=qe(0),Xe=t=>[_(t[0]),_(t[1]),Ie(t[2]),_(t[3]),_(t[4]),Ie(t[5]),_(t[6]),_(t[7]),Ie(t[8])],b=(t,i,e)=>({type:t,contents:i&&new Uint8Array(i.flat(10)),children:e}),x=(t,i,e,r,s)=>b(t,[T(i),je(e),r??[]],s),Ge=t=>{let i=512;return t.fragmented?b("ftyp",[g("iso5"),l(i),g("iso5"),g("iso6"),g("mp41")]):b("ftyp",[g("isom"),l(i),g("isom"),t.holdsAvc?g("avc1"):[],g("mp41")])},me=t=>({type:"mdat",largeSize:t}),Ye=t=>({type:"free",size:t}),ee=(t,i,e=!1)=>b("moov",void 0,[gt(i,t),...t.map(r=>St(r,i)),e?rr(t):null]),gt=(t,i)=>{let e=v(Math.max(0,...i.filter(o=>o.samples.length>0).map(o=>{let n=We(o.samples);return n.timestamp+n.duration})),de),r=Math.max(0,...i.map(o=>o.track.id))+1,s=!P(t)||!P(e),a=s?U:l;return x("mvhd",+s,0,[a(t),a(t),l(de),a(e),_(1),De(1),Array(10).fill(0),Xe(Ke),Array(24).fill(0),l(r)])},St=(t,i)=>b("trak",void 0,[yt(t,i),vt(t,i)]),yt=(t,i)=>{let e=We(t.samples),r=v(e?e.timestamp+e.duration:0,de),s=!P(i)||!P(r),a=s?U:l,o;if(t.type==="video"){let n=t.track.metadata.rotation;o=n===void 0||typeof n=="number"?qe(n??0):n}else o=Ke;return x("tkhd",+s,3,[a(i),a(i),l(t.track.id),l(0),a(r),Array(8).fill(0),h(0),h(t.track.id),De(t.type==="audio"?1:0),h(0),Xe(o),_(t.type==="video"?t.info.width:0),_(t.type==="video"?t.info.height:0)])},vt=(t,i)=>b("mdia",void 0,[_t(t,i),Et(t),Mt(t)]),_t=(t,i)=>{let e=We(t.samples),r=v(e?e.timestamp+e.duration:0,t.timescale),s=!P(i)||!P(r),a=s?U:l;return x("mdhd",+s,0,[a(i),a(i),l(t.timescale),a(r),h(21956),h(0)])},At={video:"vide",audio:"soun",subtitle:"text"},Ot={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},Et=t=>x("hdlr",0,0,[g("mhlr"),g(At[t.type]),l(0),l(0),l(0),g(Ot[t.type],!0)]),Mt=t=>b("minf",void 0,[Bt[t.type](),It(),Wt(t)]),Vt=()=>x("vmhd",0,1,[h(0),h(0),h(0),h(0)]),zt=()=>x("smhd",0,0,[h(0),h(0)]),Pt=()=>x("nmhd",0,0),Bt={video:Vt,audio:zt,subtitle:Pt},It=()=>b("dinf",void 0,[Ut()]),Ut=()=>x("dref",0,0,[l(1)],[Dt()]),Dt=()=>x("url ",0,1),Wt=t=>{let i=t.compositionTimeOffsetTable.length>1||t.compositionTimeOffsetTable.some(e=>e.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[Rt(t),Gt(t),Yt(t),Zt(t),Jt(t),er(t),i?tr(t):null])},Rt=t=>{let i;return t.type==="video"?i=Ft(dr[t.track.source._codec],t):t.type==="audio"?i=jt(fr[t.track.source._codec],t):t.type==="subtitle"&&(i=Kt(hr[t.track.source._codec],t)),d(i),x("stsd",0,0,[l(1)],[i])},Ft=(t,i)=>b(t,[Array(6).fill(0),h(1),h(0),h(0),Array(12).fill(0),h(i.info.width),h(i.info.height),l(4718592),l(4718592),l(0),h(1),Array(32).fill(0),h(24),kt(65535)],[mr[i.track.source._codec](i),ne(i.info.decoderConfig.colorSpace)?Nt(i):null]),Nt=t=>b("colr",[g("nclx"),h(H[t.info.decoderConfig.colorSpace.primaries]),h(Q[t.info.decoderConfig.colorSpace.transfer]),h($[t.info.decoderConfig.colorSpace.matrix]),T((t.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),Ht=t=>t.info.decoderConfig&&b("avcC",[...I(t.info.decoderConfig.description)]),Qt=t=>t.info.decoderConfig&&b("hvcC",[...I(t.info.decoderConfig.description)]),$e=t=>{if(!t.info.decoderConfig)return null;let i=t.info.decoderConfig;d(i.colorSpace);let e=i.codec.split("."),r=Number(e[1]),s=Number(e[2]),n=(Number(e[3])<<4)+(0<<1)+Number(i.colorSpace.fullRange);return x("vpcC",1,0,[T(r),T(s),T(n),T(2),T(2),T(2),h(0)])},$t=()=>{let e=(1<<7)+1;return b("av1C",[e,0,0,0])},jt=(t,i)=>b(t,[Array(6).fill(0),h(1),h(0),h(0),l(0),h(i.info.numberOfChannels),h(16),h(0),h(0),_(i.info.sampleRate)],[pr[i.track.source._codec](i)]),Lt=t=>{let e=[...I(t.info.decoderConfig.description??new ArrayBuffer(0))];return e=[...T(64),...T(21),...je(0),...l(0),...l(0),...T(5),...Ue(e.length),...e],e=[...h(1),...T(0),...T(4),...Ue(e.length),...e,...T(6),...T(1),...T(2)],e=[...T(3),...Ue(e.length),...e],x("esds",0,0,e)},qt=t=>{let i=3840,e=0,r=t.info.decoderConfig?.description;if(r){d(r.byteLength<18);let s=ArrayBuffer.isView(r)?new DataView(r.buffer,r.byteOffset,r.byteLength):new DataView(r);i=s.getUint16(10,!0),e=s.getInt16(14,!0)}return b("dOps",[T(0),T(t.info.numberOfChannels),h(i),l(t.info.sampleRate),De(e),T(0)])},Kt=(t,i)=>b(t,[Array(6).fill(0),h(1)],[br[i.track.source._codec](i)]),Xt=t=>b("vttC",[...y.encode(t.info.config.description)]);var Gt=t=>x("stts",0,0,[l(t.timeToSampleTable.length),t.timeToSampleTable.map(i=>[l(i.sampleCount),l(i.sampleDelta)])]),Yt=t=>{if(t.samples.every(e=>e.type==="key"))return null;let i=[...t.samples.entries()].filter(([,e])=>e.type==="key");return x("stss",0,0,[l(i.length),i.map(([e])=>l(e+1))])},Zt=t=>x("stsc",0,0,[l(t.compactlyCodedChunkTable.length),t.compactlyCodedChunkTable.map(i=>[l(i.firstChunk),l(i.samplesPerChunk),l(1)])]),Jt=t=>x("stsz",0,0,[l(0),l(t.samples.length),t.samples.map(i=>l(i.size))]),er=t=>t.finalizedChunks.length>0&&S(t.finalizedChunks).offset>=2**32?x("co64",0,0,[l(t.finalizedChunks.length),t.finalizedChunks.map(i=>U(i.offset))]):x("stco",0,0,[l(t.finalizedChunks.length),t.finalizedChunks.map(i=>l(i.offset))]),tr=t=>x("ctts",0,0,[l(t.compositionTimeOffsetTable.length),t.compositionTimeOffsetTable.map(i=>[l(i.sampleCount),l(i.sampleCompositionTimeOffset)])]),rr=t=>b("mvex",void 0,t.map(ir)),ir=t=>x("trex",0,0,[l(t.track.id),l(1),l(0),l(0),l(0)]),Re=(t,i)=>b("moof",void 0,[sr(t),...i.map(ar)]),sr=t=>x("mfhd",0,0,[l(t)]),Ze=t=>{let i=0,e=0,r=0,s=0,a=t.type==="delta";return e|=+a,a?i|=1:i|=2,i<<24|e<<16|r<<8|s},ar=t=>b("traf",void 0,[or(t),nr(t),ur(t)]),or=t=>{d(t.currentChunk);let i=0;i|=8,i|=16,i|=32,i|=131072;let e=t.currentChunk.samples[1]??t.currentChunk.samples[0],r={duration:e.timescaleUnitsToNextSample,size:e.size,flags:Ze(e)};return x("tfhd",0,i,[l(t.track.id),l(r.duration),l(r.size),l(r.flags)])},nr=t=>(d(t.currentChunk),x("tfdt",1,0,[U(v(t.currentChunk.startTimestamp,t.timescale))])),ur=t=>{d(t.currentChunk);let i=t.currentChunk.samples.map(k=>k.timescaleUnitsToNextSample),e=t.currentChunk.samples.map(k=>k.size),r=t.currentChunk.samples.map(Ze),s=t.currentChunk.samples.map(k=>v(k.timestamp-k.decodeTimestamp,t.timescale)),a=new Set(i),o=new Set(e),n=new Set(r),u=new Set(s),c=n.size===2&&r[0]!==r[1],m=a.size>1,f=o.size>1,w=!c&&n.size>1,M=u.size>1||[...u].some(k=>k!==0),C=0;return C|=1,C|=4*+c,C|=256*+m,C|=512*+f,C|=1024*+w,C|=2048*+M,x("trun",1,C,[l(t.currentChunk.samples.length),l(t.currentChunk.offset-t.currentChunk.moofOffset||0),c?l(r[0]):[],t.currentChunk.samples.map((k,F)=>[m?l(i[F]):[],f?l(e[F]):[],w?l(r[F]):[],M?Le(s[F]):[]])])},Je=t=>b("mfra",void 0,[...t.map(lr),cr()]),lr=(t,i)=>x("tfra",1,0,[l(t.track.id),l(63),l(t.finalizedChunks.length),t.finalizedChunks.map(r=>[U(v(r.startTimestamp,t.timescale)),U(r.moofOffset),l(i+1),l(1),l(1)])]),cr=()=>x("mfro",0,0,[l(0)]),et=()=>b("vtte"),tt=(t,i,e,r,s)=>b("vttc",void 0,[s!==null?b("vsid",[Le(s)]):null,e!==null?b("iden",[...y.encode(e)]):null,i!==null?b("ctim",[...y.encode(ce(i))]):null,r!==null?b("sttg",[...y.encode(r)]):null,b("payl",[...y.encode(t)])]),rt=t=>b("vtta",[...y.encode(t)]),dr={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},mr={avc:Ht,hevc:Qt,vp8:$e,vp9:$e,av1:$t},fr={aac:"mp4a",opus:"Opus"},pr={aac:Lt,opus:qt},hr={webvtt:"wvtt"},br={webvtt:Xt};var L=class{constructor(i){this.mutex=new N;this.trackTimestampInfo=new WeakMap;this.output=i}beforeTrackAdd(i){}onTrackClose(i){}validateAndNormalizeTimestamp(i,e,r){let s=e/1e6,a=this.trackTimestampInfo.get(i);if(!a){if(!r)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).`);a={timestampOffset:s,maxTimestamp:i.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:i.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(i,a)}if(i.source._offsetTimestamps&&(s-=a.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(ss.start-a.start);e.push({start:r[0].start,size:r[0].data.byteLength});for(let s=1;sc.start<=r&&rwr){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 s={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(s),this.chunks.sort((a,o)=>a.start-o.start),this.chunks.indexOf(s)}queueChunksForFlush(e=!1){d(this.writer);for(let r=0;r{if(t==="avc"){let a=Math.ceil(i/16)*Math.ceil(e/16),o=it.find(f=>a<=f.maxMacroblocks&&r<=f.maxBitrate)??S(it),n=o?o.level:0,u="64".padStart(2,"0"),c="00",m=n.toString(16).padStart(2,"0");return`avc1.${u}${c}${m}`}else if(t==="hevc"){let s=0,a=1,o="6",n=i*e,u=st.find(f=>n<=f.maxPictureSize&&r<=f.maxBitrate)??S(st);return`hev1.${s===0?"":String.fromCharCode(65+s-1)}${a}.${o}.${u.tier}${u.level}.B0`}else{if(t==="vp8")return"vp8";if(t==="vp9"){let s="00",a=i*e,o=at.find(u=>a<=u.maxPictureSize&&r<=u.maxBitrate)??S(at);return`vp09.${s}.${o.level}.08`}else if(t==="av1"){let a=i*e,o=ot.find(u=>a<=u.maxPictureSize&&r<=u.maxBitrate)??S(ot);return`av01.0.${o.level.toString().padStart(2,"0")}${o.tier}.08`}}throw new TypeError(`Unhandled codec '${t}'.`)},ut=(t,i,e)=>{if(t==="aac")return i>=2&&e<=24e3?"mp4a.40.29":e<=24e3?"mp4a.40.5":"mp4a.40.2";if(t==="opus")return"opus";if(t==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${t}'.`)},be=t=>{if(!t)throw new TypeError("Video chunk metadata must be provided.");if(typeof t!="object")throw new TypeError("Video chunk metadata must be an object.");if(!t.decoderConfig)throw new TypeError("Video chunk metadata must include a decoder configuration.");if(typeof t.decoderConfig!="object")throw new TypeError("Video chunk metadata decoder configuration must be an object.");if(typeof t.decoderConfig.codec!="string")throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(t.decoderConfig.codedWidth)||t.decoderConfig.codedWidth<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");if(!Number.isInteger(t.decoderConfig.codedHeight)||t.decoderConfig.codedHeight<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");if(t.decoderConfig.description!==void 0&&!Be(t.decoderConfig.description))throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(t.decoderConfig.colorSpace!==void 0){let{colorSpace:i}=t.decoderConfig;if(typeof i!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let e=Object.keys(H);if(i.primaries!=null&&!e.includes(i.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${e.join(", ")}.`);let r=Object.keys(Q);if(i.transfer!=null&&!r.includes(i.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${r.join(", ")}.`);let s=Object.keys($);if(i.matrix!=null&&!s.includes(i.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(i.fullRange!=null&&typeof i.fullRange!="boolean")throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.")}if((t.decoderConfig.codec.startsWith("avc1")||t.decoderConfig.codec.startsWith("avc3"))&&!t.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((t.decoderConfig.codec.startsWith("hev1")||t.decoderConfig.codec.startsWith("hvc1"))&&!t.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((t.decoderConfig.codec==="vp8"||t.decoderConfig.codec.startsWith("vp09"))&&t.decoderConfig.colorSpace===void 0)throw new TypeError("Video chunk metadata decoder configuration for VP8/VP9 must include a colorSpace.")},xe=t=>{if(!t)throw new TypeError("Audio chunk metadata must be provided.");if(typeof t!="object")throw new TypeError("Audio chunk metadata must be an object.");if(!t.decoderConfig)throw new TypeError("Audio chunk metadata must include a decoder configuration.");if(typeof t.decoderConfig!="object")throw new TypeError("Audio chunk metadata decoder configuration must be an object.");if(typeof t.decoderConfig.codec!="string")throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(t.decoderConfig.sampleRate)||t.decoderConfig.sampleRate<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");if(!Number.isInteger(t.decoderConfig.numberOfChannels)||t.decoderConfig.numberOfChannels<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");if(t.decoderConfig.description!==void 0&&!Be(t.decoderConfig.description))throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(t.decoderConfig.codec==="opus"&&t.decoderConfig.description&&t.decoderConfig.description.byteLength<18)throw new TypeError("Invalid decoder description provided for Opus; must be at least 18 bytes long.")},we=t=>{if(!t)throw new TypeError("Subtitle metadata must be provided.");if(typeof t!="object")throw new TypeError("Subtitle metadata must be an object.");if(!t.config)throw new TypeError("Subtitle metadata must include a config object.");if(typeof t.config!="object")throw new TypeError("Subtitle metadata config must be an object.");if(typeof t.config.description!="string")throw new TypeError("Subtitle metadata config description must be a string.")};var de=1e3,Tr=2082844800,v=(t,i,e=!0)=>{let r=t*i;return e?Math.round(r):r},Te=class extends L{constructor(e,r){super(e);this.timestampsMustStartAtZero=!0;this.auxTarget=new K;this.auxWriter=this.auxTarget._createWriter();this.auxBoxWriter=new J(this.auxWriter);this.ftypSize=null;this.mdat=null;this.trackDatas=[];this.creationTime=Math.floor(Date.now()/1e3)+Tr;this.finalizedChunks=[];this.nextFragmentNumber=1;this.writer=e._writer,this.boxWriter=new J(this.writer),this.fastStart=r._options.fastStart??(this.writer instanceof q?"in-memory":!1),(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),r=this.output._tracks.some(s=>s.type==="video"&&s.source._codec==="avc");this.boxWriter.writeBox(Ge({holdsAvc:r,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=me(!1):this.fastStart==="fragmented"||(this.mdat=me(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;be(r),d(r),d(r.decoderConfig),d(r.decoderConfig.codedWidth!==void 0),d(r.decoderConfig.codedHeight!==void 0);let a={track:e,type:"video",info:{width:r.decoderConfig.codedWidth,height:r.decoderConfig.codedHeight,decoderConfig:r.decoderConfig},timescale:e.metadata.frameRate??57600,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getAudioTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;xe(r),d(r),d(r.decoderConfig);let a={track:e,type:"audio",info:{numberOfChannels:r.decoderConfig.numberOfChannels,sampleRate:r.decoderConfig.sampleRate,decoderConfig:r.decoderConfig},timescale:r.decoderConfig.sampleRate,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getSubtitleTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;we(r),d(r),d(r.config);let a={track:e,type:"subtitle",info:{config:r.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(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),this.validateAndNormalizeTimestamp(e,0,!0),a}async addEncodedVideoChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createSampleForTrack(o,n,u,(r.duration??0)/1e6,r.type);await this.registerSample(o,c)}finally{a()}}async addEncodedAudioChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createSampleForTrack(o,n,u,(r.duration??0)/1e6,r.type);await this.registerSample(o,c)}finally{a()}}async addSubtitleCue(e,r,s){let a=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,s);this.validateAndNormalizeTimestamp(o.track,1e6*r.timestamp,!0),e.source._codec==="webvtt"&&(o.cueQueue.push(r),await this.processWebVTTCues(o,r.timestamp))}finally{a()}}async processWebVTTCues(e,r){for(;e.cueQueue.length>0;){let s=new Set([]);for(let m of e.cueQueue)d(m.timestamp<=r),d(e.lastCueEndTimestamp<=m.timestamp+m.duration),s.add(Math.max(m.timestamp,e.lastCueEndTimestamp)),s.add(m.timestamp+m.duration);let a=[...s].sort((m,f)=>m-f),o=a[0],n=a[1]??o;if(r=n)break;j.lastIndex=0;let w=j.test(f.text),M=f.timestamp+f.duration,C=e.cueToSourceId.get(f);if(C===void 0&&ns.timestamp).sort((s,a)=>s-a);for(let s=0;s{if(e===n)return r.type==="key";let u=n.sampleQueue[0];return u&&u.type==="key"});a>=1&&o&&(s=!0,await this.finalizeFragment())}else s=a>=.5}s&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:r.timestamp,samples:[],offset:null,moofOffset:null}),d(e.currentChunk),e.currentChunk.samples.push(r),e.timestampProcessingQueue.push(r)}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||S(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 r of e.currentChunk.samples)d(r.data),this.writer.write(r.data),r.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(r=>r.track===e))return;e:for(;;){let e=null,r=1/0;for(let a of this.trackDatas){if(a.sampleQueue.length===0&&!a.track.source._closed)break e;a.sampleQueue.length>0&&a.sampleQueue[0].timestamp=2**32&&(u.largeSize=!0,m=this.boxWriter.measureBox(u)+c),u.size=m,this.boxWriter.writeBox(u)}for(let u of this.trackDatas){u.currentChunk.offset=this.writer.getPos(),u.currentChunk.moofOffset=s;for(let c of u.currentChunk.samples)this.writer.write(c.data),c.data=null}let o=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(a));let n=Re(r,this.trackDatas);this.boxWriter.writeBox(n),this.writer.seek(o);for(let u of this.trackDatas)u.finalizedChunks.push(u.currentChunk),this.finalizedChunks.push(u.currentChunk),u.currentChunk=null;e&&await this.writer.flush()}async onTrackClose(e){let r=await this.mutex.acquire();if(e.type==="subtitle"&&e.source._codec==="webvtt"){let s=this.trackDatas.find(a=>a.track===e);s&&await this.processWebVTTCues(s,1/0)}this.fastStart==="fragmented"&&await this.interleaveSamples(),r()}async finalize(){let e=await this.mutex.acquire();for(let r of this.trackDatas)r.type==="subtitle"&&r.track.source._codec==="webvtt"&&await this.processWebVTTCues(r,1/0);if(this.fastStart==="fragmented"){for(let r of this.trackDatas){for(let s of r.sampleQueue)await this.addSampleToTrack(r,s);this.processTimestamps(r)}await this.finalizeFragment(!1)}else for(let r of this.trackDatas)this.processTimestamps(r),await this.finalizeCurrentChunk(r);if(this.fastStart==="in-memory"){d(this.mdat);let r;for(let a=0;a<2;a++){let o=ee(this.trackDatas,this.creationTime),n=this.boxWriter.measureBox(o);r=this.boxWriter.measureBox(this.mdat);let u=this.writer.getPos()+n+r;for(let c of this.finalizedChunks){c.offset=u;for(let{data:m}of c.samples)d(m),u+=m.byteLength,r+=m.byteLength}if(u<2**32)break;r>=2**32&&(this.mdat.largeSize=!0)}let s=ee(this.trackDatas,this.creationTime);this.boxWriter.writeBox(s),this.mdat.size=r,this.boxWriter.writeBox(this.mdat);for(let a of this.finalizedChunks)for(let o of a.samples)d(o.data),this.writer.write(o.data),o.data=null}else if(this.fastStart==="fragmented"){let r=this.writer.getPos(),s=Je(this.trackDatas);this.boxWriter.writeBox(s);let a=this.writer.getPos()-r;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(a)}else{d(this.mdat),d(this.ftypSize!==null);let r=this.boxWriter.offsets.get(this.mdat);d(r!==void 0);let s=this.writer.getPos()-r;this.mdat.size=s,this.mdat.largeSize=s>=2**32,this.boxWriter.patchBox(this.mdat);let a=ee(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(a);let o=r-this.writer.getPos();this.boxWriter.writeBox(Ye(o))}else this.boxWriter.writeBox(a)}e()}};var re=class{constructor(i){this.value=i}},X=class{constructor(i){this.value=i}},ie=class{constructor(i){this.value=i}};var Fe=t=>t<256?1:t<65536?2:t<1<<24?3:t<2**32?4:t<2**40?5:6,Ne=t=>t>=-64&&t<64?1:t>=-8192&&t<8192?2:t>=-(1<<20)&&t<1<<20?3:t>=-(1<<27)&&t<1<<27?4:t>=-(2**34)&&t<2**34?5:6,lt=t=>{if(t<127)return 1;if(t<16383)return 2;if(t<(1<<21)-1)return 3;if(t<(1<<28)-1)return 4;if(t<2**35-1)return 5;if(t<2**42-1)return 6;throw new Error("EBML VINT size not supported "+t)};var He=2**15,ct="https://github.com/Vanilagy/webm-muxer",dt=6,mt=5,Cr={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"},kr={video:1,audio:2,subtitle:17},Ce=class extends L{constructor(e,r){super(e);this.timestampsMustStartAtZero=!1;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap;this.dataOffsets=new WeakMap;this.trackDatas=[];this.segment=null;this.segmentInfo=null;this.seekHead=null;this.tracksElement=null;this.segmentDuration=null;this.cues=null;this.currentCluster=null;this.currentClusterMsTimestamp=null;this.trackDatasInCurrentCluster=new Set;this.duration=0;this.writer=e._writer,this.format=r,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,r=Fe(e)){let s=0;switch(r){case 6:this.helperView.setUint8(s++,e/2**40|0);case 5:this.helperView.setUint8(s++,e/2**32|0);case 4:this.helperView.setUint8(s++,e>>24);case 3:this.helperView.setUint8(s++,e>>16);case 2:this.helperView.setUint8(s++,e>>8);case 1:this.helperView.setUint8(s++,e);break;default:throw new Error("Bad UINT size "+r)}this.writer.write(this.helper.subarray(0,s))}writeSignedInt(e,r=Ne(e)){e<0&&(e+=2**(r*8)),this.writeUnsignedInt(e,r)}writeEBMLVarInt(e,r=lt(e)){let s=0;switch(r){case 1:this.helperView.setUint8(s++,128|e);break;case 2:this.helperView.setUint8(s++,64|e>>8),this.helperView.setUint8(s++,e);break;case 3:this.helperView.setUint8(s++,32|e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 4:this.helperView.setUint8(s++,16|e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 5:this.helperView.setUint8(s++,8|e/2**32&7),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 6:this.helperView.setUint8(s++,4|e/2**40&3),this.helperView.setUint8(s++,e/2**32|0),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;default:throw new Error("Bad EBML VINT size "+r)}this.writer.write(this.helper.subarray(0,s))}writeString(e){this.writer.write(new Uint8Array(e.split("").map(r=>r.charCodeAt(0))))}writeEBML(e){if(e!==null){if(e instanceof Uint8Array)this.writer.write(e);else if(Array.isArray(e))for(let r of e)this.writeEBML(r);else if(this.offsets.set(e,this.writer.getPos()),this.writeUnsignedInt(e.id),Array.isArray(e.data)){let r=this.writer.getPos(),s=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+s);let a=this.writer.getPos();if(this.dataOffsets.set(e,a),this.writeEBML(e.data),e.size!==-1){let o=this.writer.getPos()-a,n=this.writer.getPos();this.writer.seek(r),this.writeEBMLVarInt(o,s),this.writer.seek(n)}}else if(typeof e.data=="number"){let r=e.size??Fe(e.data);this.writeEBMLVarInt(r),this.writeUnsignedInt(e.data,r)}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 re)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof X)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof ie){let r=e.size??Ne(e.data.value);this.writeEBMLVarInt(r),this.writeSignedInt(e.data.value,r)}}}beforeTrackAdd(e){if(this.format instanceof D)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 D?"webm":"matroska"},{id:17031,data:2},{id:17029,data:2}]};this.writeEBML(e)}createSeekHead(){let e=new Uint8Array([28,83,187,107]),r=new Uint8Array([21,73,169,102]),s=new Uint8Array([22,84,174,107]),a={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:r},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:s},{id:21420,size:5,data:0}]}]};this.seekHead=a}createSegmentInfo(){let e={id:17545,data:new X(0)};this.segmentDuration=e;let r={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:ct},{id:22337,data:ct},this.format._options.streamable?null:e]};this.segmentInfo=r}createTracks(){let e={id:374648427,data:[]};this.tracksElement=e;for(let r of this.trackDatas)e.data.push({id:174,data:[{id:215,data:r.track.id},{id:29637,data:r.track.id},{id:131,data:kr[r.type]},{id:134,data:Cr[r.track.source._codec]},...r.type==="video"?[r.info.decoderConfig.description?{id:25506,data:I(r.info.decoderConfig.description)}:null,r.track.metadata.frameRate?{id:2352003,data:1e9/r.track.metadata.frameRate}:null,{id:224,data:[{id:176,data:r.info.width},{id:186,data:r.info.height},(()=>{if(r.info.decoderConfig.colorSpace){let s=r.info.decoderConfig.colorSpace;return ne(s)?{id:21936,data:[{id:21937,data:$[s.matrix]},{id:21946,data:Q[s.transfer]},{id:21947,data:H[s.primaries]},{id:21945,data:[1,2][Number(s.fullRange)]}]}:null}return null})()]}]:[],...r.type==="audio"?[r.info.decoderConfig.description?{id:25506,data:I(r.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new re(r.info.sampleRate)},{id:159,data:r.info.numberOfChannels}]}]:[],...r.type==="subtitle"?[{id:25506,data:y.encode(r.info.config.description)}]:[]]})}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:dt,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,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;be(r),d(r),d(r.decoderConfig),d(r.decoderConfig.codedWidth!==void 0),d(r.decoderConfig.codedHeight!==void 0);let a={track:e,type:"video",info:{width:r.decoderConfig.codedWidth,height:r.decoderConfig.codedHeight,decoderConfig:r.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getAudioTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;xe(r),d(r),d(r.decoderConfig);let a={track:e,type:"audio",info:{numberOfChannels:r.decoderConfig.numberOfChannels,sampleRate:r.decoderConfig.sampleRate,decoderConfig:r.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getSubtitleTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;we(r),d(r),d(r.config);let a={track:e,type:"subtitle",info:{config:r.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}async addEncodedVideoChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createInternalChunk(n,u,(r.duration??0)/1e6,r.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(o,c),o.chunkQueue.push(c),await this.interleaveChunks()}finally{a()}}async addEncodedAudioChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createInternalChunk(n,u,(r.duration??0)/1e6,r.type);o.chunkQueue.push(c),await this.interleaveChunks()}finally{a()}}async addSubtitleCue(e,r,s){let a=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,s),n=this.validateAndNormalizeTimestamp(o.track,1e6*r.timestamp,!0),u=r.text,c=Math.floor(n*1e3);j.lastIndex=0,u=u.replace(j,M=>{let k=le(M.slice(1,-1))-c;return`<${ce(k)}>`});let m=y.encode(u),f=`${r.settings??""} ${r.identifier??""} -${r.notes??""}`,w=this.createInternalChunk(m,n,r.duration,"key",f.trim()?x.encode(f):null);a.chunkQueue.push(w),await this.interleaveChunks()}finally{o()}}async interleaveChunks(){for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(r=>r.track===e))return;e:for(;;){let e=null,r=1/0;for(let o of this.trackDatas){if(o.chunkQueue.length===0&&!o.track.source._closed)break e;o.chunkQueue.length>0&&o.chunkQueue[0].timestamp=2&&s++;let d={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];Qe(r.data,s+0,s+3,d)}createInternalChunk(e,r,s,o,a=null){return{data:e,type:o,timestamp:r,duration:s,additions:a}}writeBlock(e,r){this.segment||(this.createTracks(),this.createSegment());let s=Math.floor(1e3*r.timestamp),o=this.trackDatas.every(f=>{if(f.track.source._closed)return!0;if(e===f)return r.type==="key";let w=f.chunkQueue[0];return w&&w.type==="key"});(!this.currentCluster||o&&s-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(s);let a=s-this.currentClusterMsTimestamp;if(a<0)return;if(a>=He)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${He} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${He} milliseconds.`);let u=new Uint8Array(4),d=new DataView(u.buffer);d.setUint8(0,128|e.track.id),d.setInt16(1,a,!1);let m=Math.floor(1e3*r.duration);if(m===0&&!r.additions){d.setUint8(3,+(r.type==="key")<<7);let f={id:163,data:[u,r.data]};this.writeEBML(f)}else{let f={id:160,data:[{id:161,data:[u,r.data]},r.type==="delta"?{id:251,data:new ie(e.lastWrittenMsTimestamp-s)}:null,r.additions?{id:30113,data:[{id:166,data:[{id:165,data:r.additions},{id:238,data:1}]}]}:null,m>0?{id:155,data:m}:null]};this.writeEBML(f)}this.duration=Math.max(this.duration,s+m),e.lastWrittenMsTimestamp=s,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:ut,data:[{id:231,data:e}]},this.writeEBML(this.currentCluster),this.currentClusterMsTimestamp=e,this.trackDatasInCurrentCluster.clear()}finalizeCurrentCluster(){c(this.currentCluster);let e=this.writer.getPos()-this.dataOffsets.get(this.currentCluster),r=this.writer.getPos();this.writer.seek(this.offsets.get(this.currentCluster)+4),this.writeEBMLVarInt(e,ut),this.writer.seek(r);let s=this.offsets.get(this.currentCluster)-this.segmentDataOffset;c(this.cues),this.cues.data.push({id:187,data:[{id:179,data:this.currentClusterMsTimestamp},...[...this.trackDatasInCurrentCluster].map(o=>({id:183,data:[{id:247,data:o.track.id},{id:241,data:s}]}))]})}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 r of this.trackDatas)for(;r.chunkQueue.length>0;)this.writeBlock(r,r.chunkQueue.shift());if(!this.format._options.streamable&&this.currentCluster&&this.finalizeCurrentCluster(),c(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let r=this.writer.getPos(),s=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(s,nt),this.segmentDuration.data=new X(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(r)}e()}};var M=class{},ke=class extends M{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(i.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=i}_createMuxer(i){return new Ce(i,this)}},se=class extends M{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.streamable!==void 0&&typeof i.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=i}_createMuxer(i){return new ge(i,this)}},D=class extends se{};var G=["avc","hevc","vp8","vp9","av1"],Y=["aac","opus"],ye=["webvtt"],W=class{constructor(){this._connectedTrack=null;this._closed=!1;this._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)}},_=class extends W{constructor(e){super();this._connectedTrack=null;if(!G.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${G.join(", ")}.`);this._codec=e}},xe=class extends _{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,i,e)}},wr=5,Cr=t=>{if(!t||typeof t!="object")throw new TypeError("Codec config must be an object.");if(!G.includes(t.codec))throw new TypeError(`Invalid video codec '${t.codec}'. Must be one of: ${G.join(", ")}.`);if(!Number.isInteger(t.bitrate)||t.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.");if(t.latencyMode!==void 0&&["quality","realtime"].includes(t.latencyMode))throw new TypeError("config.latencyMode, when provided, must be 'quality' or 'realtime'.")},oe=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastMultipleOfKeyFrameInterval=-1;this.lastWidth=null;this.lastHeight=null;Cr(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(i.codedWidth!==this.lastWidth||i.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${i.codedWidth}x${i.codedHeight}.`)}else this.lastWidth=i.codedWidth,this.lastHeight=i.codedHeight;this.ensureEncoder(i),c(this.encoder);let e=Math.floor(i.timestamp/1e6/wr);this.encoder.encode(i,{keyFrame:e!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=e,this.encoder.encodeQueueSize>=4&&await new Promise(r=>this.encoder.addEventListener("dequeue",r,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new VideoEncoder({output:(e,r)=>this.muxer.addEncodedVideoChunk(this.source._connectedTrack,e,r),error:e=>console.error("Video encode error:",e)}),this.encoder.configure({codec:it(this.codecConfig.codec,i.codedWidth,i.codedHeight),width:i.codedWidth,height:i.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode}),c(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Se=class extends _{constructor(i){super(i.codec),this._encoder=new oe(this,i)}digest(i){if(!(i instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},ve=class extends _{constructor(i,e){if(!(i instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(e.codec),this._encoder=new oe(this,e),this._canvas=i}digest(i,e=0){if(!Number.isFinite(i)||i<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(e)||e<0)throw new TypeError("duration must be a non-negative number.");let r=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*i),duration:Math.round(1e6*e),alpha:"discard"}),s=this._encoder.digest(r);return r.close(),s}_flush(){return this._encoder.flush()}},Ae=class extends _{constructor(e,r){if(!(e instanceof MediaStreamTrack)||e.kind!=="video")throw new TypeError("track must be a video MediaStreamTrack.");r={...r,latencyMode:"realtime"};super(r.codec);this._abortController=null;this._offsetTimestamps=!0;this._encoder=new oe(this,r),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),r=new WritableStream({write:s=>{this._encoder.digest(s),s.close()}});e.readable.pipeTo(r,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},O=class extends W{constructor(e){super();this._connectedTrack=null;if(!Y.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${Y.join(", ")}.`);this._codec=e}},_e=class extends O{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,i,e)}},gr=t=>{if(!t||typeof t!="object")throw new TypeError("Codec config must be an object.");if(!Y.includes(t.codec))throw new TypeError(`Invalid audio codec '${t.codec}'. Must be one of: ${Y.join(", ")}.`);if(!Number.isInteger(t.bitrate)||t.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},ae=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastNumberOfChannels=null;this.lastSampleRate=null;gr(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(i.numberOfChannels!==this.lastNumberOfChannels||i.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${i.numberOfChannels} channels at ${i.sampleRate} Hz.`)}else this.lastNumberOfChannels=i.numberOfChannels,this.lastSampleRate=i.sampleRate;this.ensureEncoder(i),c(this.encoder),this.encoder.encode(i),this.encoder.encodeQueueSize>=4&&await new Promise(e=>this.encoder.addEventListener("dequeue",e,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new AudioEncoder({output:(e,r)=>this.muxer.addEncodedAudioChunk(this.source._connectedTrack,e,r),error:e=>console.error("Audio encode error:",e)}),this.encoder.configure({codec:st(this.codecConfig.codec,i.numberOfChannels,i.sampleRate),numberOfChannels:i.numberOfChannels,sampleRate:i.sampleRate,bitrate:this.codecConfig.bitrate}),c(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Oe=class extends O{constructor(i){super(i.codec),this._encoder=new ae(this,i)}digest(i){if(!(i instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},Ee=class extends O{constructor(e){super(e.codec);this._accumulatedFrameCount=0;this._encoder=new ae(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let r=e.numberOfChannels,s=e.sampleRate,o=e.length,a=new Float32Array(r*o);for(let d=0;d{this._encoder.digest(s),s.close()}});e.readable.pipeTo(r,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},R=class extends W{constructor(e){super();this._connectedTrack=null;if(!ye.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${ye.join(", ")}.`);this._codec=e}},Me=class extends R{constructor(i){super(i),this._parser=new ue({codec:i,output:(e,r)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,e,r),error:e=>console.error("Subtitle parse error:",e)})}digest(i){if(typeof i!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(i),this._connectedTrack.output._muxer.mutex.currentPromise}};var Ie=class{constructor(i){this._tracks=[];this._started=!1;this._finalizing=!1;this._mutex=new B;if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(!(i.format instanceof M))throw new TypeError("options.format must be an OutputFormat.");if(!(i.target instanceof V))throw new TypeError("options.target must be a Target.");if(i.target._output)throw new Error("Target is already used for another output.");i.target._output=this,this._writer=i.target._createWriter(),this._muxer=i.format._createMuxer(this)}addVideoTrack(i,e={}){if(!(i instanceof _))throw new TypeError("source must be a VideoSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");if(typeof e.rotation=="number"&&![0,90,180,270].includes(e.rotation))throw new TypeError(`Invalid video rotation: ${e.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(e.rotation)&&(e.rotation.length!==9||e.rotation.some(r=>!Number.isFinite(r))))throw new TypeError(`Invalid video transformation matrix: ${e.rotation.join()}`);if(e.frameRate!==void 0&&(!Number.isInteger(e.frameRate)||e.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${e.frameRate}. Must be a positive integer.`);this._addTrack("video",i,e)}addAudioTrack(i,e={}){if(!(i instanceof O))throw new TypeError("source must be an AudioSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",i,e)}addSubtitleTrack(i,e={}){if(!(i instanceof R))throw new TypeError("source must be a SubtitleSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",i,e)}_addTrack(i,e,r){if(this._started)throw new Error("Cannot add track after output has started.");if(e._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:i,source:e,metadata:r};this._muxer.beforeTrackAdd(s),this._tracks.push(s),e._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let i=await this._mutex.acquire();await this._muxer.start();for(let e of this._tracks)e.source._start();i()}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 i=await this._mutex.acquire(),e=this._tracks.map(r=>r.source._flush());await Promise.all(e),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),i()}};return pt(kr);})(); +${r.notes??""}`,w=this.createInternalChunk(m,n,r.duration,"key",f.trim()?y.encode(f):null);o.chunkQueue.push(w),await this.interleaveChunks()}finally{a()}}async interleaveChunks(){for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(r=>r.track===e))return;e:for(;;){let e=null,r=1/0;for(let a of this.trackDatas){if(a.chunkQueue.length===0&&!a.track.source._closed)break e;a.chunkQueue.length>0&&a.chunkQueue[0].timestamp=2&&s++;let c={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];Qe(r.data,s+0,s+3,c)}createInternalChunk(e,r,s,a,o=null){return{data:e,type:a,timestamp:r,duration:s,additions:o}}writeBlock(e,r){this.segment||(this.createTracks(),this.createSegment());let s=Math.floor(1e3*r.timestamp),a=this.trackDatas.every(f=>{if(f.track.source._closed)return!0;if(e===f)return r.type==="key";let w=f.chunkQueue[0];return w&&w.type==="key"});(!this.currentCluster||a&&s-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(s);let o=s-this.currentClusterMsTimestamp;if(o<0)return;if(o>=He)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${He} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${He} milliseconds.`);let u=new Uint8Array(4),c=new DataView(u.buffer);c.setUint8(0,128|e.track.id),c.setInt16(1,o,!1);let m=Math.floor(1e3*r.duration);if(m===0&&!r.additions){c.setUint8(3,+(r.type==="key")<<7);let f={id:163,data:[u,r.data]};this.writeEBML(f)}else{let f={id:160,data:[{id:161,data:[u,r.data]},r.type==="delta"?{id:251,data:new ie(e.lastWrittenMsTimestamp-s)}:null,r.additions?{id:30113,data:[{id:166,data:[{id:165,data:r.additions},{id:238,data:1}]}]}:null,m>0?{id:155,data:m}:null]};this.writeEBML(f)}this.duration=Math.max(this.duration,s+m),e.lastWrittenMsTimestamp=s,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:mt,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),r=this.writer.getPos();this.writer.seek(this.offsets.get(this.currentCluster)+4),this.writeEBMLVarInt(e,mt),this.writer.seek(r);let s=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(a=>({id:183,data:[{id:247,data:a.track.id},{id:241,data:s}]}))]})}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 r of this.trackDatas)for(;r.chunkQueue.length>0;)this.writeBlock(r,r.chunkQueue.shift());if(!this.format._options.streamable&&this.currentCluster&&this.finalizeCurrentCluster(),d(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let r=this.writer.getPos(),s=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(s,dt),this.segmentDuration.data=new X(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(r)}e()}};var z=class{},ke=class extends z{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(i.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=i}_createMuxer(i){return new Te(i,this)}},se=class extends z{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.streamable!==void 0&&typeof i.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=i}_createMuxer(i){return new Ce(i,this)}},D=class extends se{};var G=["avc","hevc","vp8","vp9","av1"],Y=["aac","opus"],ge=["webvtt"],W=class{constructor(){this._connectedTrack=null;this._closed=!1;this._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)}},O=class extends W{constructor(e){super();this._connectedTrack=null;if(!G.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${G.join(", ")}.`);this._codec=e}},Se=class extends O{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,i,e)}},gr=5,Sr=t=>{if(!t||typeof t!="object")throw new TypeError("Codec config must be an object.");if(!G.includes(t.codec))throw new TypeError(`Invalid video codec '${t.codec}'. Must be one of: ${G.join(", ")}.`);if(!Number.isInteger(t.bitrate)||t.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.");if(t.latencyMode!==void 0&&["quality","realtime"].includes(t.latencyMode))throw new TypeError("config.latencyMode, when provided, must be 'quality' or 'realtime'.")},ae=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastMultipleOfKeyFrameInterval=-1;this.lastWidth=null;this.lastHeight=null;Sr(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(i.codedWidth!==this.lastWidth||i.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${i.codedWidth}x${i.codedHeight}.`)}else this.lastWidth=i.codedWidth,this.lastHeight=i.codedHeight;this.ensureEncoder(i),d(this.encoder);let e=Math.floor(i.timestamp/1e6/gr);this.encoder.encode(i,{keyFrame:e!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=e,this.encoder.encodeQueueSize>=4&&await new Promise(r=>this.encoder.addEventListener("dequeue",r,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new VideoEncoder({output:(e,r)=>this.muxer.addEncodedVideoChunk(this.source._connectedTrack,e,r),error:e=>console.error("Video encode error:",e)}),this.encoder.configure({codec:nt(this.codecConfig.codec,i.codedWidth,i.codedHeight,this.codecConfig.bitrate),width:i.codedWidth,height:i.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},ye=class extends O{constructor(i){super(i.codec),this._encoder=new ae(this,i)}digest(i){if(!(i instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},ve=class extends O{constructor(i,e){if(!(i instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(e.codec),this._encoder=new ae(this,e),this._canvas=i}digest(i,e=0){if(!Number.isFinite(i)||i<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(e)||e<0)throw new TypeError("duration must be a non-negative number.");let r=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*i),duration:Math.round(1e6*e),alpha:"discard"}),s=this._encoder.digest(r);return r.close(),s}_flush(){return this._encoder.flush()}},_e=class extends O{constructor(e,r){if(!(e instanceof MediaStreamTrack)||e.kind!=="video")throw new TypeError("track must be a video MediaStreamTrack.");r={...r,latencyMode:"realtime"};super(r.codec);this._abortController=null;this._offsetTimestamps=!0;this._encoder=new ae(this,r),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),r=new WritableStream({write:s=>{this._encoder.digest(s),s.close()}});e.readable.pipeTo(r,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},E=class extends W{constructor(e){super();this._connectedTrack=null;if(!Y.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${Y.join(", ")}.`);this._codec=e}},Ae=class extends E{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,i,e)}},yr=t=>{if(!t||typeof t!="object")throw new TypeError("Codec config must be an object.");if(!Y.includes(t.codec))throw new TypeError(`Invalid audio codec '${t.codec}'. Must be one of: ${Y.join(", ")}.`);if(!Number.isInteger(t.bitrate)||t.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},oe=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastNumberOfChannels=null;this.lastSampleRate=null;yr(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(i.numberOfChannels!==this.lastNumberOfChannels||i.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${i.numberOfChannels} channels at ${i.sampleRate} Hz.`)}else this.lastNumberOfChannels=i.numberOfChannels,this.lastSampleRate=i.sampleRate;this.ensureEncoder(i),d(this.encoder),this.encoder.encode(i),this.encoder.encodeQueueSize>=4&&await new Promise(e=>this.encoder.addEventListener("dequeue",e,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new AudioEncoder({output:(e,r)=>this.muxer.addEncodedAudioChunk(this.source._connectedTrack,e,r),error:e=>console.error("Audio encode error:",e)}),this.encoder.configure({codec:ut(this.codecConfig.codec,i.numberOfChannels,i.sampleRate),numberOfChannels:i.numberOfChannels,sampleRate:i.sampleRate,bitrate:this.codecConfig.bitrate}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Oe=class extends E{constructor(i){super(i.codec),this._encoder=new oe(this,i)}digest(i){if(!(i instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},Ee=class extends E{constructor(e){super(e.codec);this._accumulatedFrameCount=0;this._encoder=new oe(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let r=e.numberOfChannels,s=e.sampleRate,a=e.length,o=new Float32Array(r*a);for(let c=0;c{this._encoder.digest(s),s.close()}});e.readable.pipeTo(r,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},R=class extends W{constructor(e){super();this._connectedTrack=null;if(!ge.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${ge.join(", ")}.`);this._codec=e}},Ve=class extends R{constructor(i){super(i),this._parser=new ue({codec:i,output:(e,r)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,e,r),error:e=>console.error("Subtitle parse error:",e)})}digest(i){if(typeof i!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(i),this._connectedTrack.output._muxer.mutex.currentPromise}};var ze=class{constructor(i){this._tracks=[];this._started=!1;this._finalizing=!1;this._mutex=new N;if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(!(i.format instanceof z))throw new TypeError("options.format must be an OutputFormat.");if(!(i.target instanceof V))throw new TypeError("options.target must be a Target.");if(i.target._output)throw new Error("Target is already used for another output.");i.target._output=this,this._writer=i.target._createWriter(),this._muxer=i.format._createMuxer(this)}addVideoTrack(i,e={}){if(!(i instanceof O))throw new TypeError("source must be a VideoSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");if(typeof e.rotation=="number"&&![0,90,180,270].includes(e.rotation))throw new TypeError(`Invalid video rotation: ${e.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(e.rotation)&&(e.rotation.length!==9||e.rotation.some(r=>!Number.isFinite(r))))throw new TypeError(`Invalid video transformation matrix: ${e.rotation.join()}`);if(e.frameRate!==void 0&&(!Number.isInteger(e.frameRate)||e.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${e.frameRate}. Must be a positive integer.`);this._addTrack("video",i,e)}addAudioTrack(i,e={}){if(!(i instanceof E))throw new TypeError("source must be an AudioSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",i,e)}addSubtitleTrack(i,e={}){if(!(i instanceof R))throw new TypeError("source must be a SubtitleSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",i,e)}_addTrack(i,e,r){if(this._started)throw new Error("Cannot add track after output has started.");if(e._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:i,source:e,metadata:r};this._muxer.beforeTrackAdd(s),this._tracks.push(s),e._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let i=await this._mutex.acquire();await this._muxer.start();for(let e of this._tracks)e.source._start();i()}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 i=await this._mutex.acquire(),e=this._tracks.map(r=>r.source._flush());await Promise.all(e),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),i()}};return wt(vr);})(); 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 3f07b92..c8658a3 100644 --- a/dist/metamuxer.min.mjs +++ b/dist/metamuxer.min.mjs @@ -1,9 +1,9 @@ -function c(r){if(!r)throw new Error("Assertion failed.")}var R=r=>r&&r[r.length-1],V=r=>r>=0&&r<2**32,M=(r,i,e)=>{let t=0;for(let s=i;s>n;t<<=1,t|=u}return t},He=(r,i,e,t)=>{for(let s=i;s>e-s-1<r instanceof ArrayBuffer?new Uint8Array(r):new Uint8Array(r.buffer,r.byteOffset,r.byteLength),x=new TextEncoder,F={bt709:1,bt470bg:5,smpte170m:6},B={bt709:1,smpte170m:6,"iec61966-2-1":13},N={rgb:0,bt709:1,bt470bg:5,smpte170m:6},ae=r=>!!r&&!!r.primaries&&!!r.transfer&&!!r.matrix&&r.fullRange!==void 0,ge=r=>r instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&r instanceof SharedArrayBuffer||ArrayBuffer.isView(r)&&!(r instanceof DataView),W=class{constructor(){this.currentPromise=Promise.resolve()}async acquire(){let i,e=new Promise(s=>{i=s}),t=this.currentPromise;return this.currentPromise=e,await t,i}};var X=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,ut=/^WEBVTT(.|\n)*?\n{2}/,H=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,ne=class{constructor(i){this.preambleText=null;this.preambleEmitted=!1;this.options=i}parse(i){i=i.replaceAll(`\r +function d(t){if(!t)throw new Error("Assertion failed.")}var S=t=>t&&t[t.length-1],V=t=>t>=0&&t<2**32,z=(t,i,e)=>{let r=0;for(let s=i;s>n;r<<=1,r|=u}return r},He=(t,i,e,r)=>{for(let s=i;s>e-s-1<t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t.buffer,t.byteOffset,t.byteLength),y=new TextEncoder,R={bt709:1,bt470bg:5,smpte170m:6},F={bt709:1,smpte170m:6,"iec61966-2-1":13},N={rgb:0,bt709:1,bt470bg:5,smpte170m:6},oe=t=>!!t&&!!t.primaries&&!!t.transfer&&!!t.matrix&&t.fullRange!==void 0,Ce=t=>t instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&t instanceof SharedArrayBuffer||ArrayBuffer.isView(t)&&!(t instanceof DataView),W=class{constructor(){this.currentPromise=Promise.resolve()}async acquire(){let i,e=new Promise(s=>{i=s}),r=this.currentPromise;return this.currentPromise=e,await r,i}};var X=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,mt=/^WEBVTT(.|\n)*?\n{2}/,H=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,ne=class{constructor(i){this.preambleText=null;this.preambleEmitted=!1;this.options=i}parse(i){i=i.replaceAll(`\r `,` `).replaceAll("\r",` -`),X.lastIndex=0;let e;if(!this.preambleText){if(!ut.test(i)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}e=X.exec(i);let t=i.slice(0,e?.index??i.length).trimEnd();if(!t){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=t,e&&(i=i.slice(e.index),X.lastIndex=0)}for(;e=X.exec(i);){let t=i.slice(0,e.index),s=e[1],o=e.index+e[0].length,a=i.indexOf(` -`,o)+1,n=i.slice(o,a).trim(),u=i.indexOf(` +`),X.lastIndex=0;let e;if(!this.preambleText){if(!mt.test(i)){let s=new Error("WebVTT preamble incorrect.");throw this.options.error(s),s}e=X.exec(i);let r=i.slice(0,e?.index??i.length).trimEnd();if(!r){let s=new Error("No WebVTT preamble provided.");throw this.options.error(s),s}this.preambleText=r,e&&(i=i.slice(e.index),X.lastIndex=0)}for(;e=X.exec(i);){let r=i.slice(0,e.index),s=e[1],a=e.index+e[0].length,o=i.indexOf(` +`,a)+1,n=i.slice(a,o).trim(),u=i.indexOf(` -`,o);u===-1&&(u=i.length);let d=ue(e[2]),f=ue(e[3])-d,w=i.slice(a,u).trim();i=i.slice(u).trimStart(),X.lastIndex=0;let _={timestamp:d/1e3,duration:f/1e3,text:w,identifier:s,settings:n,notes:t},g={};this.preambleEmitted||(g.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(_,g)}}},lt=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,ue=r=>{let i=lt.exec(r);if(!i)throw new Error("Expected match.");return 60*60*1e3*Number(i[1]||"0")+60*1e3*Number(i[2])+1e3*Number(i[3])+Number(i[4])},le=r=>{let i=Math.floor(r/36e5),e=Math.floor(r%(60*60*1e3)/(60*1e3)),t=Math.floor(r%(60*1e3)/1e3),s=r%1e3;return i.toString().padStart(2,"0")+":"+e.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var G=class{constructor(i){this.writer=i;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap}writeU32(i){this.helperView.setUint32(0,i,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(i){this.helperView.setUint32(0,Math.floor(i/2**32),!1),this.helperView.setUint32(4,i,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(i){for(let e=0;e[(r%256+256)%256],h=r=>(A.setUint16(0,r,!1),[p[0],p[1]]),ct=r=>(A.setInt16(0,r,!1),[p[0],p[1]]),$e=r=>(A.setUint32(0,r,!1),[p[1],p[2],p[3]]),l=r=>(A.setUint32(0,r,!1),[p[0],p[1],p[2],p[3]]),je=r=>(A.setInt32(0,r,!1),[p[0],p[1],p[2],p[3]]),z=r=>(A.setUint32(0,Math.floor(r/2**32),!1),A.setUint32(4,r,!1),[p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]]),xe=r=>(A.setInt16(0,2**8*r,!1),[p[0],p[1]]),v=r=>(A.setInt32(0,2**16*r,!1),[p[0],p[1],p[2],p[3]]),ke=r=>(A.setInt32(0,2**30*r,!1),[p[0],p[1],p[2],p[3]]),ye=(r,i)=>{let e=[],t=r;do{let s=t&127;t>>=7,e.length>0&&(s|=128),e.push(s),i!==void 0&&i--}while(t>0||i);return e.reverse()},y=(r,i=!1)=>{let e=Array(r.length).fill(null).map((t,s)=>r.charCodeAt(s));return i&&e.push(0),e},Se=r=>{let i=null;for(let e of r)(!i||e.timestamp>i.timestamp)&&(i=e);return i},qe=r=>{let i=r*(Math.PI/180),e=Math.cos(i),t=Math.sin(i);return[e,t,0,-t,e,0,0,0,1]},Ke=qe(0),Le=r=>[v(r[0]),v(r[1]),ke(r[2]),v(r[3]),v(r[4]),ke(r[5]),v(r[6]),v(r[7]),ke(r[8])],b=(r,i,e)=>({type:r,contents:i&&new Uint8Array(i.flat(10)),children:e}),T=(r,i,e,t,s)=>b(r,[C(i),$e(e),t??[]],s),Xe=r=>{let i=512;return r.fragmented?b("ftyp",[y("iso5"),l(i),y("iso5"),y("iso6"),y("mp41")]):b("ftyp",[y("isom"),l(i),y("isom"),r.holdsAvc?y("avc1"):[],y("mp41")])},de=r=>({type:"mdat",largeSize:r}),Ge=r=>({type:"free",size:r}),Y=(r,i,e=!1)=>b("moov",void 0,[dt(i,r),...r.map(t=>mt(t,i)),e?jt(r):null]),dt=(r,i)=>{let e=S(Math.max(0,...i.filter(a=>a.samples.length>0).map(a=>{let n=Se(a.samples);return n.timestamp+n.duration})),ce),t=Math.max(0,...i.map(a=>a.track.id))+1,s=!V(r)||!V(e),o=s?z:l;return T("mvhd",+s,0,[o(r),o(r),l(ce),o(e),v(1),xe(1),Array(10).fill(0),Le(Ke),Array(24).fill(0),l(t)])},mt=(r,i)=>b("trak",void 0,[ft(r,i),pt(r,i)]),ft=(r,i)=>{let e=Se(r.samples),t=S(e?e.timestamp+e.duration:0,ce),s=!V(i)||!V(t),o=s?z:l,a;if(r.type==="video"){let n=r.track.metadata.rotation;a=n===void 0||typeof n=="number"?qe(n??0):n}else a=Ke;return T("tkhd",+s,3,[o(i),o(i),l(r.track.id),l(0),o(t),Array(8).fill(0),h(0),h(r.track.id),xe(r.type==="audio"?1:0),h(0),Le(a),v(r.type==="video"?r.info.width:0),v(r.type==="video"?r.info.height:0)])},pt=(r,i)=>b("mdia",void 0,[ht(r,i),wt(r),Ct(r)]),ht=(r,i)=>{let e=Se(r.samples),t=S(e?e.timestamp+e.duration:0,r.timescale),s=!V(i)||!V(t),o=s?z:l;return T("mdhd",+s,0,[o(i),o(i),l(r.timescale),o(t),h(21956),h(0)])},bt={video:"vide",audio:"soun",subtitle:"text"},Tt={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},wt=r=>T("hdlr",0,0,[y("mhlr"),y(bt[r.type]),l(0),l(0),l(0),y(Tt[r.type],!0)]),Ct=r=>b("minf",void 0,[xt[r.type](),St(),_t(r)]),gt=()=>T("vmhd",0,1,[h(0),h(0),h(0),h(0)]),kt=()=>T("smhd",0,0,[h(0),h(0)]),yt=()=>T("nmhd",0,0),xt={video:gt,audio:kt,subtitle:yt},St=()=>b("dinf",void 0,[vt()]),vt=()=>T("dref",0,0,[l(1)],[At()]),At=()=>T("url ",0,1),_t=r=>{let i=r.compositionTimeOffsetTable.length>1||r.compositionTimeOffsetTable.some(e=>e.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[Ot(r),Ft(r),Bt(r),Nt(r),Ht(r),Qt(r),i?$t(r):null])},Ot=r=>{let i;return r.type==="video"?i=Et(er[r.track.source._codec],r):r.type==="audio"?i=Pt(rr[r.track.source._codec],r):r.type==="subtitle"&&(i=Wt(sr[r.track.source._codec],r)),c(i),T("stsd",0,0,[l(1)],[i])},Et=(r,i)=>b(r,[Array(6).fill(0),h(1),h(0),h(0),Array(12).fill(0),h(i.info.width),h(i.info.height),l(4718592),l(4718592),l(0),h(1),Array(32).fill(0),h(24),ct(65535)],[tr[i.track.source._codec](i),ae(i.info.decoderConfig.colorSpace)?Vt(i):null]),Vt=r=>b("colr",[y("nclx"),h(F[r.info.decoderConfig.colorSpace.primaries]),h(B[r.info.decoderConfig.colorSpace.transfer]),h(N[r.info.decoderConfig.colorSpace.matrix]),C((r.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),Mt=r=>r.info.decoderConfig&&b("avcC",[...I(r.info.decoderConfig.description)]),It=r=>r.info.decoderConfig&&b("hvcC",[...I(r.info.decoderConfig.description)]),Qe=r=>{if(!r.info.decoderConfig)return null;let i=r.info.decoderConfig;c(i.colorSpace);let e=i.codec.split("."),t=Number(e[1]),s=Number(e[2]),n=(Number(e[3])<<4)+(0<<1)+Number(i.colorSpace.fullRange);return T("vpcC",1,0,[C(t),C(s),C(n),C(2),C(2),C(2),h(0)])},zt=()=>{let e=(1<<7)+1;return b("av1C",[e,0,0,0])},Pt=(r,i)=>b(r,[Array(6).fill(0),h(1),h(0),h(0),l(0),h(i.info.numberOfChannels),h(16),h(0),h(0),v(i.info.sampleRate)],[ir[i.track.source._codec](i)]),Ut=r=>{let e=[...I(r.info.decoderConfig.description??new ArrayBuffer(0))];return e=[...C(64),...C(21),...$e(0),...l(0),...l(0),...C(5),...ye(e.length),...e],e=[...h(1),...C(0),...C(4),...ye(e.length),...e,...C(6),...C(1),...C(2)],e=[...C(3),...ye(e.length),...e],T("esds",0,0,e)},Dt=r=>{let i=3840,e=0,t=r.info.decoderConfig?.description;if(t){c(t.byteLength<18);let s=ArrayBuffer.isView(t)?new DataView(t.buffer,t.byteOffset,t.byteLength):new DataView(t);i=s.getUint16(10,!0),e=s.getInt16(14,!0)}return b("dOps",[C(0),C(r.info.numberOfChannels),h(i),l(r.info.sampleRate),xe(e),C(0)])},Wt=(r,i)=>b(r,[Array(6).fill(0),h(1)],[or[i.track.source._codec](i)]),Rt=r=>b("vttC",[...x.encode(r.info.config.description)]);var Ft=r=>T("stts",0,0,[l(r.timeToSampleTable.length),r.timeToSampleTable.map(i=>[l(i.sampleCount),l(i.sampleDelta)])]),Bt=r=>{if(r.samples.every(e=>e.type==="key"))return null;let i=[...r.samples.entries()].filter(([,e])=>e.type==="key");return T("stss",0,0,[l(i.length),i.map(([e])=>l(e+1))])},Nt=r=>T("stsc",0,0,[l(r.compactlyCodedChunkTable.length),r.compactlyCodedChunkTable.map(i=>[l(i.firstChunk),l(i.samplesPerChunk),l(1)])]),Ht=r=>T("stsz",0,0,[l(0),l(r.samples.length),r.samples.map(i=>l(i.size))]),Qt=r=>r.finalizedChunks.length>0&&R(r.finalizedChunks).offset>=2**32?T("co64",0,0,[l(r.finalizedChunks.length),r.finalizedChunks.map(i=>z(i.offset))]):T("stco",0,0,[l(r.finalizedChunks.length),r.finalizedChunks.map(i=>l(i.offset))]),$t=r=>T("ctts",0,0,[l(r.compositionTimeOffsetTable.length),r.compositionTimeOffsetTable.map(i=>[l(i.sampleCount),l(i.sampleCompositionTimeOffset)])]),jt=r=>b("mvex",void 0,r.map(qt)),qt=r=>T("trex",0,0,[l(r.track.id),l(1),l(0),l(0),l(0)]),ve=(r,i)=>b("moof",void 0,[Kt(r),...i.map(Lt)]),Kt=r=>T("mfhd",0,0,[l(r)]),Ye=r=>{let i=0,e=0,t=0,s=0,o=r.type==="delta";return e|=+o,o?i|=1:i|=2,i<<24|e<<16|t<<8|s},Lt=r=>b("traf",void 0,[Xt(r),Gt(r),Yt(r)]),Xt=r=>{c(r.currentChunk);let i=0;i|=8,i|=16,i|=32,i|=131072;let e=r.currentChunk.samples[1]??r.currentChunk.samples[0],t={duration:e.timescaleUnitsToNextSample,size:e.size,flags:Ye(e)};return T("tfhd",0,i,[l(r.track.id),l(t.duration),l(t.size),l(t.flags)])},Gt=r=>(c(r.currentChunk),T("tfdt",1,0,[z(S(r.currentChunk.startTimestamp,r.timescale))])),Yt=r=>{c(r.currentChunk);let i=r.currentChunk.samples.map(k=>k.timescaleUnitsToNextSample),e=r.currentChunk.samples.map(k=>k.size),t=r.currentChunk.samples.map(Ye),s=r.currentChunk.samples.map(k=>S(k.timestamp-k.decodeTimestamp,r.timescale)),o=new Set(i),a=new Set(e),n=new Set(t),u=new Set(s),d=n.size===2&&t[0]!==t[1],m=o.size>1,f=a.size>1,w=!d&&n.size>1,_=u.size>1||[...u].some(k=>k!==0),g=0;return g|=1,g|=4*+d,g|=256*+m,g|=512*+f,g|=1024*+w,g|=2048*+_,T("trun",1,g,[l(r.currentChunk.samples.length),l(r.currentChunk.offset-r.currentChunk.moofOffset||0),d?l(t[0]):[],r.currentChunk.samples.map((k,D)=>[m?l(i[D]):[],f?l(e[D]):[],w?l(t[D]):[],_?je(s[D]):[]])])},Ze=r=>b("mfra",void 0,[...r.map(Zt),Jt()]),Zt=(r,i)=>T("tfra",1,0,[l(r.track.id),l(63),l(r.finalizedChunks.length),r.finalizedChunks.map(t=>[z(S(t.startTimestamp,r.timescale)),z(t.moofOffset),l(i+1),l(1),l(1)])]),Jt=()=>T("mfro",0,0,[l(0)]),Je=()=>b("vtte"),et=(r,i,e,t,s)=>b("vttc",void 0,[s!==null?b("vsid",[je(s)]):null,e!==null?b("iden",[...x.encode(e)]):null,i!==null?b("ctim",[...x.encode(le(i))]):null,t!==null?b("sttg",[...x.encode(t)]):null,b("payl",[...x.encode(r)])]),tt=r=>b("vtta",[...x.encode(r)]),er={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},tr={avc:Mt,hevc:It,vp8:Qe,vp9:Qe,av1:zt},rr={aac:"mp4a",opus:"Opus"},ir={aac:Ut,opus:Dt},sr={webvtt:"wvtt"},or={webvtt:Rt};var Q=class{constructor(i){this.mutex=new W;this.trackTimestampInfo=new WeakMap;this.output=i}beforeTrackAdd(i){}onTrackClose(i){}validateAndNormalizeTimestamp(i,e,t){let s=e/1e6,o=this.trackTimestampInfo.get(i);if(!o){if(!t)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:i.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:i.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(i,o)}if(i.source._offsetTimestamps&&(s-=o.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(ss.start-o.start);e.push({start:t[0].start,size:t[0].data.byteLength});for(let s=1;sd.start<=t&&tnr){for(let d=0;d=e.written[a+1].start;)e.written[a].end=Math.max(e.written[a].end,e.written[a+1].end),e.written.splice(a+1,1)}createChunk(e){let s={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(s),this.chunks.sort((o,a)=>o.start-a.start),this.chunks.indexOf(s)}queueChunksForFlush(e=!1){c(this.writer);for(let t=0;t{if(r==="avc"){let t=100;i<=768&&e<=432?t=66:i<=1920&&e<=1080&&(t=77);let s=0,o=i>1920||e>1080?50:41,a=t.toString(16).padStart(2,"0"),n=s.toString(16).padStart(2,"0"),u=o.toString(16).padStart(2,"0");return`avc1.${a}${n}${u}`}else if(r==="hevc"){let t=0,s=1,o=Array(32).fill(0);o[s]=1;let a=parseInt(o.reverse().join(""),2).toString(16).replace(/^0+/,""),n="L",u=120;return i<=1280&&e<=720?u=93:i<=1920&&e<=1080?u=120:i<=3840&&e<=2160?u=150:(n="H",u=180),`hev1.${t===0?"":String.fromCharCode(65+t-1)}${s}.${a}.${n}${u}.B0`}else{if(r==="vp8")return"vp8";if(r==="vp9"){let t="00",s;return i<=854&&e<=480?s="21":i<=1280&&e<=720?s="31":i<=1920&&e<=1080?s="41":i<=3840&&e<=2160?s="51":s="61",`vp09.${t}.${s}.08`}else if(r==="av1"){let s;return i<=854&&e<=480?s="01":i<=1280&&e<=720?s="03":i<=1920&&e<=1080?s="04":i<=3840&&e<=2160?s="07":s="09",`av01.0.${s}M.08`}}throw new TypeError(`Unhandled codec '${r}'.`)},it=(r,i,e)=>{if(r==="aac")return i>=2&&e<=24e3?"mp4a.40.29":e<=24e3?"mp4a.40.5":"mp4a.40.2";if(r==="opus")return"opus";if(r==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${r}'.`)},pe=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&&!ge(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:i}=r.decoderConfig;if(typeof i!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let e=Object.keys(F);if(i.primaries!=null&&!e.includes(i.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${e.join(", ")}.`);let t=Object.keys(B);if(i.transfer!=null&&!t.includes(i.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${t.join(", ")}.`);let s=Object.keys(N);if(i.matrix!=null&&!s.includes(i.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(i.fullRange!=null&&typeof i.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.")},he=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&&!ge(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==="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.")},be=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 ce=1e3,ur=2082844800,S=(r,i,e=!0)=>{let t=r*i;return e?Math.round(t):t},Te=class extends Q{constructor(e,t){super(e);this.timestampsMustStartAtZero=!0;this.auxTarget=new J;this.auxWriter=this.auxTarget._createWriter();this.auxBoxWriter=new G(this.auxWriter);this.ftypSize=null;this.mdat=null;this.trackDatas=[];this.creationTime=Math.floor(Date.now()/1e3)+ur;this.finalizedChunks=[];this.nextFragmentNumber=1;this.writer=e._writer,this.boxWriter=new G(this.writer),this.fastStart=t._options.fastStart??(this.writer instanceof $?"in-memory":!1),(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),t=this.output._tracks.some(s=>s.type==="video"&&s.source._codec==="avc");this.boxWriter.writeBox(Xe({holdsAvc:t,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=de(!1):this.fastStart==="fragmented"||(this.mdat=de(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,t){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;pe(t),c(t),c(t.decoderConfig),c(t.decoderConfig.codedWidth!==void 0),c(t.decoderConfig.codedHeight!==void 0);let o={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(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getAudioTrackData(e,t){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;he(t),c(t),c(t.decoderConfig);let o={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(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getSubtitleTrackData(e,t){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;be(t),c(t),c(t.config);let o={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(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),this.validateAndNormalizeTimestamp(e,0,!0),o}async addEncodedVideoChunk(e,t,s){let o=await this.mutex.acquire();try{let a=this.getVideoTrackData(e,s),n=new Uint8Array(t.byteLength);t.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,t.timestamp,t.type==="key"),d=this.createSampleForTrack(a,n,u,(t.duration??0)/1e6,t.type);await this.registerSample(a,d)}finally{o()}}async addEncodedAudioChunk(e,t,s){let o=await this.mutex.acquire();try{let a=this.getAudioTrackData(e,s),n=new Uint8Array(t.byteLength);t.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,t.timestamp,t.type==="key"),d=this.createSampleForTrack(a,n,u,(t.duration??0)/1e6,t.type);await this.registerSample(a,d)}finally{o()}}async addSubtitleCue(e,t,s){let o=await this.mutex.acquire();try{let a=this.getSubtitleTrackData(e,s);this.validateAndNormalizeTimestamp(a.track,1e6*t.timestamp,!0),e.source._codec==="webvtt"&&(a.cueQueue.push(t),await this.processWebVTTCues(a,t.timestamp))}finally{o()}}async processWebVTTCues(e,t){for(;e.cueQueue.length>0;){let s=new Set([]);for(let m of e.cueQueue)c(m.timestamp<=t),c(e.lastCueEndTimestamp<=m.timestamp+m.duration),s.add(Math.max(m.timestamp,e.lastCueEndTimestamp)),s.add(m.timestamp+m.duration);let o=[...s].sort((m,f)=>m-f),a=o[0],n=o[1]??a;if(t=n)break;H.lastIndex=0;let w=H.test(f.text),_=f.timestamp+f.duration,g=e.cueToSourceId.get(f);if(g===void 0&&n<_&&(g=e.nextSourceId++,e.cueToSourceId.set(f,g)),f.notes){let D=tt(f.notes);this.auxBoxWriter.writeBox(D)}let k=et(f.text,w?a:null,f.identifier??null,f.settings??null,g??null);this.auxBoxWriter.writeBox(k),_===n&&e.cueQueue.splice(m--,1)}let u=this.auxWriter.getSlice(0,this.auxWriter.getPos()),d=this.createSampleForTrack(e,u,a,n-a,"key");await this.registerSample(e,d),e.lastCueEndTimestamp=n}}createSampleForTrack(e,t,s,o,a){return{timestamp:s,decodeTimestamp:s,duration:o,data:t,size:t.byteLength,type:a,timescaleUnitsToNextSample:S(o,e.timescale)}}processTimestamps(e){if(e.timestampProcessingQueue.length===0)return;let t=e.timestampProcessingQueue.map(s=>s.timestamp).sort((s,o)=>s-o);for(let s=0;s{if(e===n)return t.type==="key";let u=n.sampleQueue[0];return u&&u.type==="key"});o>=1&&a&&(s=!0,await this.finalizeFragment())}else s=o>=.5}s&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:t.timestamp,samples:[],offset:null,moofOffset:null}),c(e.currentChunk),e.currentChunk.samples.push(t),e.timestampProcessingQueue.push(t)}async finalizeCurrentChunk(e){if(c(this.fastStart!=="fragmented"),!!e.currentChunk){if(e.finalizedChunks.push(e.currentChunk),this.finalizedChunks.push(e.currentChunk),(e.compactlyCodedChunkTable.length===0||R(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)c(t.data),this.writer.write(t.data),t.data=null;await this.writer.flush()}}async interleaveSamples(){c(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 o of this.trackDatas){if(o.sampleQueue.length===0&&!o.track.source._closed)break e;o.sampleQueue.length>0&&o.sampleQueue[0].timestamp=2**32&&(u.largeSize=!0,m=this.boxWriter.measureBox(u)+d),u.size=m,this.boxWriter.writeBox(u)}for(let u of this.trackDatas){u.currentChunk.offset=this.writer.getPos(),u.currentChunk.moofOffset=s;for(let d of u.currentChunk.samples)this.writer.write(d.data),d.data=null}let a=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(o));let n=ve(t,this.trackDatas);this.boxWriter.writeBox(n),this.writer.seek(a);for(let u of this.trackDatas)u.finalizedChunks.push(u.currentChunk),this.finalizedChunks.push(u.currentChunk),u.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 s=this.trackDatas.find(o=>o.track===e);s&&await this.processWebVTTCues(s,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 s of t.sampleQueue)await this.addSampleToTrack(t,s);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"){c(this.mdat);let t;for(let o=0;o<2;o++){let a=Y(this.trackDatas,this.creationTime),n=this.boxWriter.measureBox(a);t=this.boxWriter.measureBox(this.mdat);let u=this.writer.getPos()+n+t;for(let d of this.finalizedChunks){d.offset=u;for(let{data:m}of d.samples)c(m),u+=m.byteLength,t+=m.byteLength}if(u<2**32)break;t>=2**32&&(this.mdat.largeSize=!0)}let s=Y(this.trackDatas,this.creationTime);this.boxWriter.writeBox(s),this.mdat.size=t,this.boxWriter.writeBox(this.mdat);for(let o of this.finalizedChunks)for(let a of o.samples)c(a.data),this.writer.write(a.data),a.data=null}else if(this.fastStart==="fragmented"){let t=this.writer.getPos(),s=Ze(this.trackDatas);this.boxWriter.writeBox(s);let o=this.writer.getPos()-t;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(o)}else{c(this.mdat),c(this.ftypSize!==null);let t=this.boxWriter.offsets.get(this.mdat);c(t!==void 0);let s=this.writer.getPos()-t;this.mdat.size=s,this.mdat.largeSize=s>=2**32,this.boxWriter.patchBox(this.mdat);let o=Y(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(o);let a=t-this.writer.getPos();this.boxWriter.writeBox(Ge(a))}else this.boxWriter.writeBox(o)}e()}};var ee=class{constructor(i){this.value=i}},j=class{constructor(i){this.value=i}},te=class{constructor(i){this.value=i}};var _e=r=>r<256?1:r<65536?2:r<1<<24?3:r<2**32?4:r<2**40?5:6,Oe=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,st=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 Ee=2**15,ot="https://github.com/Vanilagy/webm-muxer",at=6,nt=5,lr={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"},cr={video:1,audio:2,subtitle:17},we=class extends Q{constructor(e,t){super(e);this.timestampsMustStartAtZero=!1;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap;this.dataOffsets=new WeakMap;this.trackDatas=[];this.segment=null;this.segmentInfo=null;this.seekHead=null;this.tracksElement=null;this.segmentDuration=null;this.cues=null;this.currentCluster=null;this.currentClusterMsTimestamp=null;this.trackDatasInCurrentCluster=new Set;this.duration=0;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=_e(e)){let s=0;switch(t){case 6:this.helperView.setUint8(s++,e/2**40|0);case 5:this.helperView.setUint8(s++,e/2**32|0);case 4:this.helperView.setUint8(s++,e>>24);case 3:this.helperView.setUint8(s++,e>>16);case 2:this.helperView.setUint8(s++,e>>8);case 1:this.helperView.setUint8(s++,e);break;default:throw new Error("Bad UINT size "+t)}this.writer.write(this.helper.subarray(0,s))}writeSignedInt(e,t=Oe(e)){e<0&&(e+=2**(t*8)),this.writeUnsignedInt(e,t)}writeEBMLVarInt(e,t=st(e)){let s=0;switch(t){case 1:this.helperView.setUint8(s++,128|e);break;case 2:this.helperView.setUint8(s++,64|e>>8),this.helperView.setUint8(s++,e);break;case 3:this.helperView.setUint8(s++,32|e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 4:this.helperView.setUint8(s++,16|e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 5:this.helperView.setUint8(s++,8|e/2**32&7),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 6:this.helperView.setUint8(s++,4|e/2**40&3),this.helperView.setUint8(s++,e/2**32|0),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;default:throw new Error("Bad EBML VINT size "+t)}this.writer.write(this.helper.subarray(0,s))}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(),s=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+s);let o=this.writer.getPos();if(this.dataOffsets.set(e,o),this.writeEBML(e.data),e.size!==-1){let a=this.writer.getPos()-o,n=this.writer.getPos();this.writer.seek(t),this.writeEBMLVarInt(a,s),this.writer.seek(n)}}else if(typeof e.data=="number"){let t=e.size??_e(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 ee)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof j)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof te){let t=e.size??Oe(e.data.value);this.writeEBMLVarInt(t),this.writeSignedInt(e.data.value,t)}}}beforeTrackAdd(e){if(this.format instanceof q)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 q?"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]),s=new Uint8Array([22,84,174,107]),o={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:s},{id:21420,size:5,data:0}]}]};this.seekHead=o}createSegmentInfo(){let e={id:17545,data:new j(0)};this.segmentDuration=e;let t={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:ot},{id:22337,data:ot},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:cr[t.type]},{id:134,data:lr[t.track.source._codec]},...t.type==="video"?[t.info.decoderConfig.description?{id:25506,data:I(t.info.decoderConfig.description)}:null,t.track.metadata.frameRate?{id:2352003,data:1e9/t.track.metadata.frameRate}:null,{id:224,data:[{id:176,data:t.info.width},{id:186,data:t.info.height},(()=>{if(t.info.decoderConfig.colorSpace){let s=t.info.decoderConfig.colorSpace;return ae(s)?{id:21936,data:[{id:21937,data:N[s.matrix]},{id:21946,data:B[s.transfer]},{id:21947,data:F[s.primaries]},{id:21945,data:[1,2][Number(s.fullRange)]}]}:null}return null})()]}]:[],...t.type==="audio"?[t.info.decoderConfig.description?{id:25506,data:I(t.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new ee(t.info.sampleRate)},{id:159,data:t.info.numberOfChannels}]}]:[],...t.type==="subtitle"?[{id:25506,data:x.encode(t.info.config.description)}]:[]]})}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:at,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 c(this.segment),this.dataOffsets.get(this.segment)}getVideoTrackData(e,t){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;pe(t),c(t),c(t.decoderConfig),c(t.decoderConfig.codedWidth!==void 0),c(t.decoderConfig.codedHeight!==void 0);let o={track:e,type:"video",info:{width:t.decoderConfig.codedWidth,height:t.decoderConfig.codedHeight,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getAudioTrackData(e,t){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;he(t),c(t),c(t.decoderConfig);let o={track:e,type:"audio",info:{numberOfChannels:t.decoderConfig.numberOfChannels,sampleRate:t.decoderConfig.sampleRate,decoderConfig:t.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}getSubtitleTrackData(e,t){let s=this.trackDatas.find(a=>a.track===e);if(s)return s;be(t),c(t),c(t.config);let o={track:e,type:"subtitle",info:{config:t.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(o),this.trackDatas.sort((a,n)=>a.track.id-n.track.id),o}async addEncodedVideoChunk(e,t,s){let o=await this.mutex.acquire();try{let a=this.getVideoTrackData(e,s),n=new Uint8Array(t.byteLength);t.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,t.timestamp,t.type==="key"),d=this.createInternalChunk(n,u,(t.duration??0)/1e6,t.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(a,d),a.chunkQueue.push(d),await this.interleaveChunks()}finally{o()}}async addEncodedAudioChunk(e,t,s){let o=await this.mutex.acquire();try{let a=this.getAudioTrackData(e,s),n=new Uint8Array(t.byteLength);t.copyTo(n);let u=this.validateAndNormalizeTimestamp(a.track,t.timestamp,t.type==="key"),d=this.createInternalChunk(n,u,(t.duration??0)/1e6,t.type);a.chunkQueue.push(d),await this.interleaveChunks()}finally{o()}}async addSubtitleCue(e,t,s){let o=await this.mutex.acquire();try{let a=this.getSubtitleTrackData(e,s),n=this.validateAndNormalizeTimestamp(a.track,1e6*t.timestamp,!0),u=t.text,d=Math.floor(n*1e3);H.lastIndex=0,u=u.replace(H,_=>{let k=ue(_.slice(1,-1))-d;return`<${le(k)}>`});let m=x.encode(u),f=`${t.settings??""} -${t.identifier??""} -${t.notes??""}`,w=this.createInternalChunk(m,n,t.duration,"key",f.trim()?x.encode(f):null);a.chunkQueue.push(w),await this.interleaveChunks()}finally{o()}}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 o of this.trackDatas){if(o.chunkQueue.length===0&&!o.track.source._closed)break e;o.chunkQueue.length>0&&o.chunkQueue[0].timestamp=2&&s++;let d={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];He(t.data,s+0,s+3,d)}createInternalChunk(e,t,s,o,a=null){return{data:e,type:o,timestamp:t,duration:s,additions:a}}writeBlock(e,t){this.segment||(this.createTracks(),this.createSegment());let s=Math.floor(1e3*t.timestamp),o=this.trackDatas.every(f=>{if(f.track.source._closed)return!0;if(e===f)return t.type==="key";let w=f.chunkQueue[0];return w&&w.type==="key"});(!this.currentCluster||o&&s-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(s);let a=s-this.currentClusterMsTimestamp;if(a<0)return;if(a>=Ee)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${Ee} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${Ee} milliseconds.`);let u=new Uint8Array(4),d=new DataView(u.buffer);d.setUint8(0,128|e.track.id),d.setInt16(1,a,!1);let m=Math.floor(1e3*t.duration);if(m===0&&!t.additions){d.setUint8(3,+(t.type==="key")<<7);let f={id:163,data:[u,t.data]};this.writeEBML(f)}else{let f={id:160,data:[{id:161,data:[u,t.data]},t.type==="delta"?{id:251,data:new te(e.lastWrittenMsTimestamp-s)}:null,t.additions?{id:30113,data:[{id:166,data:[{id:165,data:t.additions},{id:238,data:1}]}]}:null,m>0?{id:155,data:m}:null]};this.writeEBML(f)}this.duration=Math.max(this.duration,s+m),e.lastWrittenMsTimestamp=s,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:nt,data:[{id:231,data:e}]},this.writeEBML(this.currentCluster),this.currentClusterMsTimestamp=e,this.trackDatasInCurrentCluster.clear()}finalizeCurrentCluster(){c(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,nt),this.writer.seek(t);let s=this.offsets.get(this.currentCluster)-this.segmentDataOffset;c(this.cues),this.cues.data.push({id:187,data:[{id:179,data:this.currentClusterMsTimestamp},...[...this.trackDatasInCurrentCluster].map(o=>({id:183,data:[{id:247,data:o.track.id},{id:241,data:s}]}))]})}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(),c(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let t=this.writer.getPos(),s=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(s,at),this.segmentDuration.data=new j(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 U=class{},Ve=class extends U{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(i.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=i}_createMuxer(i){return new Te(i,this)}},Ce=class extends U{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.streamable!==void 0&&typeof i.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=i}_createMuxer(i){return new we(i,this)}},q=class extends Ce{};var re=["avc","hevc","vp8","vp9","av1"],ie=["aac","opus"],Me=["webvtt"],K=class{constructor(){this._connectedTrack=null;this._closed=!1;this._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)}},O=class extends K{constructor(e){super();this._connectedTrack=null;if(!re.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${re.join(", ")}.`);this._codec=e}},Ie=class extends O{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,i,e)}},dr=5,mr=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!re.includes(r.codec))throw new TypeError(`Invalid video codec '${r.codec}'. Must be one of: ${re.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'.")},se=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastMultipleOfKeyFrameInterval=-1;this.lastWidth=null;this.lastHeight=null;mr(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(i.codedWidth!==this.lastWidth||i.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${i.codedWidth}x${i.codedHeight}.`)}else this.lastWidth=i.codedWidth,this.lastHeight=i.codedHeight;this.ensureEncoder(i),c(this.encoder);let e=Math.floor(i.timestamp/1e6/dr);this.encoder.encode(i,{keyFrame:e!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=e,this.encoder.encodeQueueSize>=4&&await new Promise(t=>this.encoder.addEventListener("dequeue",t,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new VideoEncoder({output:(e,t)=>this.muxer.addEncodedVideoChunk(this.source._connectedTrack,e,t),error:e=>console.error("Video encode error:",e)}),this.encoder.configure({codec:rt(this.codecConfig.codec,i.codedWidth,i.codedHeight),width:i.codedWidth,height:i.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode}),c(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},ze=class extends O{constructor(i){super(i.codec),this._encoder=new se(this,i)}digest(i){if(!(i instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},Pe=class extends O{constructor(i,e){if(!(i instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(e.codec),this._encoder=new se(this,e),this._canvas=i}digest(i,e=0){if(!Number.isFinite(i)||i<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(e)||e<0)throw new TypeError("duration must be a non-negative number.");let t=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*i),duration:Math.round(1e6*e),alpha:"discard"}),s=this._encoder.digest(t);return t.close(),s}_flush(){return this._encoder.flush()}},Ue=class extends O{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._abortController=null;this._offsetTimestamps=!0;this._encoder=new se(this,t),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),t=new WritableStream({write:s=>{this._encoder.digest(s),s.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},E=class extends K{constructor(e){super();this._connectedTrack=null;if(!ie.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${ie.join(", ")}.`);this._codec=e}},De=class extends E{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,i,e)}},fr=r=>{if(!r||typeof r!="object")throw new TypeError("Codec config must be an object.");if(!ie.includes(r.codec))throw new TypeError(`Invalid audio codec '${r.codec}'. Must be one of: ${ie.join(", ")}.`);if(!Number.isInteger(r.bitrate)||r.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},oe=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastNumberOfChannels=null;this.lastSampleRate=null;fr(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(i.numberOfChannels!==this.lastNumberOfChannels||i.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${i.numberOfChannels} channels at ${i.sampleRate} Hz.`)}else this.lastNumberOfChannels=i.numberOfChannels,this.lastSampleRate=i.sampleRate;this.ensureEncoder(i),c(this.encoder),this.encoder.encode(i),this.encoder.encodeQueueSize>=4&&await new Promise(e=>this.encoder.addEventListener("dequeue",e,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new AudioEncoder({output:(e,t)=>this.muxer.addEncodedAudioChunk(this.source._connectedTrack,e,t),error:e=>console.error("Audio encode error:",e)}),this.encoder.configure({codec:it(this.codecConfig.codec,i.numberOfChannels,i.sampleRate),numberOfChannels:i.numberOfChannels,sampleRate:i.sampleRate,bitrate:this.codecConfig.bitrate}),c(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},We=class extends E{constructor(i){super(i.codec),this._encoder=new oe(this,i)}digest(i){if(!(i instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},Re=class extends E{constructor(e){super(e.codec);this._accumulatedFrameCount=0;this._encoder=new oe(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let t=e.numberOfChannels,s=e.sampleRate,o=e.length,a=new Float32Array(t*o);for(let d=0;d{this._encoder.digest(s),s.close()}});e.readable.pipeTo(t,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},L=class extends K{constructor(e){super();this._connectedTrack=null;if(!Me.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${Me.join(", ")}.`);this._codec=e}},Be=class extends L{constructor(i){super(i),this._parser=new ne({codec:i,output:(e,t)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,e,t),error:e=>console.error("Subtitle parse error:",e)})}digest(i){if(typeof i!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(i),this._connectedTrack.output._muxer.mutex.currentPromise}};var Ne=class{constructor(i){this._tracks=[];this._started=!1;this._finalizing=!1;this._mutex=new W;if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(!(i.format instanceof U))throw new TypeError("options.format must be an OutputFormat.");if(!(i.target instanceof P))throw new TypeError("options.target must be a Target.");if(i.target._output)throw new Error("Target is already used for another output.");i.target._output=this,this._writer=i.target._createWriter(),this._muxer=i.format._createMuxer(this)}addVideoTrack(i,e={}){if(!(i instanceof O))throw new TypeError("source must be a VideoSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");if(typeof e.rotation=="number"&&![0,90,180,270].includes(e.rotation))throw new TypeError(`Invalid video rotation: ${e.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(e.rotation)&&(e.rotation.length!==9||e.rotation.some(t=>!Number.isFinite(t))))throw new TypeError(`Invalid video transformation matrix: ${e.rotation.join()}`);if(e.frameRate!==void 0&&(!Number.isInteger(e.frameRate)||e.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${e.frameRate}. Must be a positive integer.`);this._addTrack("video",i,e)}addAudioTrack(i,e={}){if(!(i instanceof E))throw new TypeError("source must be an AudioSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",i,e)}addSubtitleTrack(i,e={}){if(!(i instanceof L))throw new TypeError("source must be a SubtitleSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",i,e)}_addTrack(i,e,t){if(this._started)throw new Error("Cannot add track after output has started.");if(e._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:i,source:e,metadata:t};this._muxer.beforeTrackAdd(s),this._tracks.push(s),e._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let i=await this._mutex.acquire();await this._muxer.start();for(let e of this._tracks)e.source._start();i()}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 i=await this._mutex.acquire(),e=this._tracks.map(t=>t.source._flush());await Promise.all(e),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),i()}};export{ie as AUDIO_CODECS,J as ArrayBufferTarget,Re as AudioBufferSource,We as AudioDataSource,E as AudioSource,Pe as CanvasSource,De as EncodedAudioChunkSource,Ie as EncodedVideoChunkSource,K as MediaSource,Fe as MediaStreamAudioTrackSource,Ue as MediaStreamVideoTrackSource,Ce as MkvOutputFormat,Ve as Mp4OutputFormat,Ne as Output,U as OutputFormat,Me as SUBTITLE_CODECS,Ae as StreamTarget,L as SubtitleSource,P as Target,Be as TextSubtitleSource,re as VIDEO_CODECS,ze as VideoFrameSource,O as VideoSource,q as WebMOutputFormat}; +`,a);u===-1&&(u=i.length);let c=ue(e[2]),f=ue(e[3])-c,w=i.slice(o,u).trim();i=i.slice(u).trimStart(),X.lastIndex=0;let O={timestamp:c/1e3,duration:f/1e3,text:w,identifier:s,settings:n,notes:r},C={};this.preambleEmitted||(C.config={description:this.preambleText},this.preambleEmitted=!0),this.options.output(O,C)}}},ft=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,ue=t=>{let i=ft.exec(t);if(!i)throw new Error("Expected match.");return 60*60*1e3*Number(i[1]||"0")+60*1e3*Number(i[2])+1e3*Number(i[3])+Number(i[4])},le=t=>{let i=Math.floor(t/36e5),e=Math.floor(t%(60*60*1e3)/(60*1e3)),r=Math.floor(t%(60*1e3)/1e3),s=t%1e3;return i.toString().padStart(2,"0")+":"+e.toString().padStart(2,"0")+":"+r.toString().padStart(2,"0")+"."+s.toString().padStart(3,"0")};var G=class{constructor(i){this.writer=i;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap}writeU32(i){this.helperView.setUint32(0,i,!1),this.writer.write(this.helper.subarray(0,4))}writeU64(i){this.helperView.setUint32(0,Math.floor(i/2**32),!1),this.helperView.setUint32(4,i,!1),this.writer.write(this.helper.subarray(0,8))}writeAscii(i){for(let e=0;e[(t%256+256)%256],h=t=>(A.setUint16(0,t,!1),[p[0],p[1]]),pt=t=>(A.setInt16(0,t,!1),[p[0],p[1]]),$e=t=>(A.setUint32(0,t,!1),[p[1],p[2],p[3]]),l=t=>(A.setUint32(0,t,!1),[p[0],p[1],p[2],p[3]]),je=t=>(A.setInt32(0,t,!1),[p[0],p[1],p[2],p[3]]),B=t=>(A.setUint32(0,Math.floor(t/2**32),!1),A.setUint32(4,t,!1),[p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]]),Se=t=>(A.setInt16(0,2**8*t,!1),[p[0],p[1]]),_=t=>(A.setInt32(0,2**16*t,!1),[p[0],p[1],p[2],p[3]]),ke=t=>(A.setInt32(0,2**30*t,!1),[p[0],p[1],p[2],p[3]]),ge=(t,i)=>{let e=[],r=t;do{let s=r&127;r>>=7,e.length>0&&(s|=128),e.push(s),i!==void 0&&i--}while(r>0||i);return e.reverse()},g=(t,i=!1)=>{let e=Array(t.length).fill(null).map((r,s)=>t.charCodeAt(s));return i&&e.push(0),e},ye=t=>{let i=null;for(let e of t)(!i||e.timestamp>i.timestamp)&&(i=e);return i},Le=t=>{let i=t*(Math.PI/180),e=Math.cos(i),r=Math.sin(i);return[e,r,0,-r,e,0,0,0,1]},qe=Le(0),Ke=t=>[_(t[0]),_(t[1]),ke(t[2]),_(t[3]),_(t[4]),ke(t[5]),_(t[6]),_(t[7]),ke(t[8])],b=(t,i,e)=>({type:t,contents:i&&new Uint8Array(i.flat(10)),children:e}),x=(t,i,e,r,s)=>b(t,[T(i),$e(e),r??[]],s),Xe=t=>{let i=512;return t.fragmented?b("ftyp",[g("iso5"),l(i),g("iso5"),g("iso6"),g("mp41")]):b("ftyp",[g("isom"),l(i),g("isom"),t.holdsAvc?g("avc1"):[],g("mp41")])},de=t=>({type:"mdat",largeSize:t}),Ge=t=>({type:"free",size:t}),Y=(t,i,e=!1)=>b("moov",void 0,[ht(i,t),...t.map(r=>bt(r,i)),e?Xt(t):null]),ht=(t,i)=>{let e=v(Math.max(0,...i.filter(o=>o.samples.length>0).map(o=>{let n=ye(o.samples);return n.timestamp+n.duration})),ce),r=Math.max(0,...i.map(o=>o.track.id))+1,s=!V(t)||!V(e),a=s?B:l;return x("mvhd",+s,0,[a(t),a(t),l(ce),a(e),_(1),Se(1),Array(10).fill(0),Ke(qe),Array(24).fill(0),l(r)])},bt=(t,i)=>b("trak",void 0,[xt(t,i),wt(t,i)]),xt=(t,i)=>{let e=ye(t.samples),r=v(e?e.timestamp+e.duration:0,ce),s=!V(i)||!V(r),a=s?B:l,o;if(t.type==="video"){let n=t.track.metadata.rotation;o=n===void 0||typeof n=="number"?Le(n??0):n}else o=qe;return x("tkhd",+s,3,[a(i),a(i),l(t.track.id),l(0),a(r),Array(8).fill(0),h(0),h(t.track.id),Se(t.type==="audio"?1:0),h(0),Ke(o),_(t.type==="video"?t.info.width:0),_(t.type==="video"?t.info.height:0)])},wt=(t,i)=>b("mdia",void 0,[Tt(t,i),gt(t),St(t)]),Tt=(t,i)=>{let e=ye(t.samples),r=v(e?e.timestamp+e.duration:0,t.timescale),s=!V(i)||!V(r),a=s?B:l;return x("mdhd",+s,0,[a(i),a(i),l(t.timescale),a(r),h(21956),h(0)])},Ct={video:"vide",audio:"soun",subtitle:"text"},kt={video:"VideoHandler",audio:"SoundHandler",subtitle:"TextHandler"},gt=t=>x("hdlr",0,0,[g("mhlr"),g(Ct[t.type]),l(0),l(0),l(0),g(kt[t.type],!0)]),St=t=>b("minf",void 0,[At[t.type](),Ot(),Vt(t)]),yt=()=>x("vmhd",0,1,[h(0),h(0),h(0),h(0)]),vt=()=>x("smhd",0,0,[h(0),h(0)]),_t=()=>x("nmhd",0,0),At={video:yt,audio:vt,subtitle:_t},Ot=()=>b("dinf",void 0,[Et()]),Et=()=>x("dref",0,0,[l(1)],[Mt()]),Mt=()=>x("url ",0,1),Vt=t=>{let i=t.compositionTimeOffsetTable.length>1||t.compositionTimeOffsetTable.some(e=>e.sampleCompositionTimeOffset!==0);return b("stbl",void 0,[zt(t),Qt(t),$t(t),jt(t),Lt(t),qt(t),i?Kt(t):null])},zt=t=>{let i;return t.type==="video"?i=Pt(sr[t.track.source._codec],t):t.type==="audio"?i=Wt(or[t.track.source._codec],t):t.type==="subtitle"&&(i=Nt(ur[t.track.source._codec],t)),d(i),x("stsd",0,0,[l(1)],[i])},Pt=(t,i)=>b(t,[Array(6).fill(0),h(1),h(0),h(0),Array(12).fill(0),h(i.info.width),h(i.info.height),l(4718592),l(4718592),l(0),h(1),Array(32).fill(0),h(24),pt(65535)],[ar[i.track.source._codec](i),oe(i.info.decoderConfig.colorSpace)?Bt(i):null]),Bt=t=>b("colr",[g("nclx"),h(R[t.info.decoderConfig.colorSpace.primaries]),h(F[t.info.decoderConfig.colorSpace.transfer]),h(N[t.info.decoderConfig.colorSpace.matrix]),T((t.info.decoderConfig.colorSpace.fullRange?1:0)<<7)]),It=t=>t.info.decoderConfig&&b("avcC",[...P(t.info.decoderConfig.description)]),Ut=t=>t.info.decoderConfig&&b("hvcC",[...P(t.info.decoderConfig.description)]),Qe=t=>{if(!t.info.decoderConfig)return null;let i=t.info.decoderConfig;d(i.colorSpace);let e=i.codec.split("."),r=Number(e[1]),s=Number(e[2]),n=(Number(e[3])<<4)+(0<<1)+Number(i.colorSpace.fullRange);return x("vpcC",1,0,[T(r),T(s),T(n),T(2),T(2),T(2),h(0)])},Dt=()=>{let e=(1<<7)+1;return b("av1C",[e,0,0,0])},Wt=(t,i)=>b(t,[Array(6).fill(0),h(1),h(0),h(0),l(0),h(i.info.numberOfChannels),h(16),h(0),h(0),_(i.info.sampleRate)],[nr[i.track.source._codec](i)]),Rt=t=>{let e=[...P(t.info.decoderConfig.description??new ArrayBuffer(0))];return e=[...T(64),...T(21),...$e(0),...l(0),...l(0),...T(5),...ge(e.length),...e],e=[...h(1),...T(0),...T(4),...ge(e.length),...e,...T(6),...T(1),...T(2)],e=[...T(3),...ge(e.length),...e],x("esds",0,0,e)},Ft=t=>{let i=3840,e=0,r=t.info.decoderConfig?.description;if(r){d(r.byteLength<18);let s=ArrayBuffer.isView(r)?new DataView(r.buffer,r.byteOffset,r.byteLength):new DataView(r);i=s.getUint16(10,!0),e=s.getInt16(14,!0)}return b("dOps",[T(0),T(t.info.numberOfChannels),h(i),l(t.info.sampleRate),Se(e),T(0)])},Nt=(t,i)=>b(t,[Array(6).fill(0),h(1)],[lr[i.track.source._codec](i)]),Ht=t=>b("vttC",[...y.encode(t.info.config.description)]);var Qt=t=>x("stts",0,0,[l(t.timeToSampleTable.length),t.timeToSampleTable.map(i=>[l(i.sampleCount),l(i.sampleDelta)])]),$t=t=>{if(t.samples.every(e=>e.type==="key"))return null;let i=[...t.samples.entries()].filter(([,e])=>e.type==="key");return x("stss",0,0,[l(i.length),i.map(([e])=>l(e+1))])},jt=t=>x("stsc",0,0,[l(t.compactlyCodedChunkTable.length),t.compactlyCodedChunkTable.map(i=>[l(i.firstChunk),l(i.samplesPerChunk),l(1)])]),Lt=t=>x("stsz",0,0,[l(0),l(t.samples.length),t.samples.map(i=>l(i.size))]),qt=t=>t.finalizedChunks.length>0&&S(t.finalizedChunks).offset>=2**32?x("co64",0,0,[l(t.finalizedChunks.length),t.finalizedChunks.map(i=>B(i.offset))]):x("stco",0,0,[l(t.finalizedChunks.length),t.finalizedChunks.map(i=>l(i.offset))]),Kt=t=>x("ctts",0,0,[l(t.compositionTimeOffsetTable.length),t.compositionTimeOffsetTable.map(i=>[l(i.sampleCount),l(i.sampleCompositionTimeOffset)])]),Xt=t=>b("mvex",void 0,t.map(Gt)),Gt=t=>x("trex",0,0,[l(t.track.id),l(1),l(0),l(0),l(0)]),ve=(t,i)=>b("moof",void 0,[Yt(t),...i.map(Zt)]),Yt=t=>x("mfhd",0,0,[l(t)]),Ye=t=>{let i=0,e=0,r=0,s=0,a=t.type==="delta";return e|=+a,a?i|=1:i|=2,i<<24|e<<16|r<<8|s},Zt=t=>b("traf",void 0,[Jt(t),er(t),tr(t)]),Jt=t=>{d(t.currentChunk);let i=0;i|=8,i|=16,i|=32,i|=131072;let e=t.currentChunk.samples[1]??t.currentChunk.samples[0],r={duration:e.timescaleUnitsToNextSample,size:e.size,flags:Ye(e)};return x("tfhd",0,i,[l(t.track.id),l(r.duration),l(r.size),l(r.flags)])},er=t=>(d(t.currentChunk),x("tfdt",1,0,[B(v(t.currentChunk.startTimestamp,t.timescale))])),tr=t=>{d(t.currentChunk);let i=t.currentChunk.samples.map(k=>k.timescaleUnitsToNextSample),e=t.currentChunk.samples.map(k=>k.size),r=t.currentChunk.samples.map(Ye),s=t.currentChunk.samples.map(k=>v(k.timestamp-k.decodeTimestamp,t.timescale)),a=new Set(i),o=new Set(e),n=new Set(r),u=new Set(s),c=n.size===2&&r[0]!==r[1],m=a.size>1,f=o.size>1,w=!c&&n.size>1,O=u.size>1||[...u].some(k=>k!==0),C=0;return C|=1,C|=4*+c,C|=256*+m,C|=512*+f,C|=1024*+w,C|=2048*+O,x("trun",1,C,[l(t.currentChunk.samples.length),l(t.currentChunk.offset-t.currentChunk.moofOffset||0),c?l(r[0]):[],t.currentChunk.samples.map((k,D)=>[m?l(i[D]):[],f?l(e[D]):[],w?l(r[D]):[],O?je(s[D]):[]])])},Ze=t=>b("mfra",void 0,[...t.map(rr),ir()]),rr=(t,i)=>x("tfra",1,0,[l(t.track.id),l(63),l(t.finalizedChunks.length),t.finalizedChunks.map(r=>[B(v(r.startTimestamp,t.timescale)),B(r.moofOffset),l(i+1),l(1),l(1)])]),ir=()=>x("mfro",0,0,[l(0)]),Je=()=>b("vtte"),et=(t,i,e,r,s)=>b("vttc",void 0,[s!==null?b("vsid",[je(s)]):null,e!==null?b("iden",[...y.encode(e)]):null,i!==null?b("ctim",[...y.encode(le(i))]):null,r!==null?b("sttg",[...y.encode(r)]):null,b("payl",[...y.encode(t)])]),tt=t=>b("vtta",[...y.encode(t)]),sr={avc:"avc1",hevc:"hvc1",vp8:"vp08",vp9:"vp09",av1:"av01"},ar={avc:It,hevc:Ut,vp8:Qe,vp9:Qe,av1:Dt},or={aac:"mp4a",opus:"Opus"},nr={aac:Rt,opus:Ft},ur={webvtt:"wvtt"},lr={webvtt:Ht};var Q=class{constructor(i){this.mutex=new W;this.trackTimestampInfo=new WeakMap;this.output=i}beforeTrackAdd(i){}onTrackClose(i){}validateAndNormalizeTimestamp(i,e,r){let s=e/1e6,a=this.trackTimestampInfo.get(i);if(!a){if(!r)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).`);a={timestampOffset:s,maxTimestamp:i.source._offsetTimestamps?0:s,lastKeyFrameTimestamp:i.source._offsetTimestamps?0:s},this.trackTimestampInfo.set(i,a)}if(i.source._offsetTimestamps&&(s-=a.timestampOffset),s<0)throw new Error(`Timestamps must be non-negative (got ${s}s).`);if(ss.start-a.start);e.push({start:r[0].start,size:r[0].data.byteLength});for(let s=1;sc.start<=r&&rdr){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 s={start:Math.floor(e/this.chunkSize)*this.chunkSize,data:new Uint8Array(this.chunkSize),written:[],shouldFlush:!1};return this.chunks.push(s),this.chunks.sort((a,o)=>a.start-o.start),this.chunks.indexOf(s)}queueChunksForFlush(e=!1){d(this.writer);for(let r=0;r{if(t==="avc"){let a=Math.ceil(i/16)*Math.ceil(e/16),o=rt.find(f=>a<=f.maxMacroblocks&&r<=f.maxBitrate)??S(rt),n=o?o.level:0,u="64".padStart(2,"0"),c="00",m=n.toString(16).padStart(2,"0");return`avc1.${u}${c}${m}`}else if(t==="hevc"){let s=0,a=1,o="6",n=i*e,u=it.find(f=>n<=f.maxPictureSize&&r<=f.maxBitrate)??S(it);return`hev1.${s===0?"":String.fromCharCode(65+s-1)}${a}.${o}.${u.tier}${u.level}.B0`}else{if(t==="vp8")return"vp8";if(t==="vp9"){let s="00",a=i*e,o=st.find(u=>a<=u.maxPictureSize&&r<=u.maxBitrate)??S(st);return`vp09.${s}.${o.level}.08`}else if(t==="av1"){let a=i*e,o=at.find(u=>a<=u.maxPictureSize&&r<=u.maxBitrate)??S(at);return`av01.0.${o.level.toString().padStart(2,"0")}${o.tier}.08`}}throw new TypeError(`Unhandled codec '${t}'.`)},nt=(t,i,e)=>{if(t==="aac")return i>=2&&e<=24e3?"mp4a.40.29":e<=24e3?"mp4a.40.5":"mp4a.40.2";if(t==="opus")return"opus";if(t==="vorbis")return"vorbis";throw new TypeError(`Unhandled codec '${t}'.`)},pe=t=>{if(!t)throw new TypeError("Video chunk metadata must be provided.");if(typeof t!="object")throw new TypeError("Video chunk metadata must be an object.");if(!t.decoderConfig)throw new TypeError("Video chunk metadata must include a decoder configuration.");if(typeof t.decoderConfig!="object")throw new TypeError("Video chunk metadata decoder configuration must be an object.");if(typeof t.decoderConfig.codec!="string")throw new TypeError("Video chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(t.decoderConfig.codedWidth)||t.decoderConfig.codedWidth<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedWidth (positive integer).");if(!Number.isInteger(t.decoderConfig.codedHeight)||t.decoderConfig.codedHeight<=0)throw new TypeError("Video chunk metadata decoder configuration must specify a valid codedHeight (positive integer).");if(t.decoderConfig.description!==void 0&&!Ce(t.decoderConfig.description))throw new TypeError("Video chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(t.decoderConfig.colorSpace!==void 0){let{colorSpace:i}=t.decoderConfig;if(typeof i!="object")throw new TypeError("Video chunk metadata decoder configuration colorSpace, when provided, must be an object.");let e=Object.keys(R);if(i.primaries!=null&&!e.includes(i.primaries))throw new TypeError(`Video chunk metadata decoder configuration colorSpace primaries, when defined, must be one of ${e.join(", ")}.`);let r=Object.keys(F);if(i.transfer!=null&&!r.includes(i.transfer))throw new TypeError(`Video chunk metadata decoder configuration colorSpace transfer, when defined, must be one of ${r.join(", ")}.`);let s=Object.keys(N);if(i.matrix!=null&&!s.includes(i.matrix))throw new TypeError(`Video chunk metadata decoder configuration colorSpace matrix, when defined, must be one of ${s.join(", ")}.`);if(i.fullRange!=null&&typeof i.fullRange!="boolean")throw new TypeError("Video chunk metadata decoder configuration colorSpace fullRange, when defined, must be a boolean.")}if((t.decoderConfig.codec.startsWith("avc1")||t.decoderConfig.codec.startsWith("avc3"))&&!t.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((t.decoderConfig.codec.startsWith("hev1")||t.decoderConfig.codec.startsWith("hvc1"))&&!t.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((t.decoderConfig.codec==="vp8"||t.decoderConfig.codec.startsWith("vp09"))&&t.decoderConfig.colorSpace===void 0)throw new TypeError("Video chunk metadata decoder configuration for VP8/VP9 must include a colorSpace.")},he=t=>{if(!t)throw new TypeError("Audio chunk metadata must be provided.");if(typeof t!="object")throw new TypeError("Audio chunk metadata must be an object.");if(!t.decoderConfig)throw new TypeError("Audio chunk metadata must include a decoder configuration.");if(typeof t.decoderConfig!="object")throw new TypeError("Audio chunk metadata decoder configuration must be an object.");if(typeof t.decoderConfig.codec!="string")throw new TypeError("Audio chunk metadata decoder configuration must specify a codec string.");if(!Number.isInteger(t.decoderConfig.sampleRate)||t.decoderConfig.sampleRate<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid sampleRate (positive integer).");if(!Number.isInteger(t.decoderConfig.numberOfChannels)||t.decoderConfig.numberOfChannels<=0)throw new TypeError("Audio chunk metadata decoder configuration must specify a valid numberOfChannels (positive integer).");if(t.decoderConfig.description!==void 0&&!Ce(t.decoderConfig.description))throw new TypeError("Audio chunk metadata decoder configuration description, when defined, must be an ArrayBuffer or an ArrayBuffer view.");if(t.decoderConfig.codec==="opus"&&t.decoderConfig.description&&t.decoderConfig.description.byteLength<18)throw new TypeError("Invalid decoder description provided for Opus; must be at least 18 bytes long.")},be=t=>{if(!t)throw new TypeError("Subtitle metadata must be provided.");if(typeof t!="object")throw new TypeError("Subtitle metadata must be an object.");if(!t.config)throw new TypeError("Subtitle metadata must include a config object.");if(typeof t.config!="object")throw new TypeError("Subtitle metadata config must be an object.");if(typeof t.config.description!="string")throw new TypeError("Subtitle metadata config description must be a string.")};var ce=1e3,mr=2082844800,v=(t,i,e=!0)=>{let r=t*i;return e?Math.round(r):r},xe=class extends Q{constructor(e,r){super(e);this.timestampsMustStartAtZero=!0;this.auxTarget=new J;this.auxWriter=this.auxTarget._createWriter();this.auxBoxWriter=new G(this.auxWriter);this.ftypSize=null;this.mdat=null;this.trackDatas=[];this.creationTime=Math.floor(Date.now()/1e3)+mr;this.finalizedChunks=[];this.nextFragmentNumber=1;this.writer=e._writer,this.boxWriter=new G(this.writer),this.fastStart=r._options.fastStart??(this.writer instanceof $?"in-memory":!1),(this.fastStart==="in-memory"||this.fastStart==="fragmented")&&(this.writer.ensureMonotonicity=!0)}async start(){let e=await this.mutex.acquire(),r=this.output._tracks.some(s=>s.type==="video"&&s.source._codec==="avc");this.boxWriter.writeBox(Xe({holdsAvc:r,fragmented:this.fastStart==="fragmented"})),this.ftypSize=this.writer.getPos(),this.fastStart==="in-memory"?this.mdat=de(!1):this.fastStart==="fragmented"||(this.mdat=de(!0),this.boxWriter.writeBox(this.mdat)),await this.writer.flush(),e()}getVideoTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;pe(r),d(r),d(r.decoderConfig),d(r.decoderConfig.codedWidth!==void 0),d(r.decoderConfig.codedHeight!==void 0);let a={track:e,type:"video",info:{width:r.decoderConfig.codedWidth,height:r.decoderConfig.codedHeight,decoderConfig:r.decoderConfig},timescale:e.metadata.frameRate??57600,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getAudioTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;he(r),d(r),d(r.decoderConfig);let a={track:e,type:"audio",info:{numberOfChannels:r.decoderConfig.numberOfChannels,sampleRate:r.decoderConfig.sampleRate,decoderConfig:r.decoderConfig},timescale:r.decoderConfig.sampleRate,samples:[],sampleQueue:[],timestampProcessingQueue:[],timeToSampleTable:[],compositionTimeOffsetTable:[],lastTimescaleUnits:null,lastSample:null,finalizedChunks:[],currentChunk:null,compactlyCodedChunkTable:[]};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getSubtitleTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;be(r),d(r),d(r.config);let a={track:e,type:"subtitle",info:{config:r.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(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),this.validateAndNormalizeTimestamp(e,0,!0),a}async addEncodedVideoChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createSampleForTrack(o,n,u,(r.duration??0)/1e6,r.type);await this.registerSample(o,c)}finally{a()}}async addEncodedAudioChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createSampleForTrack(o,n,u,(r.duration??0)/1e6,r.type);await this.registerSample(o,c)}finally{a()}}async addSubtitleCue(e,r,s){let a=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,s);this.validateAndNormalizeTimestamp(o.track,1e6*r.timestamp,!0),e.source._codec==="webvtt"&&(o.cueQueue.push(r),await this.processWebVTTCues(o,r.timestamp))}finally{a()}}async processWebVTTCues(e,r){for(;e.cueQueue.length>0;){let s=new Set([]);for(let m of e.cueQueue)d(m.timestamp<=r),d(e.lastCueEndTimestamp<=m.timestamp+m.duration),s.add(Math.max(m.timestamp,e.lastCueEndTimestamp)),s.add(m.timestamp+m.duration);let a=[...s].sort((m,f)=>m-f),o=a[0],n=a[1]??o;if(r=n)break;H.lastIndex=0;let w=H.test(f.text),O=f.timestamp+f.duration,C=e.cueToSourceId.get(f);if(C===void 0&&ns.timestamp).sort((s,a)=>s-a);for(let s=0;s{if(e===n)return r.type==="key";let u=n.sampleQueue[0];return u&&u.type==="key"});a>=1&&o&&(s=!0,await this.finalizeFragment())}else s=a>=.5}s&&(e.currentChunk&&await this.finalizeCurrentChunk(e),e.currentChunk={startTimestamp:r.timestamp,samples:[],offset:null,moofOffset:null}),d(e.currentChunk),e.currentChunk.samples.push(r),e.timestampProcessingQueue.push(r)}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||S(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 r of e.currentChunk.samples)d(r.data),this.writer.write(r.data),r.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(r=>r.track===e))return;e:for(;;){let e=null,r=1/0;for(let a of this.trackDatas){if(a.sampleQueue.length===0&&!a.track.source._closed)break e;a.sampleQueue.length>0&&a.sampleQueue[0].timestamp=2**32&&(u.largeSize=!0,m=this.boxWriter.measureBox(u)+c),u.size=m,this.boxWriter.writeBox(u)}for(let u of this.trackDatas){u.currentChunk.offset=this.writer.getPos(),u.currentChunk.moofOffset=s;for(let c of u.currentChunk.samples)this.writer.write(c.data),c.data=null}let o=this.writer.getPos();this.writer.seek(this.boxWriter.offsets.get(a));let n=ve(r,this.trackDatas);this.boxWriter.writeBox(n),this.writer.seek(o);for(let u of this.trackDatas)u.finalizedChunks.push(u.currentChunk),this.finalizedChunks.push(u.currentChunk),u.currentChunk=null;e&&await this.writer.flush()}async onTrackClose(e){let r=await this.mutex.acquire();if(e.type==="subtitle"&&e.source._codec==="webvtt"){let s=this.trackDatas.find(a=>a.track===e);s&&await this.processWebVTTCues(s,1/0)}this.fastStart==="fragmented"&&await this.interleaveSamples(),r()}async finalize(){let e=await this.mutex.acquire();for(let r of this.trackDatas)r.type==="subtitle"&&r.track.source._codec==="webvtt"&&await this.processWebVTTCues(r,1/0);if(this.fastStart==="fragmented"){for(let r of this.trackDatas){for(let s of r.sampleQueue)await this.addSampleToTrack(r,s);this.processTimestamps(r)}await this.finalizeFragment(!1)}else for(let r of this.trackDatas)this.processTimestamps(r),await this.finalizeCurrentChunk(r);if(this.fastStart==="in-memory"){d(this.mdat);let r;for(let a=0;a<2;a++){let o=Y(this.trackDatas,this.creationTime),n=this.boxWriter.measureBox(o);r=this.boxWriter.measureBox(this.mdat);let u=this.writer.getPos()+n+r;for(let c of this.finalizedChunks){c.offset=u;for(let{data:m}of c.samples)d(m),u+=m.byteLength,r+=m.byteLength}if(u<2**32)break;r>=2**32&&(this.mdat.largeSize=!0)}let s=Y(this.trackDatas,this.creationTime);this.boxWriter.writeBox(s),this.mdat.size=r,this.boxWriter.writeBox(this.mdat);for(let a of this.finalizedChunks)for(let o of a.samples)d(o.data),this.writer.write(o.data),o.data=null}else if(this.fastStart==="fragmented"){let r=this.writer.getPos(),s=Ze(this.trackDatas);this.boxWriter.writeBox(s);let a=this.writer.getPos()-r;this.writer.seek(this.writer.getPos()-4),this.boxWriter.writeU32(a)}else{d(this.mdat),d(this.ftypSize!==null);let r=this.boxWriter.offsets.get(this.mdat);d(r!==void 0);let s=this.writer.getPos()-r;this.mdat.size=s,this.mdat.largeSize=s>=2**32,this.boxWriter.patchBox(this.mdat);let a=Y(this.trackDatas,this.creationTime);if(typeof this.fastStart=="object"){this.writer.seek(this.ftypSize),this.boxWriter.writeBox(a);let o=r-this.writer.getPos();this.boxWriter.writeBox(Ge(o))}else this.boxWriter.writeBox(a)}e()}};var ee=class{constructor(i){this.value=i}},j=class{constructor(i){this.value=i}},te=class{constructor(i){this.value=i}};var Ae=t=>t<256?1:t<65536?2:t<1<<24?3:t<2**32?4:t<2**40?5:6,Oe=t=>t>=-64&&t<64?1:t>=-8192&&t<8192?2:t>=-(1<<20)&&t<1<<20?3:t>=-(1<<27)&&t<1<<27?4:t>=-(2**34)&&t<2**34?5:6,ut=t=>{if(t<127)return 1;if(t<16383)return 2;if(t<(1<<21)-1)return 3;if(t<(1<<28)-1)return 4;if(t<2**35-1)return 5;if(t<2**42-1)return 6;throw new Error("EBML VINT size not supported "+t)};var Ee=2**15,lt="https://github.com/Vanilagy/webm-muxer",ct=6,dt=5,fr={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"},pr={video:1,audio:2,subtitle:17},we=class extends Q{constructor(e,r){super(e);this.timestampsMustStartAtZero=!1;this.helper=new Uint8Array(8);this.helperView=new DataView(this.helper.buffer);this.offsets=new WeakMap;this.dataOffsets=new WeakMap;this.trackDatas=[];this.segment=null;this.segmentInfo=null;this.seekHead=null;this.tracksElement=null;this.segmentDuration=null;this.cues=null;this.currentCluster=null;this.currentClusterMsTimestamp=null;this.trackDatasInCurrentCluster=new Set;this.duration=0;this.writer=e._writer,this.format=r,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,r=Ae(e)){let s=0;switch(r){case 6:this.helperView.setUint8(s++,e/2**40|0);case 5:this.helperView.setUint8(s++,e/2**32|0);case 4:this.helperView.setUint8(s++,e>>24);case 3:this.helperView.setUint8(s++,e>>16);case 2:this.helperView.setUint8(s++,e>>8);case 1:this.helperView.setUint8(s++,e);break;default:throw new Error("Bad UINT size "+r)}this.writer.write(this.helper.subarray(0,s))}writeSignedInt(e,r=Oe(e)){e<0&&(e+=2**(r*8)),this.writeUnsignedInt(e,r)}writeEBMLVarInt(e,r=ut(e)){let s=0;switch(r){case 1:this.helperView.setUint8(s++,128|e);break;case 2:this.helperView.setUint8(s++,64|e>>8),this.helperView.setUint8(s++,e);break;case 3:this.helperView.setUint8(s++,32|e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 4:this.helperView.setUint8(s++,16|e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 5:this.helperView.setUint8(s++,8|e/2**32&7),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;case 6:this.helperView.setUint8(s++,4|e/2**40&3),this.helperView.setUint8(s++,e/2**32|0),this.helperView.setUint8(s++,e>>24),this.helperView.setUint8(s++,e>>16),this.helperView.setUint8(s++,e>>8),this.helperView.setUint8(s++,e);break;default:throw new Error("Bad EBML VINT size "+r)}this.writer.write(this.helper.subarray(0,s))}writeString(e){this.writer.write(new Uint8Array(e.split("").map(r=>r.charCodeAt(0))))}writeEBML(e){if(e!==null){if(e instanceof Uint8Array)this.writer.write(e);else if(Array.isArray(e))for(let r of e)this.writeEBML(r);else if(this.offsets.set(e,this.writer.getPos()),this.writeUnsignedInt(e.id),Array.isArray(e.data)){let r=this.writer.getPos(),s=e.size===-1?1:e.size??4;e.size===-1?this.writeByte(255):this.writer.seek(this.writer.getPos()+s);let a=this.writer.getPos();if(this.dataOffsets.set(e,a),this.writeEBML(e.data),e.size!==-1){let o=this.writer.getPos()-a,n=this.writer.getPos();this.writer.seek(r),this.writeEBMLVarInt(o,s),this.writer.seek(n)}}else if(typeof e.data=="number"){let r=e.size??Ae(e.data);this.writeEBMLVarInt(r),this.writeUnsignedInt(e.data,r)}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 ee)this.writeEBMLVarInt(4),this.writeFloat32(e.data.value);else if(e.data instanceof j)this.writeEBMLVarInt(8),this.writeFloat64(e.data.value);else if(e.data instanceof te){let r=e.size??Oe(e.data.value);this.writeEBMLVarInt(r),this.writeSignedInt(e.data.value,r)}}}beforeTrackAdd(e){if(this.format instanceof L)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 L?"webm":"matroska"},{id:17031,data:2},{id:17029,data:2}]};this.writeEBML(e)}createSeekHead(){let e=new Uint8Array([28,83,187,107]),r=new Uint8Array([21,73,169,102]),s=new Uint8Array([22,84,174,107]),a={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:r},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:s},{id:21420,size:5,data:0}]}]};this.seekHead=a}createSegmentInfo(){let e={id:17545,data:new j(0)};this.segmentDuration=e;let r={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:lt},{id:22337,data:lt},this.format._options.streamable?null:e]};this.segmentInfo=r}createTracks(){let e={id:374648427,data:[]};this.tracksElement=e;for(let r of this.trackDatas)e.data.push({id:174,data:[{id:215,data:r.track.id},{id:29637,data:r.track.id},{id:131,data:pr[r.type]},{id:134,data:fr[r.track.source._codec]},...r.type==="video"?[r.info.decoderConfig.description?{id:25506,data:P(r.info.decoderConfig.description)}:null,r.track.metadata.frameRate?{id:2352003,data:1e9/r.track.metadata.frameRate}:null,{id:224,data:[{id:176,data:r.info.width},{id:186,data:r.info.height},(()=>{if(r.info.decoderConfig.colorSpace){let s=r.info.decoderConfig.colorSpace;return oe(s)?{id:21936,data:[{id:21937,data:N[s.matrix]},{id:21946,data:F[s.transfer]},{id:21947,data:R[s.primaries]},{id:21945,data:[1,2][Number(s.fullRange)]}]}:null}return null})()]}]:[],...r.type==="audio"?[r.info.decoderConfig.description?{id:25506,data:P(r.info.decoderConfig.description)}:null,{id:225,data:[{id:181,data:new ee(r.info.sampleRate)},{id:159,data:r.info.numberOfChannels}]}]:[],...r.type==="subtitle"?[{id:25506,data:y.encode(r.info.config.description)}]:[]]})}createSegment(){let e={id:408125543,size:this.format._options.streamable?-1:ct,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,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;pe(r),d(r),d(r.decoderConfig),d(r.decoderConfig.codedWidth!==void 0),d(r.decoderConfig.codedHeight!==void 0);let a={track:e,type:"video",info:{width:r.decoderConfig.codedWidth,height:r.decoderConfig.codedHeight,decoderConfig:r.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getAudioTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;he(r),d(r),d(r.decoderConfig);let a={track:e,type:"audio",info:{numberOfChannels:r.decoderConfig.numberOfChannels,sampleRate:r.decoderConfig.sampleRate,decoderConfig:r.decoderConfig},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}getSubtitleTrackData(e,r){let s=this.trackDatas.find(o=>o.track===e);if(s)return s;be(r),d(r),d(r.config);let a={track:e,type:"subtitle",info:{config:r.config},chunkQueue:[],lastWrittenMsTimestamp:null};return this.trackDatas.push(a),this.trackDatas.sort((o,n)=>o.track.id-n.track.id),a}async addEncodedVideoChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getVideoTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createInternalChunk(n,u,(r.duration??0)/1e6,r.type);e.source._codec==="vp9"&&this.fixVP9ColorSpace(o,c),o.chunkQueue.push(c),await this.interleaveChunks()}finally{a()}}async addEncodedAudioChunk(e,r,s){let a=await this.mutex.acquire();try{let o=this.getAudioTrackData(e,s),n=new Uint8Array(r.byteLength);r.copyTo(n);let u=this.validateAndNormalizeTimestamp(o.track,r.timestamp,r.type==="key"),c=this.createInternalChunk(n,u,(r.duration??0)/1e6,r.type);o.chunkQueue.push(c),await this.interleaveChunks()}finally{a()}}async addSubtitleCue(e,r,s){let a=await this.mutex.acquire();try{let o=this.getSubtitleTrackData(e,s),n=this.validateAndNormalizeTimestamp(o.track,1e6*r.timestamp,!0),u=r.text,c=Math.floor(n*1e3);H.lastIndex=0,u=u.replace(H,O=>{let k=ue(O.slice(1,-1))-c;return`<${le(k)}>`});let m=y.encode(u),f=`${r.settings??""} +${r.identifier??""} +${r.notes??""}`,w=this.createInternalChunk(m,n,r.duration,"key",f.trim()?y.encode(f):null);o.chunkQueue.push(w),await this.interleaveChunks()}finally{a()}}async interleaveChunks(){for(let e of this.output._tracks)if(!e.source._closed&&!this.trackDatas.some(r=>r.track===e))return;e:for(;;){let e=null,r=1/0;for(let a of this.trackDatas){if(a.chunkQueue.length===0&&!a.track.source._closed)break e;a.chunkQueue.length>0&&a.chunkQueue[0].timestamp=2&&s++;let c={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[e.info.decoderConfig.colorSpace.matrix];He(r.data,s+0,s+3,c)}createInternalChunk(e,r,s,a,o=null){return{data:e,type:a,timestamp:r,duration:s,additions:o}}writeBlock(e,r){this.segment||(this.createTracks(),this.createSegment());let s=Math.floor(1e3*r.timestamp),a=this.trackDatas.every(f=>{if(f.track.source._closed)return!0;if(e===f)return r.type==="key";let w=f.chunkQueue[0];return w&&w.type==="key"});(!this.currentCluster||a&&s-this.currentClusterMsTimestamp>=1e3)&&this.createNewCluster(s);let o=s-this.currentClusterMsTimestamp;if(o<0)return;if(o>=Ee)throw new Error(`Current Matroska cluster exceeded its maximum allowed length of ${Ee} milliseconds. In order to produce a correct WebM file, you must pass in a key frame at least every ${Ee} milliseconds.`);let u=new Uint8Array(4),c=new DataView(u.buffer);c.setUint8(0,128|e.track.id),c.setInt16(1,o,!1);let m=Math.floor(1e3*r.duration);if(m===0&&!r.additions){c.setUint8(3,+(r.type==="key")<<7);let f={id:163,data:[u,r.data]};this.writeEBML(f)}else{let f={id:160,data:[{id:161,data:[u,r.data]},r.type==="delta"?{id:251,data:new te(e.lastWrittenMsTimestamp-s)}:null,r.additions?{id:30113,data:[{id:166,data:[{id:165,data:r.additions},{id:238,data:1}]}]}:null,m>0?{id:155,data:m}:null]};this.writeEBML(f)}this.duration=Math.max(this.duration,s+m),e.lastWrittenMsTimestamp=s,this.trackDatasInCurrentCluster.add(e)}createNewCluster(e){this.currentCluster&&!this.format._options.streamable&&this.finalizeCurrentCluster(),this.currentCluster={id:524531317,size:this.format._options.streamable?-1:dt,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),r=this.writer.getPos();this.writer.seek(this.offsets.get(this.currentCluster)+4),this.writeEBMLVarInt(e,dt),this.writer.seek(r);let s=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(a=>({id:183,data:[{id:247,data:a.track.id},{id:241,data:s}]}))]})}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 r of this.trackDatas)for(;r.chunkQueue.length>0;)this.writeBlock(r,r.chunkQueue.shift());if(!this.format._options.streamable&&this.currentCluster&&this.finalizeCurrentCluster(),d(this.cues),this.writeEBML(this.cues),!this.format._options.streamable){let r=this.writer.getPos(),s=this.writer.getPos()-this.segmentDataOffset;this.writer.seek(this.offsets.get(this.segment)+4),this.writeEBMLVarInt(s,ct),this.segmentDuration.data=new j(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(r)}e()}};var U=class{},Me=class extends U{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.fastStart!==void 0&&![!1,"in-memory","fragmented"].includes(i.fastStart))throw new TypeError('options.fastStart, when provided, must be false, "in-memory", or "fragmented".');super(),this._options=i}_createMuxer(i){return new xe(i,this)}},Te=class extends U{constructor(i={}){if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(i.streamable!==void 0&&typeof i.streamable!="boolean")throw new TypeError("options.streamable, when provided, must be a boolean.");super(),this._options=i}_createMuxer(i){return new we(i,this)}},L=class extends Te{};var re=["avc","hevc","vp8","vp9","av1"],ie=["aac","opus"],Ve=["webvtt"],q=class{constructor(){this._connectedTrack=null;this._closed=!1;this._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)}},E=class extends q{constructor(e){super();this._connectedTrack=null;if(!re.includes(e))throw new TypeError(`Invalid video codec '${e}'. Must be one of: ${re.join(", ")}.`);this._codec=e}},ze=class extends E{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedVideoChunk))throw new TypeError("chunk must be an EncodedVideoChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedVideoChunk(this._connectedTrack,i,e)}},hr=5,br=t=>{if(!t||typeof t!="object")throw new TypeError("Codec config must be an object.");if(!re.includes(t.codec))throw new TypeError(`Invalid video codec '${t.codec}'. Must be one of: ${re.join(", ")}.`);if(!Number.isInteger(t.bitrate)||t.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.");if(t.latencyMode!==void 0&&["quality","realtime"].includes(t.latencyMode))throw new TypeError("config.latencyMode, when provided, must be 'quality' or 'realtime'.")},se=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastMultipleOfKeyFrameInterval=-1;this.lastWidth=null;this.lastHeight=null;br(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastWidth!==null&&this.lastHeight!==null){if(i.codedWidth!==this.lastWidth||i.codedHeight!==this.lastHeight)throw new Error(`Video frame size must remain constant. Expected ${this.lastWidth}x${this.lastHeight}, got ${i.codedWidth}x${i.codedHeight}.`)}else this.lastWidth=i.codedWidth,this.lastHeight=i.codedHeight;this.ensureEncoder(i),d(this.encoder);let e=Math.floor(i.timestamp/1e6/hr);this.encoder.encode(i,{keyFrame:e!==this.lastMultipleOfKeyFrameInterval}),this.lastMultipleOfKeyFrameInterval=e,this.encoder.encodeQueueSize>=4&&await new Promise(r=>this.encoder.addEventListener("dequeue",r,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new VideoEncoder({output:(e,r)=>this.muxer.addEncodedVideoChunk(this.source._connectedTrack,e,r),error:e=>console.error("Video encode error:",e)}),this.encoder.configure({codec:ot(this.codecConfig.codec,i.codedWidth,i.codedHeight,this.codecConfig.bitrate),width:i.codedWidth,height:i.codedHeight,bitrate:this.codecConfig.bitrate,framerate:this.source._connectedTrack?.metadata.frameRate,latencyMode:this.codecConfig.latencyMode}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},Pe=class extends E{constructor(i){super(i.codec),this._encoder=new se(this,i)}digest(i){if(!(i instanceof VideoFrame))throw new TypeError("videoFrame must be a VideoFrame.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},Be=class extends E{constructor(i,e){if(!(i instanceof HTMLCanvasElement))throw new TypeError("canvas must be an HTMLCanvasElement.");super(e.codec),this._encoder=new se(this,e),this._canvas=i}digest(i,e=0){if(!Number.isFinite(i)||i<0)throw new TypeError("timestamp must be a non-negative number.");if(!Number.isFinite(e)||e<0)throw new TypeError("duration must be a non-negative number.");let r=new VideoFrame(this._canvas,{timestamp:Math.round(1e6*i),duration:Math.round(1e6*e),alpha:"discard"}),s=this._encoder.digest(r);return r.close(),s}_flush(){return this._encoder.flush()}},Ie=class extends E{constructor(e,r){if(!(e instanceof MediaStreamTrack)||e.kind!=="video")throw new TypeError("track must be a video MediaStreamTrack.");r={...r,latencyMode:"realtime"};super(r.codec);this._abortController=null;this._offsetTimestamps=!0;this._encoder=new se(this,r),this._track=e}_start(){this._abortController=new AbortController;let e=new MediaStreamTrackProcessor({track:this._track}),r=new WritableStream({write:s=>{this._encoder.digest(s),s.close()}});e.readable.pipeTo(r,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},M=class extends q{constructor(e){super();this._connectedTrack=null;if(!ie.includes(e))throw new TypeError(`Invalid audio codec '${e}'. Must be one of: ${ie.join(", ")}.`);this._codec=e}},Ue=class extends M{constructor(i){super(i)}digest(i,e){if(!(i instanceof EncodedAudioChunk))throw new TypeError("chunk must be an EncodedAudioChunk.");return this._ensureValidDigest(),this._connectedTrack.output._muxer.addEncodedAudioChunk(this._connectedTrack,i,e)}},xr=t=>{if(!t||typeof t!="object")throw new TypeError("Codec config must be an object.");if(!ie.includes(t.codec))throw new TypeError(`Invalid audio codec '${t.codec}'. Must be one of: ${ie.join(", ")}.`);if(!Number.isInteger(t.bitrate)||t.bitrate<=0)throw new TypeError("config.bitrate must be a positive integer.")},ae=class{constructor(i,e){this.source=i;this.codecConfig=e;this.encoder=null;this.muxer=null;this.lastNumberOfChannels=null;this.lastSampleRate=null;xr(e)}async digest(i){if(this.source._ensureValidDigest(),this.lastNumberOfChannels!==null&&this.lastSampleRate!==null){if(i.numberOfChannels!==this.lastNumberOfChannels||i.sampleRate!==this.lastSampleRate)throw new Error(`Audio parameters must remain constant. Expected ${this.lastNumberOfChannels} channels at ${this.lastSampleRate} Hz, got ${i.numberOfChannels} channels at ${i.sampleRate} Hz.`)}else this.lastNumberOfChannels=i.numberOfChannels,this.lastSampleRate=i.sampleRate;this.ensureEncoder(i),d(this.encoder),this.encoder.encode(i),this.encoder.encodeQueueSize>=4&&await new Promise(e=>this.encoder.addEventListener("dequeue",e,{once:!0})),await this.muxer.mutex.currentPromise}ensureEncoder(i){this.encoder||(this.encoder=new AudioEncoder({output:(e,r)=>this.muxer.addEncodedAudioChunk(this.source._connectedTrack,e,r),error:e=>console.error("Audio encode error:",e)}),this.encoder.configure({codec:nt(this.codecConfig.codec,i.numberOfChannels,i.sampleRate),numberOfChannels:i.numberOfChannels,sampleRate:i.sampleRate,bitrate:this.codecConfig.bitrate}),d(this.source._connectedTrack),this.muxer=this.source._connectedTrack.output._muxer)}async flush(){this.encoder&&(await this.encoder.flush(),this.encoder.close())}},De=class extends M{constructor(i){super(i.codec),this._encoder=new ae(this,i)}digest(i){if(!(i instanceof AudioData))throw new TypeError("audioData must be an AudioData.");return this._encoder.digest(i)}_flush(){return this._encoder.flush()}},We=class extends M{constructor(e){super(e.codec);this._accumulatedFrameCount=0;this._encoder=new ae(this,e)}digest(e){if(!(e instanceof AudioBuffer))throw new TypeError("audioBuffer must be an AudioBuffer.");let r=e.numberOfChannels,s=e.sampleRate,a=e.length,o=new Float32Array(r*a);for(let c=0;c{this._encoder.digest(s),s.close()}});e.readable.pipeTo(r,{signal:this._abortController.signal}).catch(s=>{s instanceof DOMException&&s.name==="AbortError"||console.error("Pipe error:",s)})}async _flush(){this._abortController&&(this._abortController.abort(),this._abortController=null),await this._encoder.flush()}},K=class extends q{constructor(e){super();this._connectedTrack=null;if(!Ve.includes(e))throw new TypeError(`Invalid subtitle codec '${e}'. Must be one of: ${Ve.join(", ")}.`);this._codec=e}},Fe=class extends K{constructor(i){super(i),this._parser=new ne({codec:i,output:(e,r)=>this._connectedTrack?.output._muxer.addSubtitleCue(this._connectedTrack,e,r),error:e=>console.error("Subtitle parse error:",e)})}digest(i){if(typeof i!="string")throw new TypeError("text must be a string.");return this._ensureValidDigest(),this._parser.parse(i),this._connectedTrack.output._muxer.mutex.currentPromise}};var Ne=class{constructor(i){this._tracks=[];this._started=!1;this._finalizing=!1;this._mutex=new W;if(!i||typeof i!="object")throw new TypeError("options must be an object.");if(!(i.format instanceof U))throw new TypeError("options.format must be an OutputFormat.");if(!(i.target instanceof I))throw new TypeError("options.target must be a Target.");if(i.target._output)throw new Error("Target is already used for another output.");i.target._output=this,this._writer=i.target._createWriter(),this._muxer=i.format._createMuxer(this)}addVideoTrack(i,e={}){if(!(i instanceof E))throw new TypeError("source must be a VideoSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");if(typeof e.rotation=="number"&&![0,90,180,270].includes(e.rotation))throw new TypeError(`Invalid video rotation: ${e.rotation}. Has to be 0, 90, 180 or 270.`);if(Array.isArray(e.rotation)&&(e.rotation.length!==9||e.rotation.some(r=>!Number.isFinite(r))))throw new TypeError(`Invalid video transformation matrix: ${e.rotation.join()}`);if(e.frameRate!==void 0&&(!Number.isInteger(e.frameRate)||e.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${e.frameRate}. Must be a positive integer.`);this._addTrack("video",i,e)}addAudioTrack(i,e={}){if(!(i instanceof M))throw new TypeError("source must be an AudioSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("audio",i,e)}addSubtitleTrack(i,e={}){if(!(i instanceof K))throw new TypeError("source must be a SubtitleSource.");if(!e||typeof e!="object")throw new TypeError("metadata must be an object.");this._addTrack("subtitle",i,e)}_addTrack(i,e,r){if(this._started)throw new Error("Cannot add track after output has started.");if(e._connectedTrack)throw new Error("Source is already used for a track.");let s={id:this._tracks.length+1,output:this,type:i,source:e,metadata:r};this._muxer.beforeTrackAdd(s),this._tracks.push(s),e._connectedTrack=s}async start(){if(this._started)throw new Error("Output already started.");this._started=!0,this._writer.start();let i=await this._mutex.acquire();await this._muxer.start();for(let e of this._tracks)e.source._start();i()}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 i=await this._mutex.acquire(),e=this._tracks.map(r=>r.source._flush());await Promise.all(e),await this._muxer.finalize(),await this._writer.flush(),await this._writer.finalize(),i()}};export{ie as AUDIO_CODECS,J as ArrayBufferTarget,We as AudioBufferSource,De as AudioDataSource,M as AudioSource,Be as CanvasSource,Ue as EncodedAudioChunkSource,ze as EncodedVideoChunkSource,q as MediaSource,Re as MediaStreamAudioTrackSource,Ie as MediaStreamVideoTrackSource,Te as MkvOutputFormat,Me as Mp4OutputFormat,Ne as Output,U as OutputFormat,Ve as SUBTITLE_CODECS,_e as StreamTarget,K as SubtitleSource,I as Target,Fe as TextSubtitleSource,re as VIDEO_CODECS,Pe as VideoFrameSource,E as VideoSource,L as WebMOutputFormat}; diff --git a/dist/metamuxer.mjs b/dist/metamuxer.mjs index c2d3332..03b8a44 100644 --- a/dist/metamuxer.mjs +++ b/dist/metamuxer.mjs @@ -1411,76 +1411,211 @@ var StreamTarget = class extends Target { }; // src/codec.ts -var buildVideoCodecString = (codec, width, height) => { +var AVC_LEVEL_TABLE = [ + { maxMacroblocks: 99, maxBitrate: 64e3, level: 10 }, + // Level 1 + { maxMacroblocks: 396, maxBitrate: 192e3, level: 11 }, + // Level 1.1 + { maxMacroblocks: 396, maxBitrate: 384e3, level: 12 }, + // Level 1.2 + { maxMacroblocks: 396, maxBitrate: 768e3, level: 13 }, + // Level 1.3 + { maxMacroblocks: 396, maxBitrate: 2e6, level: 20 }, + // Level 2 + { maxMacroblocks: 792, maxBitrate: 4e6, level: 21 }, + // Level 2.1 + { maxMacroblocks: 1620, maxBitrate: 4e6, level: 22 }, + // Level 2.2 + { maxMacroblocks: 1620, maxBitrate: 1e7, level: 30 }, + // Level 3 + { maxMacroblocks: 3600, maxBitrate: 14e6, level: 31 }, + // Level 3.1 + { maxMacroblocks: 5120, maxBitrate: 2e7, level: 32 }, + // Level 3.2 + { maxMacroblocks: 8192, maxBitrate: 2e7, level: 40 }, + // Level 4 + { maxMacroblocks: 8192, maxBitrate: 5e7, level: 41 }, + // Level 4.1 + { maxMacroblocks: 8704, maxBitrate: 5e7, level: 42 }, + // Level 4.2 + { maxMacroblocks: 22080, maxBitrate: 135e6, level: 50 }, + // Level 5 + { maxMacroblocks: 36864, maxBitrate: 24e7, level: 51 }, + // Level 5.1 + { maxMacroblocks: 36864, maxBitrate: 24e7, level: 52 }, + // Level 5.2 + { maxMacroblocks: 139264, maxBitrate: 24e7, level: 60 }, + // Level 6 + { maxMacroblocks: 139264, maxBitrate: 48e7, level: 61 }, + // Level 6.1 + { maxMacroblocks: 139264, maxBitrate: 8e8, level: 62 } + // Level 6.2 +]; +var HEVC_LEVEL_TABLE = [ + { maxPictureSize: 36864, maxBitrate: 128e3, tier: "L", level: 30 }, + // Level 1 (Low Tier) + { maxPictureSize: 122880, maxBitrate: 15e5, tier: "L", level: 60 }, + // Level 2 (Low Tier) + { maxPictureSize: 245760, maxBitrate: 3e6, tier: "L", level: 63 }, + // Level 2.1 (Low Tier) + { maxPictureSize: 552960, maxBitrate: 6e6, tier: "L", level: 90 }, + // Level 3 (Low Tier) + { maxPictureSize: 983040, maxBitrate: 1e7, tier: "L", level: 93 }, + // Level 3.1 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 12e6, tier: "L", level: 120 }, + // Level 4 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 3e7, tier: "H", level: 120 }, + // Level 4 (High Tier) + { maxPictureSize: 2228224, maxBitrate: 2e7, tier: "L", level: 123 }, + // Level 4.1 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 5e7, tier: "H", level: 123 }, + // Level 4.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 25e6, tier: "L", level: 150 }, + // Level 5 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 1e8, tier: "H", level: 150 }, + // Level 5 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 4e7, tier: "L", level: 153 }, + // Level 5.1 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 16e7, tier: "H", level: 153 }, + // Level 5.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 6e7, tier: "L", level: 156 }, + // Level 5.2 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 24e7, tier: "H", level: 156 }, + // Level 5.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "L", level: 180 }, + // Level 6 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 180 }, + // Level 6 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 12e7, tier: "L", level: 183 }, + // Level 6.1 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 48e7, tier: "H", level: 183 }, + // Level 6.1 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "L", level: 186 }, + // Level 6.2 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 186 } + // Level 6.2 (High Tier) +]; +var VP9_LEVEL_TABLE = [ + { maxPictureSize: 36864, maxBitrate: 2e5, level: 10 }, + // Level 1 + { maxPictureSize: 73728, maxBitrate: 8e5, level: 11 }, + // Level 1.1 + { maxPictureSize: 122880, maxBitrate: 18e5, level: 20 }, + // Level 2 + { maxPictureSize: 245760, maxBitrate: 36e5, level: 21 }, + // Level 2.1 + { maxPictureSize: 552960, maxBitrate: 72e5, level: 30 }, + // Level 3 + { maxPictureSize: 983040, maxBitrate: 12e6, level: 31 }, + // Level 3.1 + { maxPictureSize: 2228224, maxBitrate: 18e6, level: 40 }, + // Level 4 + { maxPictureSize: 2228224, maxBitrate: 3e7, level: 41 }, + // Level 4.1 + { maxPictureSize: 8912896, maxBitrate: 6e7, level: 50 }, + // Level 5 + { maxPictureSize: 8912896, maxBitrate: 12e7, level: 51 }, + // Level 5.1 + { maxPictureSize: 8912896, maxBitrate: 18e7, level: 52 }, + // Level 5.2 + { maxPictureSize: 35651584, maxBitrate: 18e7, level: 60 }, + // Level 6 + { maxPictureSize: 35651584, maxBitrate: 24e7, level: 61 }, + // Level 6.1 + { maxPictureSize: 35651584, maxBitrate: 48e7, level: 62 } + // Level 6.2 +]; +var AV1_LEVEL_TABLE = [ + { maxPictureSize: 147456, maxBitrate: 15e5, tier: "M", level: 0 }, + // Level 2.0 (Main Tier) + { maxPictureSize: 278784, maxBitrate: 3e6, tier: "M", level: 1 }, + // Level 2.1 (Main Tier) + { maxPictureSize: 665856, maxBitrate: 6e6, tier: "M", level: 4 }, + // Level 3.0 (Main Tier) + { maxPictureSize: 1065024, maxBitrate: 1e7, tier: "M", level: 5 }, + // Level 3.1 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 12e6, tier: "M", level: 8 }, + // Level 4.0 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 3e7, tier: "H", level: 8 }, + // Level 4.0 (High Tier) + { maxPictureSize: 2359296, maxBitrate: 2e7, tier: "M", level: 9 }, + // Level 4.1 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 5e7, tier: "H", level: 9 }, + // Level 4.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 3e7, tier: "M", level: 12 }, + // Level 5.0 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 1e8, tier: "H", level: 12 }, + // Level 5.0 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 4e7, tier: "M", level: 13 }, + // Level 5.1 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 16e7, tier: "H", level: 13 }, + // Level 5.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 6e7, tier: "M", level: 14 }, + // Level 5.2 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 24e7, tier: "H", level: 14 }, + // Level 5.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "M", level: 15 }, + // Level 5.3 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 15 }, + // Level 5.3 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 6e7, tier: "M", level: 16 }, + // Level 6.0 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 24e7, tier: "H", level: 16 }, + // Level 6.0 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 1e8, tier: "M", level: 17 }, + // Level 6.1 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 48e7, tier: "H", level: 17 }, + // Level 6.1 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 16e7, tier: "M", level: 18 }, + // Level 6.2 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 18 }, + // Level 6.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 16e7, tier: "M", level: 19 }, + // Level 6.3 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 8e8, tier: "H", level: 19 } + // Level 6.3 (High Tier) +]; +var buildVideoCodecString = (codec, width, height, bitrate) => { if (codec === "avc") { - let profileIndication = 100; - if (width <= 768 && height <= 432) { - profileIndication = 66; - } else if (width <= 1920 && height <= 1080) { - profileIndication = 77; - } - const profileCompatibility = 0; - const levelIndication = width > 1920 || height > 1080 ? 50 : 41; + const profileIndication = 100; + const totalMacroblocks = Math.ceil(width / 16) * Math.ceil(height / 16); + const levelInfo = AVC_LEVEL_TABLE.find( + (level) => totalMacroblocks <= level.maxMacroblocks && bitrate <= level.maxBitrate + ) ?? last(AVC_LEVEL_TABLE); + const levelIndication = levelInfo ? levelInfo.level : 0; const hexProfileIndication = profileIndication.toString(16).padStart(2, "0"); - const hexProfileCompatibility = profileCompatibility.toString(16).padStart(2, "0"); + const hexProfileCompatibility = "00"; const hexLevelIndication = levelIndication.toString(16).padStart(2, "0"); return `avc1.${hexProfileIndication}${hexProfileCompatibility}${hexLevelIndication}`; } else if (codec === "hevc") { let profileSpace = 0; let profileIdc = 1; - const compatibilityFlags = Array(32).fill(0); - compatibilityFlags[profileIdc] = 1; - const compatibilityHex = parseInt(compatibilityFlags.reverse().join(""), 2).toString(16).replace(/^0+/, ""); - let tier = "L"; - let level = 120; - if (width <= 1280 && height <= 720) { - level = 93; - } else if (width <= 1920 && height <= 1080) { - level = 120; - } else if (width <= 3840 && height <= 2160) { - level = 150; - } else { - tier = "H"; - level = 180; - } + const compatibilityFlags = "6"; + const pictureSize = width * height; + const levelInfo = HEVC_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(HEVC_LEVEL_TABLE); const constraintFlags = "B0"; const profilePrefix = profileSpace === 0 ? "" : String.fromCharCode(65 + profileSpace - 1); - return `hev1.${profilePrefix}${profileIdc}.${compatibilityHex}.${tier}${level}.${constraintFlags}`; + return `hev1.${profilePrefix}${profileIdc}.${compatibilityFlags}.${levelInfo.tier}${levelInfo.level}.${constraintFlags}`; } else if (codec === "vp8") { return "vp8"; } else if (codec === "vp9") { const profile = "00"; - let level; - if (width <= 854 && height <= 480) { - level = "21"; - } else if (width <= 1280 && height <= 720) { - level = "31"; - } else if (width <= 1920 && height <= 1080) { - level = "41"; - } else if (width <= 3840 && height <= 2160) { - level = "51"; - } else { - level = "61"; - } + const pictureSize = width * height; + const levelInfo = VP9_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(VP9_LEVEL_TABLE); const bitDepth = "08"; - return `vp09.${profile}.${level}.${bitDepth}`; + return `vp09.${profile}.${levelInfo.level}.${bitDepth}`; } else if (codec === "av1") { const profile = 0; - let level; - if (width <= 854 && height <= 480) { - level = "01"; - } else if (width <= 1280 && height <= 720) { - level = "03"; - } else if (width <= 1920 && height <= 1080) { - level = "04"; - } else if (width <= 3840 && height <= 2160) { - level = "07"; - } else { - level = "09"; - } - const tier = "M"; + const pictureSize = width * height; + const levelInfo = AV1_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(AV1_LEVEL_TABLE); const bitDepth = "08"; - return `av01.${profile}.${level}${tier}.${bitDepth}`; + return `av01.${profile}.${levelInfo.level.toString().padStart(2, "0")}${levelInfo.tier}.${bitDepth}`; } throw new TypeError(`Unhandled codec '${codec}'.`); }; @@ -3070,7 +3205,7 @@ var VideoEncoderWrapper = class { error: (error) => console.error("Video encode error:", error) }); this.encoder.configure({ - codec: buildVideoCodecString(this.codecConfig.codec, videoFrame.codedWidth, videoFrame.codedHeight), + codec: buildVideoCodecString(this.codecConfig.codec, videoFrame.codedWidth, videoFrame.codedHeight, this.codecConfig.bitrate), width: videoFrame.codedWidth, height: videoFrame.codedHeight, bitrate: this.codecConfig.bitrate, diff --git a/package.json b/package.json index 3182423..193433b 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,12 @@ "import": "./dist/metamuxer.mjs", "require": "./dist/metamuxer.js" }, + "files": [ + "README.md", + "package.json", + "LICENSE", + "dist" + ], "scripts": { "build": "node build.mjs && tsc && api-extractor run && node append-namespace.mjs", "build-local": "node build.mjs && tsc && api-extractor run --local --verbose && node append-namespace.mjs", diff --git a/src/codec.ts b/src/codec.ts index f9d06b7..8608063 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -1,118 +1,158 @@ -import { COLOR_PRIMARIES_MAP, isAllowSharedBufferSource, MATRIX_COEFFICIENTS_MAP, TRANSFER_CHARACTERISTICS_MAP } from "./misc"; +import { COLOR_PRIMARIES_MAP, isAllowSharedBufferSource, last, MATRIX_COEFFICIENTS_MAP, TRANSFER_CHARACTERISTICS_MAP } from "./misc"; import { AudioCodec, VideoCodec } from "./source"; import { SubtitleMetadata } from "./subtitles"; -export const buildVideoCodecString = (codec: VideoCodec, width: number, height: number) => { - if (codec === 'avc') { - let profileIndication = 0x64; // Default to High Profile +// https://en.wikipedia.org/wiki/Advanced_Video_Coding +const AVC_LEVEL_TABLE = [ + { maxMacroblocks: 99, maxBitrate: 64000, level: 0x0A }, // Level 1 + { maxMacroblocks: 396, maxBitrate: 192000, level: 0x0B }, // Level 1.1 + { maxMacroblocks: 396, maxBitrate: 384000, level: 0x0C }, // Level 1.2 + { maxMacroblocks: 396, maxBitrate: 768000, level: 0x0D }, // Level 1.3 + { maxMacroblocks: 396, maxBitrate: 2000000, level: 0x14 }, // Level 2 + { maxMacroblocks: 792, maxBitrate: 4000000, level: 0x15 }, // Level 2.1 + { maxMacroblocks: 1620, maxBitrate: 4000000, level: 0x16 }, // Level 2.2 + { maxMacroblocks: 1620, maxBitrate: 10000000, level: 0x1E }, // Level 3 + { maxMacroblocks: 3600, maxBitrate: 14000000, level: 0x1F }, // Level 3.1 + { maxMacroblocks: 5120, maxBitrate: 20000000, level: 0x20 }, // Level 3.2 + { maxMacroblocks: 8192, maxBitrate: 20000000, level: 0x28 }, // Level 4 + { maxMacroblocks: 8192, maxBitrate: 50000000, level: 0x29 }, // Level 4.1 + { maxMacroblocks: 8704, maxBitrate: 50000000, level: 0x2A }, // Level 4.2 + { maxMacroblocks: 22080, maxBitrate: 135000000, level: 0x32 }, // Level 5 + { maxMacroblocks: 36864, maxBitrate: 240000000, level: 0x33 }, // Level 5.1 + { maxMacroblocks: 36864, maxBitrate: 240000000, level: 0x34 }, // Level 5.2 + { maxMacroblocks: 139264, maxBitrate: 240000000, level: 0x3C }, // Level 6 + { maxMacroblocks: 139264, maxBitrate: 480000000, level: 0x3D }, // Level 6.1 + { maxMacroblocks: 139264, maxBitrate: 800000000, level: 0x3E }, // Level 6.2 +]; - if (width <= 768 && height <= 432) { - profileIndication = 0x42; // Baseline for smaller videos - } else if (width <= 1920 && height <= 1080) { - profileIndication = 0x4D; // Main for HD - } +// https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding +const HEVC_LEVEL_TABLE = [ + { maxPictureSize: 36864, maxBitrate: 128000, tier: 'L', level: 30 }, // Level 1 (Low Tier) + { maxPictureSize: 122880, maxBitrate: 1500000, tier: 'L', level: 60 }, // Level 2 (Low Tier) + { maxPictureSize: 245760, maxBitrate: 3000000, tier: 'L', level: 63 }, // Level 2.1 (Low Tier) + { maxPictureSize: 552960, maxBitrate: 6000000, tier: 'L', level: 90 }, // Level 3 (Low Tier) + { maxPictureSize: 983040, maxBitrate: 10000000, tier: 'L', level: 93 }, // Level 3.1 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 12000000, tier: 'L', level: 120 }, // Level 4 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 30000000, tier: 'H', level: 120 }, // Level 4 (High Tier) + { maxPictureSize: 2228224, maxBitrate: 20000000, tier: 'L', level: 123 }, // Level 4.1 (Low Tier) + { maxPictureSize: 2228224, maxBitrate: 50000000, tier: 'H', level: 123 }, // Level 4.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 25000000, tier: 'L', level: 150 }, // Level 5 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 100000000, tier: 'H', level: 150 }, // Level 5 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 40000000, tier: 'L', level: 153 }, // Level 5.1 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 160000000, tier: 'H', level: 153 }, // Level 5.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 60000000, tier: 'L', level: 156 }, // Level 5.2 (Low Tier) + { maxPictureSize: 8912896, maxBitrate: 240000000, tier: 'H', level: 156 }, // Level 5.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 60000000, tier: 'L', level: 180 }, // Level 6 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'H', level: 180 }, // Level 6 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 120000000, tier: 'L', level: 183 }, // Level 6.1 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 480000000, tier: 'H', level: 183 }, // Level 6.1 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'L', level: 186 }, // Level 6.2 (Low Tier) + { maxPictureSize: 35651584, maxBitrate: 800000000, tier: 'H', level: 186 }, // Level 6.2 (High Tier) +]; - const profileCompatibility = 0x00; +// https://en.wikipedia.org/wiki/VP9 +const VP9_LEVEL_TABLE = [ + { maxPictureSize: 36864, maxBitrate: 200000, level: 10 }, // Level 1 + { maxPictureSize: 73728, maxBitrate: 800000, level: 11 }, // Level 1.1 + { maxPictureSize: 122880, maxBitrate: 1800000, level: 20 }, // Level 2 + { maxPictureSize: 245760, maxBitrate: 3600000, level: 21 }, // Level 2.1 + { maxPictureSize: 552960, maxBitrate: 7200000, level: 30 }, // Level 3 + { maxPictureSize: 983040, maxBitrate: 12000000, level: 31 }, // Level 3.1 + { maxPictureSize: 2228224, maxBitrate: 18000000, level: 40 }, // Level 4 + { maxPictureSize: 2228224, maxBitrate: 30000000, level: 41 }, // Level 4.1 + { maxPictureSize: 8912896, maxBitrate: 60000000, level: 50 }, // Level 5 + { maxPictureSize: 8912896, maxBitrate: 120000000, level: 51 }, // Level 5.1 + { maxPictureSize: 8912896, maxBitrate: 180000000, level: 52 }, // Level 5.2 + { maxPictureSize: 35651584, maxBitrate: 180000000, level: 60 }, // Level 6 + { maxPictureSize: 35651584, maxBitrate: 240000000, level: 61 }, // Level 6.1 + { maxPictureSize: 35651584, maxBitrate: 480000000, level: 62 }, // Level 6.2 +]; - // TODO this is not correct. Fails for 3000x3000 for example. This logic needs to be more complex - // Default to Level 4.1 (0x29) for most content, only bump to Level 5.0 (0x32) for 4K content - const levelIndication = (width > 1920 || height > 1080) ? 0x32 : 0x29; +// https://en.wikipedia.org/wiki/AV1 +const AV1_LEVEL_TABLE = [ + { maxPictureSize: 147456, maxBitrate: 1500000, tier: 'M', level: 0 }, // Level 2.0 (Main Tier) + { maxPictureSize: 278784, maxBitrate: 3000000, tier: 'M', level: 1 }, // Level 2.1 (Main Tier) + { maxPictureSize: 665856, maxBitrate: 6000000, tier: 'M', level: 4 }, // Level 3.0 (Main Tier) + { maxPictureSize: 1065024, maxBitrate: 10000000, tier: 'M', level: 5 }, // Level 3.1 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 12000000, tier: 'M', level: 8 }, // Level 4.0 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 30000000, tier: 'H', level: 8 }, // Level 4.0 (High Tier) + { maxPictureSize: 2359296, maxBitrate: 20000000, tier: 'M', level: 9 }, // Level 4.1 (Main Tier) + { maxPictureSize: 2359296, maxBitrate: 50000000, tier: 'H', level: 9 }, // Level 4.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 30000000, tier: 'M', level: 12 }, // Level 5.0 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 100000000, tier: 'H', level: 12 }, // Level 5.0 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 40000000, tier: 'M', level: 13 }, // Level 5.1 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 160000000, tier: 'H', level: 13 }, // Level 5.1 (High Tier) + { maxPictureSize: 8912896, maxBitrate: 60000000, tier: 'M', level: 14 }, // Level 5.2 (Main Tier) + { maxPictureSize: 8912896, maxBitrate: 240000000, tier: 'H', level: 14 }, // Level 5.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 60000000, tier: 'M', level: 15 }, // Level 5.3 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'H', level: 15 }, // Level 5.3 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 60000000, tier: 'M', level: 16 }, // Level 6.0 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 240000000, tier: 'H', level: 16 }, // Level 6.0 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 100000000, tier: 'M', level: 17 }, // Level 6.1 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 480000000, tier: 'H', level: 17 }, // Level 6.1 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 160000000, tier: 'M', level: 18 }, // Level 6.2 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 800000000, tier: 'H', level: 18 }, // Level 6.2 (High Tier) + { maxPictureSize: 35651584, maxBitrate: 160000000, tier: 'M', level: 19 }, // Level 6.3 (Main Tier) + { maxPictureSize: 35651584, maxBitrate: 800000000, tier: 'H', level: 19 }, // Level 6.3 (High Tier) +]; - const hexProfileIndication = profileIndication.toString(16).padStart(2, '0'); - const hexProfileCompatibility = profileCompatibility.toString(16).padStart(2, '0'); - const hexLevelIndication = levelIndication.toString(16).padStart(2, '0'); +export const buildVideoCodecString = (codec: VideoCodec, width: number, height: number, bitrate: number) => { + if (codec === 'avc') { + const profileIndication = 0x64; // High Profile + const totalMacroblocks = Math.ceil(width / 16) * Math.ceil(height / 16); - return `avc1.${hexProfileIndication}${hexProfileCompatibility}${hexLevelIndication}`; - } else if (codec === 'hevc') { - // Start with general_profile_space and general_profile_idc - let profileSpace = 0; // Assuming general_profile_space == 0 (most common) - let profileIdc = 1; // Assuming Main Profile (1) + // Determine the level based on the table + const levelInfo = AVC_LEVEL_TABLE.find( + (level) => totalMacroblocks <= level.maxMacroblocks && bitrate <= level.maxBitrate + ) ?? last(AVC_LEVEL_TABLE)!; + const levelIndication = levelInfo ? levelInfo.level : 0; + + const hexProfileIndication = profileIndication.toString(16).padStart(2, '0'); + const hexProfileCompatibility = '00'; + const hexLevelIndication = levelIndication.toString(16).padStart(2, '0'); + + return `avc1.${hexProfileIndication}${hexProfileCompatibility}${hexLevelIndication}`; + } else if (codec === 'hevc') { + let profileSpace = 0; + let profileIdc = 1; // Main Profile - // Generate compatibility flags (32 bits in reverse order) - // For basic compatibility, we'll set the main profile bit - const compatibilityFlags = Array(32).fill(0); - compatibilityFlags[profileIdc] = 1; // Set bit for current profile - const compatibilityHex = parseInt(compatibilityFlags.reverse().join(''), 2) - .toString(16) - .replace(/^0+/, ''); // Remove leading zeroes - - // Determine tier and level based on resolution - let tier = 'L'; // L for Main Tier, H for High Tier - let level = 120; // Default level 4.0 (120) + const compatibilityFlags = '6'; // Taken from the example in ISO 14496-15 + + const pictureSize = width * height; + const levelInfo = HEVC_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(HEVC_LEVEL_TABLE)!; - // Adjust level based on resolution (simplified) - if (width <= 1280 && height <= 720) { - level = 93; // Level 3.1 - } else if (width <= 1920 && height <= 1080) { - level = 120; // Level 4.0 - } else if (width <= 3840 && height <= 2160) { - level = 150; // Level 5.0 - } else { - tier = 'H'; // Use High Tier for very high resolutions - level = 180; // Level 6.0 - } + const constraintFlags = 'B0'; // Progressive source flag - // Generate constraint flags (6 bytes) - // Using B0 as a simple default (progressive source flag) - const constraintFlags = 'B0'; - - // Construct the final string following the format - // If profile_space is 0, start with the profile_idc directly const profilePrefix = profileSpace === 0 ? '' : String.fromCharCode(65 + profileSpace - 1); - return `hev1.${profilePrefix}${profileIdc}.${compatibilityHex}.${tier}${level}.${constraintFlags}`; + return `hev1.${profilePrefix}${profileIdc}.${compatibilityFlags}.${levelInfo.tier}${levelInfo.level}.${constraintFlags}`; } else if (codec === 'vp8') { return 'vp8'; // Easy, this one } else if (codec === 'vp9') { - // Default to Profile 0 (most common) - const profile = "00"; + const profile = "00"; // Profile 0 - // Determine level based on resolution - // VP9 levels are specified as two digits: major.minor - let level; - if (width <= 854 && height <= 480) { - level = "21"; // Level 2.1 - } else if (width <= 1280 && height <= 720) { - level = "31"; // Level 3.1 - } else if (width <= 1920 && height <= 1080) { - level = "41"; // Level 4.1 - } else if (width <= 3840 && height <= 2160) { - level = "51"; // Level 5.1 - } else { - level = "61"; // Level 6.1 - } + const pictureSize = width * height; + const levelInfo = VP9_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(VP9_LEVEL_TABLE)!; - // Default to 8-bit depth - const bitDepth = "08"; + const bitDepth = "08"; // 8-bit - return `vp09.${profile}.${level}.${bitDepth}`; + return `vp09.${profile}.${levelInfo.level}.${bitDepth}`; } else if (codec === 'av1') { - // Default to Main Profile (0) - const profile = 0; + const profile = 0; // Main Profile - // Determine level based on resolution - // Using a simplified level selection based on common resolutions - let level; - if (width <= 854 && height <= 480) { - level = "01"; // Level 2.1 - } else if (width <= 1280 && height <= 720) { - level = "03"; // Level 2.3 - } else if (width <= 1920 && height <= 1080) { - level = "04"; // Level 3.0 - } else if (width <= 3840 && height <= 2160) { - level = "07"; // Level 4.0 - } else { - level = "09"; // Level 4.2 - } + const pictureSize = width * height; + const levelInfo = AV1_LEVEL_TABLE.find( + (level) => pictureSize <= level.maxPictureSize && bitrate <= level.maxBitrate + ) ?? last(AV1_LEVEL_TABLE)!; - // Default to Main tier - const tier = "M"; - - // Default to 8-bit depth - const bitDepth = "08"; + const bitDepth = "08"; // 8-bit - return `av01.${profile}.${level}${tier}.${bitDepth}`; + return `av01.${profile}.${levelInfo.level.toString().padStart(2, '0')}${levelInfo.tier}.${bitDepth}`; } throw new TypeError(`Unhandled codec '${codec}'.`); diff --git a/src/source.ts b/src/source.ts index eecc5d3..77334f5 100644 --- a/src/source.ts +++ b/src/source.ts @@ -188,7 +188,7 @@ class VideoEncoderWrapper { }); this.encoder.configure({ - codec: buildVideoCodecString(this.codecConfig.codec, videoFrame.codedWidth, videoFrame.codedHeight), + codec: buildVideoCodecString(this.codecConfig.codec, videoFrame.codedWidth, videoFrame.codedHeight, this.codecConfig.bitrate), width: videoFrame.codedWidth, height: videoFrame.codedHeight, bitrate: this.codecConfig.bitrate,