@catlabtech/webcvt-transcode 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/abort.ts","../src/pcm.ts","../src/decode.ts","../src/video-demux.ts","../src/demux.ts","../src/encode.ts","../src/matrix.ts","../src/probe-cache.ts","../src/video.ts","../src/backend.ts"],"names":["WebcvtError","WebCodecsAudioDecoder","parseMp4","parseWebm","parseMkv","findVideoTrack","iterateVideoSamples","findAudioTrack","deriveCodecString","iterateAudioSamplesAuto","iterateWebmVideoChunks","iterateWebmAudioChunks","iterateMkvVideoChunks","iterateMkvAudioChunks","US_PER_SEC","parseWav","parseMp3","parseAdts","buildAudioSpecificConfig","parseFlac","encodeBlockHeader","BLOCK_TYPE_STREAMINFO","STREAMINFO_SIZE","encodeStreamInfo","OPUS_RATE","parseOgg","serializeWav","WebCodecsAudioEncoder","buildOpusHead","buildOpusTags","serializeOgg","serializeWebm","probeAudioDecoder","probeAudioCodec","probeVideoDecoder","probeVideoCodec","WebCodecsNotSupportedError","WEBM_TIMECODE_SCALE","WebCodecsVideoEncoder","WebCodecsVideoDecoder","serializeMkv","DEFAULT_QUALITY","defaultRegistry"],"mappings":";;;;;;;;;;;;;;AAgBO,IAAM,yBAAA,GAAN,cAAwCA,sBAAA,CAAY;AAAA,EACzD,WAAA,CAAY,MAAc,EAAA,EAAY;AACpC,IAAA,KAAA;AAAA,MACE,uBAAA;AAAA,MACA,CAAA,iCAAA,EAAoC,IAAI,CAAA,QAAA,EAAM,EAAE,CAAA,8GAAA;AAAA,KAClD;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,2BAAA;AAAA,EACd;AACF;AAOO,IAAM,2BAAA,GAAN,cAA0CA,sBAAA,CAAY;AAAA,EAC3D,WAAA,CAAY,MAAc,GAAA,EAAa;AACrC,IAAA,KAAA;AAAA,MACE,2BAAA;AAAA,MACA,CAAA,mBAAA,EAAsB,IAAI,CAAA,6BAAA,EAAgC,GAAG,CAAA,OAAA;AAAA,KAC/D;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,6BAAA;AAAA,EACd;AACF;AAGO,IAAM,mBAAA,GAAN,cAAkCA,sBAAA,CAAY;AAAA,EACnD,WAAA,CAAY,SAAiB,OAAA,EAAwB;AACnD,IAAA,KAAA,CAAM,wBAAA,EAA0B,CAAA,wBAAA,EAA2B,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA;AAC7E,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAGO,IAAM,mBAAA,GAAN,cAAkCA,sBAAA,CAAY;AAAA,EACnD,WAAA,CAAY,SAAiB,OAAA,EAAwB;AACnD,IAAA,KAAA,CAAM,uBAAA,EAAyB,CAAA,uBAAA,EAA0B,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA;AAC3E,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAGO,IAAM,iBAAA,GAAN,cAAgCA,sBAAA,CAAY;AAAA,EACjD,WAAA,CAAY,SAAiB,OAAA,EAAwB;AACnD,IAAA,KAAA,CAAM,sBAAA,EAAwB,CAAA,sBAAA,EAAyB,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA;AACzE,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;;;ACxDO,SAAS,eAAe,MAAA,EAA4B;AACzD,EAAA,IAAI,MAAA,EAAQ,OAAA,EAAS,MAAM,gBAAA,EAAiB;AAC9C;AAGO,SAAS,gBAAA,GAAiC;AAC/C,EAAA,OAAO,IAAI,YAAA,CAAa,4BAAA,EAA8B,YAAY,CAAA;AACpE;AAGO,SAAS,aAAa,GAAA,EAAuB;AAClD,EAAA,OAAO,GAAA,YAAe,YAAA,IAAgB,GAAA,CAAI,IAAA,KAAS,YAAA;AACrD;AAOO,SAAS,YAAA,CAAa,KAAc,KAAA,EAAsB;AAC/D,EAAA,IAAI,YAAA,CAAa,GAAG,CAAA,EAAG,OAAO,GAAA;AAC9B,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,EAAA,OAAO,IAAI,mBAAA,CAAoB,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI,EAAE,KAAA,EAAO,GAAA,EAAK,CAAA;AACvE;;;ACHO,SAAS,oBAAoB,IAAA,EAAiC;AACnE,EAAA,MAAM,SAAS,IAAA,CAAK,cAAA;AACpB,EAAA,MAAM,SAAyB,EAAC;AAChC,EAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,IAAA,CAAK,kBAAkB,EAAA,EAAA,EAAM;AACjD,IAAA,MAAM,KAAA,GAAQ,IAAI,YAAA,CAAa,MAAM,CAAA;AACrC,IAAA,IAAA,CAAK,OAAO,KAAA,EAAO,EAAE,YAAY,EAAA,EAAI,MAAA,EAAQ,cAAc,CAAA;AAC3D,IAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,EACnB;AACA,EAAA,OAAO,MAAA;AACT;AAOO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,cAAgC,EAAC;AAAA,EACjC,OAAA,GAAU,CAAA;AAAA,EACV,YAAA,GAAe,CAAA;AAAA,EACf,WAAA,GAAc,CAAA;AAAA,EAEd,GAAA,CAAI,QAAwB,UAAA,EAA0B;AACpD,IAAA,IAAI,IAAA,CAAK,iBAAiB,CAAA,EAAG;AAC3B,MAAA,IAAA,CAAK,eAAe,MAAA,CAAO,MAAA;AAC3B,MAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,MAAA,IAAA,CAAK,WAAA,GAAc,MAAA,CAAO,GAAA,CAAI,MAAM,EAAE,CAAA;AAAA,IACxC;AACA,IAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,IAAA,CAAK,cAAc,EAAA,EAAA,EAAM;AAC7C,MAAA,IAAA,CAAK,WAAA,CAAY,EAAE,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,EAAE,CAAA,IAAK,MAAA,CAAO,CAAC,CAAA,IAAK,IAAI,YAAA,CAAa,CAAC,CAAC,CAAA;AAAA,IAC3E;AACA,IAAA,IAAA,CAAK,OAAA,IAAW,MAAA,CAAO,CAAC,CAAA,EAAG,MAAA,IAAU,CAAA;AAAA,EACvC;AAAA,EAEA,MAAA,CAAO,oBAA4B,gBAAA,EAAwC;AACzE,IAAA,IAAI,IAAA,CAAK,iBAAiB,CAAA,EAAG;AAC3B,MAAA,OAAO;AAAA,QACL,UAAA,EAAY,kBAAA;AAAA,QACZ,gBAAA,EAAkB,gBAAA;AAAA,QAClB,cAAA,EAAgB,CAAA;AAAA,QAChB,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,gBAAA,EAAiB,EAAG,MAAM,IAAI,YAAA,CAAa,CAAC,CAAC;AAAA,OAC9E;AAAA,IACF;AACA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,CAAC,WAAW,WAAA,CAAY,MAAA,EAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AACnF,IAAA,OAAO;AAAA,MACL,YAAY,IAAA,CAAK,WAAA;AAAA,MACjB,kBAAkB,IAAA,CAAK,YAAA;AAAA,MACvB,gBAAgB,IAAA,CAAK,OAAA;AAAA,MACrB;AAAA,KACF;AAAA,EACF;AACF,CAAA;AAMA,IAAM,sBAAA,GAAyB,CAAA;AAGxB,SAAS,aAAa,IAAA,EAA6B;AACxD,EAAA,MAAM,EAAE,MAAA,EAAQ,SAAA,EAAU,GAAI,IAAA;AAC9B,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,QAAQ,CAAA;AACtC,EAAA,MAAM,OAAO,MAAA,CAAO,aAAA;AACpB,EAAA,MAAM,iBAAiB,IAAA,GAAO,CAAA;AAC9B,EAAA,MAAM,YAAY,cAAA,GAAiB,EAAA;AACnC,EAAA,MAAM,MAAA,GAAS,YAAY,CAAA,GAAI,IAAA,CAAK,MAAM,SAAA,CAAU,MAAA,GAAS,SAAS,CAAA,GAAI,CAAA;AAC1E,EAAA,MAAM,OAAA,GAAU,OAAO,WAAA,KAAgB,sBAAA;AACvC,EAAA,MAAM,IAAA,GAAO,IAAI,QAAA,CAAS,SAAA,CAAU,QAAQ,SAAA,CAAU,UAAA,EAAY,UAAU,UAAU,CAAA;AACtF,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,EAAA,EAAG,EAAG,MAAM,IAAI,YAAA,CAAa,MAAM,CAAC,CAAA;AAE1E,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,EAAQ,CAAA,EAAA,EAAK;AAC/B,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,CAAA,EAAA,EAAK;AAC3B,MAAA,MAAM,GAAA,GAAM,CAAA,GAAI,SAAA,GAAY,CAAA,GAAI,cAAA;AAChC,MAAA,MAAM,MAAA,GAAS,SAAS,CAAC,CAAA;AACzB,MAAA,IAAI,MAAA,SAAe,CAAC,CAAA,GAAI,WAAW,IAAA,EAAM,GAAA,EAAK,MAAM,OAAO,CAAA;AAAA,IAC7D;AAAA,EACF;AACA,EAAA,OAAO,EAAE,YAAY,MAAA,CAAO,UAAA,EAAY,kBAAkB,EAAA,EAAI,cAAA,EAAgB,QAAQ,QAAA,EAAS;AACjG;AAOO,SAAS,gBAAgB,OAAA,EAAmC;AACjE,EAAA,MAAM,EAAE,gBAAA,EAAkB,EAAA,EAAI,cAAA,EAAgB,CAAA,EAAG,UAAS,GAAI,OAAA;AAC9D,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,CAAA,GAAI,KAAK,CAAC,CAAA;AACrC,EAAA,MAAM,IAAA,GAAO,IAAI,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA;AACpC,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,CAAA,EAAA,EAAK;AAC3B,MAAA,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,YAAA,CAAa,QAAA,CAAS,CAAC,IAAI,CAAC,CAAA,IAAK,CAAC,CAAA,EAAG,IAAI,CAAA;AAC5D,MAAA,GAAA,IAAO,CAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;AAWO,SAAS,cAAA,CACd,OAAA,EACA,UAAA,EACA,UAAA,EACA,WAAA,EACW;AACX,EAAA,MAAM,KAAK,OAAA,CAAQ,gBAAA;AACnB,EAAA,MAAM,IAAA,GAAO,IAAI,YAAA,CAAa,EAAA,GAAK,UAAU,CAAA;AAC7C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,CAAA,EAAA,EAAK;AAC3B,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,QAAA,CAAS,CAAC,CAAA;AAChC,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,QAAA,CAAS,YAAY,UAAA,GAAa,UAAU,CAAA,EAAG,CAAA,GAAI,UAAU,CAAA;AAAA,EACzF;AACA,EAAA,OAAO,IAAI,SAAA,CAAU;AAAA,IACnB,MAAA,EAAQ,YAAA;AAAA,IACR,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,cAAA,EAAgB,UAAA;AAAA,IAChB,gBAAA,EAAkB,EAAA;AAAA,IAClB,SAAA,EAAW,WAAA;AAAA,IACX;AAAA,GACD,CAAA;AACH;AAMA,SAAS,WAAA,CAAY,QAAwB,KAAA,EAA6B;AACxE,EAAA,MAAM,GAAA,GAAM,IAAI,YAAA,CAAa,KAAK,CAAA;AAClC,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,GAAA,CAAI,GAAA,CAAI,GAAG,GAAG,CAAA;AACd,IAAA,GAAA,IAAO,CAAA,CAAE,MAAA;AAAA,EACX;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,aAAa,CAAA,EAAmB;AACvC,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,KAAK,CAAA;AAC9B,EAAA,OAAO,CAAA,GAAI,MAAA,GAAS,MAAA,GAAS,CAAA,GAAI,QAAQ,KAAA,GAAQ,CAAA;AACnD;AAEA,SAAS,UAAA,CAAW,IAAA,EAAgB,GAAA,EAAa,IAAA,EAAc,OAAA,EAA0B;AACvF,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAO,IAAA,KAAS,EAAA,GAAK,IAAA,CAAK,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA,GAAI,IAAA,CAAK,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA;AAAA,EAC7E;AACA,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,CAAA;AACH,MAAA,OAAA,CAAS,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,GAAI,GAAA,IAAO,GAAA;AAAA,IACvC,KAAK,EAAA;AACH,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,IAAI,CAAA,GAAI,KAAA;AAAA,IACpC,KAAK,EAAA,EAAI;AACP,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA;AAC5B,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,QAAA,CAAS,GAAA,GAAM,CAAC,CAAA;AAChC,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,QAAA,CAAS,GAAA,GAAM,CAAC,CAAA;AAChC,MAAA,IAAI,GAAA,GAAM,EAAA,GAAM,EAAA,IAAM,CAAA,GAAM,EAAA,IAAM,EAAA;AAClC,MAAA,IAAI,GAAA,GAAM,SAAU,GAAA,IAAO,QAAA;AAC3B,MAAA,OAAO,GAAA,GAAM,OAAA;AAAA,IACf;AAAA,IACA,KAAK,EAAA;AACH,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,IAAI,CAAA,GAAI,UAAA;AAAA,IACpC;AACE,MAAA,OAAO,CAAA;AAAA;AAEb;;;ACjLA,eAAsB,WAAA,CAAY,OAAoB,GAAA,EAA2C;AAC/F,EAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AAEzB,EAAA,IAAI,KAAA,CAAM,SAAS,KAAA,EAAO;AACxB,IAAA,GAAA,CAAI,aAAa,CAAC,CAAA;AAClB,IAAA,OAAO,KAAA,CAAM,OAAA;AAAA,EACf;AAEA,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,UAAA,EAAY,kBAAiB,GAAI,KAAA;AACzD,EAAA,MAAM,GAAA,GAAM,IAAI,iBAAA,EAAkB;AAElC,EAAA,MAAM,UAAU,IAAIC,0CAAA,CAAsB,EAAE,MAAA,EAAO,EAAG,CAAC,IAAA,KAAS;AAC9D,IAAA,GAAA,CAAI,GAAA,CAAI,mBAAA,CAAoB,IAAI,CAAA,EAAG,KAAK,UAAU,CAAA;AAClD,IAAA,IAAA,CAAK,KAAA,EAAM;AAAA,EACb,CAAC,CAAA;AAED,EAAA,MAAM,OAAA,GAAU,MAAY,OAAA,CAAQ,KAAA,EAAM;AAC1C,EAAA,GAAA,CAAI,QAAQ,gBAAA,CAAiB,OAAA,EAAS,SAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAE7D,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,OAAO,MAAA,IAAU,CAAA;AAC/B,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,MAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,IAAA,GAAO,OAAO,CAAC,CAAA;AACrB,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,OAAA,CAAQ,MAAA;AAAA,QACN,IAAI,iBAAA,CAAkB;AAAA,UACpB,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,WAAW,IAAA,CAAK,WAAA;AAAA,UAChB,UAAU,IAAA,CAAK,UAAA;AAAA,UACf,MAAM,IAAA,CAAK;AAAA,SACZ;AAAA,OACH;AACA,MAAA,GAAA,CAAI,UAAA,GAAA,CAAc,CAAA,GAAI,CAAA,IAAK,KAAK,CAAA;AAAA,IAClC;AACA,IAAA,MAAM,QAAQ,KAAA,EAAM;AACpB,IAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AAAA,EAC3B,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,YAAA,CAAa,KAAK,QAAQ,CAAA;AAAA,EAClC,CAAA,SAAE;AACA,IAAA,GAAA,CAAI,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AAChD,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB;AAEA,EAAA,OAAO,GAAA,CAAI,MAAA,CAAO,UAAA,EAAY,gBAAgB,CAAA;AAChD;ACfA,IAAM,UAAA,GAAa,GAAA;AAEnB,IAAM,SAAA,GAAY,IAAA;AAElB,IAAM,sBAAA,GAAyB,GAAA;AA6CxB,SAAS,mBAAA,CACd,QACA,KAAA,EACqB;AACrB,EAAA,OAAO,KAAK,MAAM;AAChB,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,KAAA,EAAO;AACV,QAAA,MAAM,IAAA,GAAOC,4BAAS,KAAK,CAAA;AAC3B,QAAA,OAAO,EAAE,OAAO,QAAA,CAAS,IAAI,GAAG,KAAA,EAAO,QAAA,CAAS,IAAI,CAAA,EAAE;AAAA,MACxD;AAAA,MACA,KAAK,MAAA,EAAQ;AACX,QAAA,MAAM,IAAA,GAAOC,8BAAU,KAAK,CAAA;AAC5B,QAAA,OAAO,EAAE,OAAO,SAAA,CAAU,IAAI,GAAG,KAAA,EAAO,SAAA,CAAU,IAAI,CAAA,EAAE;AAAA,MAC1D;AAAA,MACA,KAAK,KAAA,EAAO;AACV,QAAA,MAAM,IAAA,GAAOC,4BAAS,KAAK,CAAA;AAC3B,QAAA,OAAO,EAAE,OAAO,QAAA,CAAS,IAAI,GAAG,KAAA,EAAO,QAAA,CAAS,IAAI,CAAA,EAAE;AAAA,MACxD;AAAA;AACF,EACF,CAAC,CAAA;AACH;AAGO,SAAS,wBAAA,CACd,QACA,KAAA,EACmB;AACnB,EAAA,OAAO,KAAK,MAAM;AAChB,IAAA,IAAI,KAAA;AACJ,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,KAAA;AACH,QAAA,KAAA,GAAQ,QAAA,CAASF,2BAAA,CAAS,KAAK,CAAC,CAAA;AAChC,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,KAAA,GAAQ,SAAA,CAAUC,6BAAA,CAAU,KAAK,CAAC,CAAA;AAClC,QAAA;AAAA,MACF,KAAK,KAAA;AACH,QAAA,KAAA,GAAQ,QAAA,CAASC,2BAAA,CAAS,KAAK,CAAC,CAAA;AAChC,QAAA;AAAA;AAEJ,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,GAAG,MAAM,CAAA,+EAAA;AAAA,OACX;AAAA,IACF;AACA,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH;AAMA,SAAS,SAAS,IAAA,EAAkC;AAClD,EAAA,MAAM,KAAA,GAAQC,kCAAe,IAAI,CAAA;AACjC,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,WAAA,CAAY,SAAS,OAAA,EAAS;AAChD,IAAA,MAAM,IAAI,oBAAoB,wBAAwB,CAAA;AAAA,EACxD;AACA,EAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY,KAAA;AAChC,EAAA,MAAM,MAAA,GAA6B;AAAA,IACjC,OAAO,KAAA,CAAM,WAAA;AAAA,IACb,WAAA,EAAa,MAAM,WAAA,CAAY,KAAA;AAAA,IAC/B,YAAY,KAAA,CAAM,KAAA;AAAA,IAClB,aAAa,KAAA,CAAM;AAAA,GACrB;AAEA,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAA,IAAKC,sCAAA,CAAoB,KAAA,EAAO,IAAA,CAAK,SAAS,CAAA,EAAG;AAC1D,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,CAAA,CAAE,UAAA,GAAa,KAAA,GAAQ,OAAA;AAAA,MAC7B,WAAA,EAAa,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,kBAAkB,CAAA;AAAA,MAC5C,UAAA,EAAY,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,UAAU,CAAA;AAAA,MACnC,MAAM,CAAA,CAAE;AAAA,KACT,CAAA;AAAA,EACH;AACA,EAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,oBAAoB,gCAAgC,CAAA;AAEvF,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,SAAA,EAAW,kBAAkB,MAAM,CAAA;AAAA,IACnC,KAAA,EAAO,aAAA,CAAc,KAAA,CAAM,MAAM;AAAA,GACnC;AACF;AAEA,SAAS,SAAS,IAAA,EAAyC;AACzD,EAAA,MAAM,KAAA,GAAyBC,kCAAe,IAAI,CAAA;AAClD,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,WAAA,CAAY,IAAA,KAAS,SAAS,OAAO,IAAA;AACzD,EAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY,KAAA;AAChC,EAAA,MAAM,KAAA,GAAQC,oCAAA,CAAkB,KAAA,CAAM,oBAAA,EAAsB,MAAM,mBAAmB,CAAA;AACrF,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAM,YAAY,CAAA;AACvD,EAAA,MAAM,aAAa,KAAA,CAAM,UAAA;AAEzB,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,CAAA,IAAKC,0CAAA,CAAwB,IAAA,EAAM,KAAK,CAAA,EAAG;AACpD,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,KAAA;AAAA,MACN,WAAA,EAAa,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,WAAW,CAAA;AAAA,MACrC,UAAA,EAAY,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,UAAU,CAAA;AAAA,MACnC,MAAM,CAAA,CAAE;AAAA,KACT,CAAA;AAAA,EACH;AACA,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAEhC,EAAA,OAAO;AAAA,IACL,QAAQ,EAAE,KAAA,EAAO,aAAa,KAAA,CAAM,mBAAA,EAAqB,YAAY,gBAAA,EAAiB;AAAA,IACtF,MAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,cAAc,MAAA,EAAgC;AACrD,EAAA,IAAI,MAAA,CAAO,UAAA,CAAW,KAAK,CAAA,EAAG,OAAO,MAAA;AACrC,EAAA,IAAI,MAAA,CAAO,WAAW,KAAK,CAAA,IAAK,OAAO,UAAA,CAAW,KAAK,GAAG,OAAO,MAAA;AACjE,EAAA,IAAI,MAAA,KAAW,QAAQ,OAAO,KAAA;AAC9B,EAAA,IAAI,MAAA,KAAW,QAAQ,OAAO,KAAA;AAC9B,EAAA,OAAO,MAAA;AACT;AAMA,SAAS,UAAU,IAAA,EAAmC;AACpD,EAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAA2B,CAAA,CAAE,cAAc,CAAC,CAAA;AAC5E,EAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,oBAAoB,yBAAyB,CAAA;AACnE,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAO,GAAI,gBAAgB,KAAK,CAAA;AAE/C,EAAA,MAAM,SAAS,kBAAA,CAAmBC,sCAAA,CAAuB,IAAA,EAAM,KAAA,CAAM,WAAW,CAAC,CAAA;AACjF,EAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,oBAAoB,gCAAgC,CAAA;AAEvF,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAO,KAAA,CAAM,UAAA;AAAA,IACb,QAAQ,KAAA,CAAM,WAAA;AAAA,IACd,SAAA,EAAW,kBAAkB,MAAM,CAAA;AAAA,IACnC;AAAA,GACF;AACF;AAEA,SAAS,gBAAgB,KAAA,EAGvB;AACA,EAAA,MAAM,OAAO,EAAE,UAAA,EAAY,MAAM,UAAA,EAAY,WAAA,EAAa,MAAM,WAAA,EAAY;AAC5E,EAAA,QAAQ,MAAM,OAAA;AAAS,IACrB,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,OAAO,KAAA,EAAO,MAAA,EAAQ,EAAE,KAAA,EAAO,KAAA,EAAO,GAAG,IAAA,EAAK,EAAE;AAAA,IAC3D,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,OAAO,KAAA,EAAO,MAAA,EAAQ,EAAE,KAAA,EAAO,eAAA,EAAiB,GAAG,IAAA,EAAK,EAAE;AAAA,IACrE,KAAK,QAAA;AACH,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,KAAA;AAAA,QACP,MAAA,EAAQ;AAAA,UACN,KAAA,EAAO,eAAA;AAAA,UACP,GAAI,MAAM,YAAA,GAAe,EAAE,aAAa,KAAA,CAAM,YAAA,KAAiB,EAAC;AAAA,UAChE,GAAG;AAAA;AACL,OACF;AAAA;AAEN;AAEA,SAAS,UAAU,IAAA,EAA0C;AAC3D,EAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAA2B,CAAA,CAAE,cAAc,CAAC,CAAA;AAC5E,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,IAAI,KAAA,CAAM,OAAA,KAAY,QAAA,EAAU,OAAO,IAAA;AACvC,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAM,QAAQ,CAAA;AACnD,EAAA,MAAM,MAAA,GAAS,oBAAA;AAAA,IACb,kBAAA,CAAmBC,sCAAA,CAAuB,IAAA,EAAM,KAAA,CAAM,WAAW,CAAC;AAAA,GACpE;AACA,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAEhC,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,MAAA;AAAA,MACP,aAAa,KAAA,CAAM,YAAA;AAAA,MACnB,UAAA,EAAY,SAAA;AAAA,MACZ;AAAA,KACF;AAAA,IACA,MAAA;AAAA,IACA,UAAA,EAAY,SAAA;AAAA,IACZ;AAAA,GACF;AACF;AAMA,SAAS,SAAS,IAAA,EAAkC;AAClD,EAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAA0B,CAAA,CAAE,cAAc,CAAC,CAAA;AAC3E,EAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,oBAAoB,wBAAwB,CAAA;AAClE,EAAA,MAAM,MAAA,GAA6B;AAAA,IACjC,OAAO,KAAA,CAAM,oBAAA;AAAA,IACb,GAAI,mBAAA,CAAoB,KAAA,CAAM,OAAO,CAAA,IAAK,KAAA,CAAM,YAAA,GAC5C,EAAE,WAAA,EAAa,KAAA,CAAM,YAAA,EAAa,GAClC,EAAC;AAAA,IACL,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,aAAa,KAAA,CAAM;AAAA,GACrB;AAEA,EAAA,MAAM,SAAS,kBAAA,CAAmBC,qCAAA,CAAsB,IAAA,EAAM,KAAA,CAAM,WAAW,CAAC,CAAA;AAChF,EAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,oBAAoB,+BAA+B,CAAA;AAEtF,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAO,KAAA,CAAM,UAAA;AAAA,IACb,QAAQ,KAAA,CAAM,WAAA;AAAA,IACd,SAAA,EAAW,kBAAkB,MAAM,CAAA;AAAA,IACnC,KAAA,EAAO,aAAA,CAAc,KAAA,CAAM,OAAO;AAAA,GACpC;AACF;AAEA,SAAS,SAAS,IAAA,EAAyC;AACzD,EAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAA0B,CAAA,CAAE,cAAc,CAAC,CAAA;AAC3E,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAEnB,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,UAAA;AACJ,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAM,QAAQ,CAAA;AACnD,EAAA,IAAI,KAAA,CAAM,YAAY,QAAA,EAAU;AAC9B,IAAA,UAAA,GAAa,SAAA;AACb,IAAA,MAAA,GAAS,EAAE,KAAA,EAAO,MAAA,EAAQ,aAAa,KAAA,CAAM,YAAA,EAAc,YAAY,gBAAA,EAAiB;AAAA,EAC1F,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,KAAY,OAAA,EAAS;AACpC,IAAA,UAAA,GAAa,KAAA,CAAM,iBAAA;AACnB,IAAA,MAAA,GAAS;AAAA,MACP,OAAO,KAAA,CAAM,oBAAA;AAAA,MACb,aAAa,KAAA,CAAM,YAAA;AAAA,MACnB,UAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAA,GAAS,oBAAA;AAAA,IACb,kBAAA,CAAmBC,qCAAA,CAAsB,IAAA,EAAM,KAAA,CAAM,WAAW,CAAC;AAAA,GACnE;AACA,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAEhC,EAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,UAAA,EAAY,gBAAA,EAAiB;AACxD;AAEA,SAAS,oBAAoB,OAAA,EAA4C;AACvE,EAAA,OAAO,OAAA,KAAY,iBAAA,IAAqB,OAAA,KAAY,kBAAA,IAAsB,OAAA,KAAY,QAAA;AACxF;AAEA,SAAS,cAAc,OAAA,EAAmD;AACxE,EAAA,QAAQ,OAAA;AAAS,IACf,KAAK,iBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,OAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,OAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,QAAA;AACH,MAAA,OAAO,KAAA;AAAA;AAEb;AAMA,SAAS,mBACP,GAAA,EACyB;AACzB,EAAA,MAAM,GAAA,GAAM,CAAC,GAAG,GAAG,CAAA;AACnB,EAAA,MAAM,QAAiC,EAAC;AACxC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,MAAM,CAAA,GAAI,IAAI,CAAC,CAAA;AACf,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AACtB,IAAA,MAAM,UAAA,GAAa,IAAA,GACf,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,WAAW,CAAA,GAC3C,KAAA,CAAM,EAAA,CAAG,EAAE,GAAG,UAAA,IAAc,sBAAA;AACjC,IAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,WAAA,EAAa,CAAA,CAAE,WAAA,EAAa,UAAA,EAAY,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,CAAA;AAAA,EACnF;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,mBAAmB,GAAA,EAAoE;AAC9F,EAAA,OAAO,CAAC,GAAG,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAC1B,IAAA,EAAM,KAAA;AAAA,IACN,aAAa,CAAA,CAAE,WAAA;AAAA,IACf,UAAA,EAAY,CAAA;AAAA;AAAA,IACZ,MAAM,CAAA,CAAE;AAAA,GACV,CAAE,CAAA;AACJ;AAGA,SAAS,qBAAqB,MAAA,EAAgD;AAC5E,EAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM;AAC1B,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA;AACzB,IAAA,MAAM,UAAA,GAAa,IAAA,GACf,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAK,WAAA,GAAc,CAAA,CAAE,WAAW,CAAA,GAC5C,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,GACV,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAA,CAAE,WAAA,IAAe,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,EAAG,WAAA,IAAe,CAAA,CAAE,CAAA,GAC7D,sBAAA;AACN,IAAA,OAAO,EAAE,GAAG,CAAA,EAAG,UAAA,EAAW;AAAA,EAC5B,CAAC,CAAA;AACH;AAEA,SAAS,kBAAkB,MAAA,EAAkD;AAC3E,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,CAAA;AAC9B,EAAA,MAAM,KAAA,GAAQ,OAAO,CAAC,CAAA;AACtB,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AACrC,EAAA,IAAI,CAAC,KAAA,IAAS,CAAC,IAAA,EAAM,OAAO,CAAA;AAC5B,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,GAAc,IAAA,CAAK,aAAa,KAAA,CAAM,WAAA;AAC1D,EAAA,IAAI,MAAA,IAAU,GAAG,OAAO,CAAA;AACxB,EAAA,OAAO,IAAA,CAAK,KAAA,CAAO,MAAA,CAAO,MAAA,GAAS,SAAU,UAAU,CAAA;AACzD;AAEA,SAAS,KAAQ,GAAA,EAAiB;AAChC,EAAA,IAAI;AACF,IAAA,OAAO,GAAA,EAAI;AAAA,EACb,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,GAAA,YAAe,qBAAqB,MAAM,GAAA;AAC9C,IAAA,MAAM,IAAI,mBAAA,CAAoB,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAA,EAAG,EAAE,KAAA,EAAO,GAAA,EAAK,CAAA;AAAA,EAChG;AACF;;;AC9XA,IAAMC,WAAAA,GAAa,GAAA;AAGZ,SAAS,UAAA,CAAW,YAAuB,KAAA,EAAgC;AAChF,EAAA,IAAI;AACF,IAAA,QAAQ,UAAA;AAAY,MAClB,KAAK,KAAA;AACH,QAAA,OAAO,EAAE,MAAM,KAAA,EAAO,OAAA,EAAS,aAAaC,2BAAA,CAAS,KAAK,CAAC,CAAA,EAAE;AAAA,MAC/D,KAAK,KAAA;AACH,QAAA,OAAO,SAAS,KAAK,CAAA;AAAA,MACvB,KAAK,KAAA;AACH,QAAA,OAAO,SAAS,KAAK,CAAA;AAAA,MACvB,KAAK,MAAA;AACH,QAAA,OAAO,UAAU,KAAK,CAAA;AAAA,MACxB,KAAK,MAAA;AACH,QAAA,OAAO,UAAU,KAAK,CAAA;AAAA,MACxB;AACE,QAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,4BAAA,EAA+B,UAAU,CAAA,CAAA,CAAG,CAAA;AAAA;AAC9E,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,GAAA,YAAe,qBAAqB,MAAM,GAAA;AAC9C,IAAA,MAAM,IAAI,mBAAA,CAAoB,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAA,EAAG,EAAE,KAAA,EAAO,GAAA,EAAK,CAAA;AAAA,EAChG;AACF;AASO,SAAS,mBAAA,CAAoB,QAAyB,KAAA,EAAgC;AAC3F,EAAA,MAAM,KAAA,GAAQ,wBAAA,CAAyB,MAAA,EAAQ,KAAK,CAAA;AACpD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,kBAAkB,KAAA,CAAM;AAAA,GAC1B;AACF;AAMA,SAAS,SAAS,KAAA,EAAgC;AAChD,EAAA,MAAM,EAAE,MAAA,EAAO,GAAIC,2BAAA,CAAS,KAAK,CAAA;AACjC,EAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,oBAAoB,yBAAyB,CAAA;AAChF,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,MAAA;AACzB,EAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,oBAAoB,yBAAyB,CAAA;AACnE,EAAA,MAAM,aAAa,KAAA,CAAM,UAAA;AACzB,EAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,WAAA,KAAgB,MAAA,GAAS,CAAA,GAAI,CAAA;AAE5D,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,eAAA;AACzB,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,KAAA;AAAA,MACN,WAAA,EAAa,IAAA,CAAK,KAAA,CAAO,MAAA,GAAS,aAAcF,WAAU,CAAA;AAAA,MAC1D,UAAA,EAAY,IAAA,CAAK,KAAA,CAAO,GAAA,GAAM,aAAcA,WAAU,CAAA;AAAA,MACtD,MAAM,KAAA,CAAM;AAAA,KACb,CAAA;AACD,IAAA,MAAA,IAAU,GAAA;AAAA,EACZ;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,EAAE,KAAA,EAAO,KAAA,EAAO,YAAY,gBAAA,EAAiB;AAAA,IACrD,MAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF;AAMA,IAAM,qBAAA,GAAwB,IAAA;AAE9B,SAAS,SAAS,KAAA,EAAgC;AAChD,EAAA,MAAM,EAAE,MAAA,EAAO,GAAIG,4BAAA,CAAU,KAAK,CAAA;AAClC,EAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,oBAAoB,wBAAwB,CAAA;AAC/E,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAC,CAAA,EAAG,MAAA;AAC1B,EAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,oBAAoB,wBAAwB,CAAA;AACnE,EAAA,MAAM,aAAa,MAAA,CAAO,UAAA;AAC1B,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,oBAAoB,CAAA;AAChE,EAAA,MAAM,WAAA,GAAcC,4CAAyB,MAAM,CAAA;AAEnD,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,CAAA;AAC7C,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,KAAA;AAAA,MACN,WAAA,EAAa,IAAA,CAAK,KAAA,CAAO,MAAA,GAAS,aAAcJ,WAAU,CAAA;AAAA,MAC1D,UAAA,EAAY,IAAA,CAAK,KAAA,CAAO,qBAAA,GAAwB,aAAcA,WAAU,CAAA;AAAA,MACxE,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,UAAU;AAAA;AAAA,KACrC,CAAA;AACD,IAAA,MAAA,IAAU,qBAAA;AAAA,EACZ;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,QAAQ,EAAE,KAAA,EAAO,WAAA,EAAa,UAAA,EAAY,kBAAkB,WAAA,EAAY;AAAA,IACxE,MAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF;AAMA,SAAS,UAAU,KAAA,EAAgC;AACjD,EAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAIK,8BAAU,KAAK,CAAA;AAC9C,EAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,oBAAoB,oBAAoB,CAAA;AAC3E,EAAA,MAAM,aAAa,UAAA,CAAW,UAAA;AAC9B,EAAA,MAAM,mBAAmB,UAAA,CAAW,QAAA;AACpC,EAAA,MAAM,WAAA,GAAc,qBAAqB,UAAU,CAAA;AAEnD,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,KAAA;AAAA,MACN,aAAa,IAAA,CAAK,KAAA,CAAO,KAAA,CAAM,YAAA,GAAe,aAAcL,WAAU,CAAA;AAAA,MACtE,YAAY,IAAA,CAAK,KAAA,CAAO,KAAA,CAAM,SAAA,GAAY,aAAcA,WAAU,CAAA;AAAA,MAClE,MAAM,KAAA,CAAM;AAAA,KACb,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,QAAQ,EAAE,KAAA,EAAO,MAAA,EAAQ,UAAA,EAAY,kBAAkB,WAAA,EAAY;AAAA,IACnE,MAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF;AAOA,SAAS,qBAAqB,IAAA,EAAkC;AAC9D,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,CAAC,KAAM,EAAA,EAAM,EAAA,EAAM,EAAI,CAAC,CAAA;AACrD,EAAA,MAAM,MAAA,GAASM,qCAAA,CAAkB,IAAA,EAAMC,yCAAA,EAAuBC,mCAAe,CAAA;AAC7E,EAAA,MAAM,IAAA,GAAOC,qCAAiB,IAAI,CAAA;AAClC,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,KAAA,CAAM,SAAS,MAAA,CAAO,MAAA,GAAS,KAAK,MAAM,CAAA;AACrE,EAAA,GAAA,CAAI,GAAA,CAAI,OAAO,CAAC,CAAA;AAChB,EAAA,GAAA,CAAI,GAAA,CAAI,MAAA,EAAQ,KAAA,CAAM,MAAM,CAAA;AAC5B,EAAA,GAAA,CAAI,GAAA,CAAI,IAAA,EAAM,KAAA,CAAM,MAAA,GAAS,OAAO,MAAM,CAAA;AAC1C,EAAA,OAAO,GAAA;AACT;AAMA,IAAMC,UAAAA,GAAY,IAAA;AAClB,IAAM,kBAAA,GAAqB,GAAA;AAE3B,SAAS,UAAU,KAAA,EAAgC;AACjD,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAIC,2BAAA,CAAS,KAAK,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,QAAQ,CAAC,CAAA;AACxB,EAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,oBAAoB,2BAA2B,CAAA;AACtE,EAAA,IAAI,MAAA,CAAO,UAAU,MAAA,EAAQ;AAC3B,IAAA,MAAM,IAAI,mBAAA;AAAA,MACR,CAAA,kBAAA,EAAqB,OAAO,KAAK,CAAA,uDAAA;AAAA,KACnC;AAAA,EACF;AACA,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,QAAQ,CAAA;AAEpD,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,MAAW,GAAA,IAAO,OAAO,OAAA,EAAS;AAGhC,IAAA,IAAI,MAAM,MAAA,GAAS,kBAAA;AACnB,IAAA,IAAI,GAAA,CAAI,mBAAmB,EAAA,EAAI;AAC7B,MAAA,MAAM,CAAA,GAAI,MAAA,CAAO,GAAA,CAAI,eAAe,CAAA;AACpC,MAAA,IAAI,CAAA,GAAI,QAAQ,GAAA,GAAM,CAAA;AAAA,IACxB;AACA,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAM,MAAM,CAAA;AAChD,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,KAAA;AAAA,MACN,WAAA,EAAa,IAAA,CAAK,KAAA,CAAO,MAAA,GAASD,aAAaV,WAAU,CAAA;AAAA,MACzD,UAAA,EAAY,IAAA,CAAK,KAAA,CAAO,eAAA,GAAkBU,aAAaV,WAAU,CAAA;AAAA,MACjE,MAAM,GAAA,CAAI;AAAA,KACX,CAAA;AACD,IAAA,MAAA,GAAS,GAAA;AAAA,EACX;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,MAAA;AAAA,MACP,UAAA,EAAYU,UAAAA;AAAA,MACZ,gBAAA;AAAA,MACA,aAAa,MAAA,CAAO;AAAA,KACtB;AAAA,IACA,MAAA;AAAA,IACA,UAAA,EAAYA,UAAAA;AAAA,IACZ;AAAA,GACF;AACF;AC7MO,SAAS,UAAU,OAAA,EAAmC;AAC3D,EAAA,MAAM,SAAA,GAAY,gBAAgB,OAAO,CAAA;AACzC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,gBAAgB,CAAA;AACrD,EAAA,MAAM,aAAA,GAAgB,EAAA;AACtB,EAAA,MAAM,UAAA,GAAc,WAAW,aAAA,GAAiB,CAAA;AAChD,EAAA,MAAM,IAAA,GAAgB;AAAA,IACpB,MAAA,EAAQ;AAAA,MACN,WAAA,EAAa,CAAA;AAAA,MACb,QAAA;AAAA,MACA,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,aAAA;AAAA,MACA,UAAA;AAAA,MACA,QAAA,EAAU,QAAQ,UAAA,GAAa;AAAA,KACjC;AAAA,IACA;AAAA,GACF;AACA,EAAA,OAAOE,gCAAa,IAAI,CAAA;AAC1B;AAsBA,eAAe,iBAAA,CACb,OAAA,EACA,MAAA,EACA,GAAA,EAC6B;AAC7B,EAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AAEzB,EAAA,MAAM,MAAoB,EAAC;AAC3B,EAAA,IAAI,WAAA;AAEJ,EAAA,MAAM,OAAA,GAAU,IAAIC,0CAAA,CAAsB,EAAE,QAAO,EAAG,CAAC,OAAO,QAAA,KAAa;AACzE,IAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,KAAA,CAAM,UAAU,CAAA;AAC7C,IAAA,KAAA,CAAM,OAAO,KAAK,CAAA;AAClB,IAAA,GAAA,CAAI,IAAA,CAAK;AAAA,MACP,IAAA,EAAM,KAAA;AAAA,MACN,aAAa,KAAA,CAAM,SAAA;AAAA,MACnB,UAAA,EAAY,MAAM,QAAA,IAAY;AAAA,KAC/B,CAAA;AACD,IAAA,MAAM,IAAA,GAAO,UAAU,aAAA,EAAe,WAAA;AACtC,IAAA,IAAI,WAAA,KAAgB,MAAA,IAAa,IAAA,KAAS,MAAA,EAAW;AACnD,MAAA,WAAA,GAAc,IAAI,UAAA;AAAA,QAChB,IAAA,YAAgB,WAAA,GAAc,IAAA,GAAQ,IAAA,CAAyB,MAAA;AAAA,QAC/D,IAAA,YAAgB,WAAA,GAAc,CAAA,GAAK,IAAA,CAAyB,UAAA;AAAA,QAC5D,IAAA,YAAgB,WAAA,GAAc,IAAA,CAAK,UAAA,GAAc,IAAA,CAAyB;AAAA,QAC1E,KAAA,EAAM;AAAA,IACV;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,OAAA,GAAU,MAAY,OAAA,CAAQ,KAAA,EAAM;AAC1C,EAAA,GAAA,CAAI,QAAQ,gBAAA,CAAiB,OAAA,EAAS,SAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAE7D,EAAA,IAAI;AACF,IAAA,MAAM,cAAA,GAAiB,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,CAAQ,UAAA,GAAa,EAAE,CAAC,CAAA;AACtE,IAAA,MAAM,KAAA,GAAQ,QAAQ,cAAA,IAAkB,CAAA;AACxC,IAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,OAAA,CAAQ,cAAA,EAAgB,SAAS,cAAA,EAAgB;AAC3E,MAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,cAAA,EAAgB,OAAA,CAAQ,iBAAiB,KAAK,CAAA;AACrE,MAAA,MAAM,cAAc,IAAA,CAAK,KAAA,CAAO,KAAA,GAAQ,OAAA,CAAQ,aAAc,GAAS,CAAA;AACvE,MAAA,OAAA,CAAQ,OAAO,cAAA,CAAe,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,WAAW,CAAC,CAAA;AACjE,MAAA,GAAA,CAAI,aAAa,IAAA,CAAK,GAAA,CAAI,IAAI,KAAA,GAAQ,KAAA,IAAS,KAAK,CAAC,CAAA;AAAA,IACvD;AACA,IAAA,MAAM,QAAQ,KAAA,EAAM;AACpB,IAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AAAA,EAC3B,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,YAAA,CAAa,KAAK,QAAQ,CAAA;AAAA,EAClC,CAAA,SAAE;AACA,IAAA,GAAA,CAAI,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AAChD,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB;AAEA,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,WAAA,EAAY;AACpC;AAMO,IAAMH,UAAAA,GAAY,IAAA;AAClB,IAAM,aAAA,GAAgB,IAAA;AAC7B,IAAM,UAAA,GAAa,CAAA;AACnB,IAAM,mBAAA,GAAsB,GAAA;AAC5B,IAAM,sBAAA,GAAyB,GAAA;AAMxB,SAAS,gBAAA,CACd,OAAA,EACA,IAAA,EACA,GAAA,EACuB;AACvB,EAAA,OAAO,UAAA,CAAW,OAAA,EAAS,IAAA,EAAM,GAAG,CAAA;AACtC;AAEA,eAAe,UAAA,CACb,OAAA,EACA,IAAA,EACA,GAAA,EACuB;AACvB,EAAA,MAAM,MAAA,GAA6B;AAAA,IACjC,KAAA,EAAO,MAAA;AAAA,IACP,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,gBAAA,EAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,gBAAgB,CAAA;AAAA,IACtD,GAAI,KAAK,OAAA,GAAU,EAAE,SAAS,IAAA,CAAK,OAAA,KAAY;AAAC,GAClD;AACA,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,iBAAA,CAAkB,OAAA,EAAS,QAAQ,GAAG,CAAA;AAC/D,EAAA,OAAO,MAAA;AACT;AAGA,eAAsB,aAAA,CACpB,OAAA,EACA,IAAA,EACA,GAAA,EACqB;AACrB,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,gBAAgB,CAAA;AACrD,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,OAAA,EAAS,MAAM,GAAG,CAAA;AAClD,EAAA,MAAM,iBAAiBI,gCAAA,CAAc;AAAA,IACnC,YAAA,EAAc,QAAA;AAAA,IACd,OAAA,EAAS,aAAA;AAAA,IACT,iBAAiB,OAAA,CAAQ;AAAA,GAC1B,CAAA;AACD,EAAA,MAAM,QAAA,GAAWC,iCAAc,kBAAA,EAAoB;AAAA,IACjD,EAAE,GAAA,EAAK,SAAA,EAAW,KAAA,EAAO,kBAAA;AAAmB,GAC7C,CAAA;AAED,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACjC,MAAM,CAAA,CAAE,IAAA;AAAA;AAAA,IAER,eAAA,EAAiB,MAAA;AAAA,MACf,IAAA,CAAK,OAAQ,CAAA,CAAE,WAAA,GAAc,EAAE,UAAA,IAAc,GAAA,GAAaL,UAAS,CAAA,GAAI;AAAA,KACzE;AAAA,IACA,YAAA,EAAc;AAAA,GAChB,CAAE,CAAA;AAEF,EAAA,MAAM,IAAA,GAAgB;AAAA,IACpB,OAAA,EAAS;AAAA,MACP;AAAA,QACE,YAAA,EAAc,UAAA;AAAA,QACd,KAAA,EAAO,MAAA;AAAA,QACP,cAAA;AAAA,QACA,QAAA;AAAA,QACA,KAAA,EAAO,MAAA;AAAA,QACP,OAAA;AAAA,QACA,OAAA,EAAS,aAAA;AAAA,QACT,UAAA,EAAYA,UAAAA;AAAA,QACZ;AAAA;AACF;AACF,GACF;AACA,EAAA,OAAOM,gCAAa,IAAI,CAAA;AAC1B;AAGA,eAAsB,cAAA,CACpB,OAAA,EACA,IAAA,EACA,GAAA,EACqB;AACrB,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,gBAAgB,CAAA;AACrD,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,OAAA,EAAS,MAAM,GAAG,CAAA;AAClD,EAAA,MAAM,eAAeF,gCAAA,CAAc;AAAA,IACjC,YAAA,EAAc,QAAA;AAAA,IACd,OAAA,EAAS,aAAA;AAAA,IACT,iBAAiB,OAAA,CAAQ;AAAA,GAC1B,CAAA;AAGD,EAAA,MAAM,WAA0B,EAAC;AACjC,EAAA,IAAI,OAAA,GAA8B,IAAA;AAClC,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,WAAA,GAAc,GAAI,CAAC,CAAA;AACpD,IAAA,IAAI,YAAY,IAAA,IAAQ,IAAA,GAAO,QAAQ,QAAA,GAAW,MAAA,CAAO,sBAAsB,CAAA,EAAG;AAChF,MAAA,OAAA,GAAU,EAAE,UAAA,EAAY,CAAA,EAAG,UAAU,IAAA,EAAM,MAAA,EAAQ,EAAC,EAAE;AACtD,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,IACvB;AACA,IAAA,OAAA,CAAQ,OAAO,IAAA,CAAK;AAAA,MAClB,WAAA,EAAa,CAAA;AAAA,MACb,WAAA,EAAa,IAAA,GAAO,MAAA,CAAO,mBAAmB,CAAA;AAAA,MAC9C,QAAA,EAAU,IAAA;AAAA,MACV,SAAA,EAAW,KAAA;AAAA,MACX,WAAA,EAAa,KAAA;AAAA,MACb,MAAA,EAAQ,CAAC,CAAA,CAAE,IAAI;AAAA,KAChB,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,KAAA,GAAwB;AAAA,IAC5B,WAAA,EAAa,CAAA;AAAA,IACb,QAAA,EAAU,EAAA;AAAA,IACV,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,QAAA;AAAA,IACT,YAAA;AAAA,IACA,iBAAA,EAAmBJ,UAAAA;AAAA,IACnB;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAiB;AAAA,IACrB,UAAA,EAAY;AAAA,MACV,WAAA,EAAa,CAAA;AAAA,MACb,eAAA,EAAiB,CAAA;AAAA,MACjB,eAAA,EAAiB,CAAA;AAAA,MACjB,iBAAA,EAAmB,CAAA;AAAA,MACnB,OAAA,EAAS,MAAA;AAAA,MACT,cAAA,EAAgB,CAAA;AAAA,MAChB,kBAAA,EAAoB;AAAA,KACtB;AAAA,IACA,oBAAA,EAAsB,CAAA;AAAA;AAAA,IACtB,IAAA,EAAM;AAAA,MACJ,aAAA,EAAe,mBAAA;AAAA,MACf,SAAA,EAAW,kBAAA;AAAA,MACX,UAAA,EAAY;AAAA,KACd;AAAA,IACA,MAAA,EAAQ,CAAC,KAAK,CAAA;AAAA,IACd,QAAA;AAAA,IACA,SAAA,EAAW,IAAI,UAAA,CAAW,CAAC;AAAA;AAAA,GAC7B;AACA,EAAA,OAAOO,kCAAc,IAAI,CAAA;AAC3B;AAOA,eAAsB,SAAA,CACpB,OAAA,EACA,IAAA,EACA,GAAA,EACqB;AACrB,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,KAAA,EAAO,WAAA;AAAA,IACP,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,gBAAA,EAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,gBAAgB,CAAA;AAAA,IACtD,GAAI,KAAK,OAAA,GAAU,EAAE,SAAS,IAAA,CAAK,OAAA,KAAY,EAAC;AAAA;AAAA;AAAA,IAGhD,GAAA,EAAK,EAAE,MAAA,EAAQ,MAAA;AAAgB,GACjC;AAEA,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,iBAAA,CAAkB,OAAA,EAAS,QAAQ,GAAG,CAAA;AAC/D,EAAA,OAAO,YAAY,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAC9C;AAgBA,eAAsB,UAAA,CACpB,OAAA,EACA,KAAA,EACA,GAAA,EACqB;AACrB,EAAA,MAAM,MAAA,GAA6B;AAAA,IACjC,KAAA,EAAO,MAAA;AAAA,IACP,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,gBAAA,EAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,gBAAgB;AAAA,GACxD;AACA,EAAA,MAAM,EAAE,QAAQ,WAAA,EAAY,GAAI,MAAM,iBAAA,CAAkB,OAAA,EAAS,QAAQ,GAAG,CAAA;AAC5E,EAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,IAAA,MAAM,IAAI,mBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,WAAA,CAAY,CAAC,WAAA,EAAa,GAAG,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAC,CAAA;AAChE;AAMA,SAAS,YAAY,KAAA,EAAiC;AACpD,EAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,CAAC,CAAA;AACpD,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,KAAK,CAAA;AAChC,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,GAAA,CAAI,GAAA,CAAI,GAAG,GAAG,CAAA;AACd,IAAA,GAAA,IAAO,CAAA,CAAE,MAAA;AAAA,EACX;AACA,EAAA,OAAO,GAAA;AACT;;;ACxUO,IAAM,YAAA,GAAoD,OAAO,MAAA,CAAO;AAAA,EAC7E,WAAA,EAAa,KAAA;AAAA,EACb,aAAA,EAAe,KAAA;AAAA,EACf,YAAA,EAAc,KAAA;AAAA,EACd,YAAA,EAAc,KAAA;AAAA,EACd,WAAA,EAAa,KAAA;AAAA,EACb,cAAA,EAAgB,KAAA;AAAA,EAChB,WAAA,EAAa,KAAA;AAAA,EACb,aAAA,EAAe,KAAA;AAAA,EACf,WAAA,EAAa,MAAA;AAAA,EACb,YAAA,EAAc,MAAA;AAAA,EACd,YAAA,EAAc,MAAA;AAAA,EACd,cAAA,EAAgB;AAClB,CAAC;AAUM,IAAM,cAAA,GAAyD,OAAO,MAAA,CAAO;AAAA,EAClF,WAAA,EAAa,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,EAC9C,aAAA,EAAe,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,EAChD,YAAA,EAAc,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,EAC/C,WAAA,EAAa,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,MAAA,EAAO;AAAA,EAC/C,YAAA,EAAc,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,MAAA,EAAO;AAAA,EAChD,YAAA,EAAc,EAAE,SAAA,EAAW,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,EACjD,WAAA,EAAa,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,EAC9C,YAAA,EAAc,EAAE,SAAA,EAAW,MAAA,EAAQ,OAAO,MAAA;AAC5C,CAAC;AAMM,IAAM,mBAAwC,MAAA,CAAO,MAAA;AAAA,EAC1D,IAAI,GAAA;AAAA,IACF,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,CAAE,OAAA;AAAA,MAAQ,CAAC,MAAA,KACjC,MAAA,CAAO,IAAA,CAAK,cAAc,CAAA,CAAE,GAAA,CAAI,CAAC,OAAA,KAAY,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE;AAAA;AACrE;AAEJ;AAGO,SAAS,SAAA,CAAU,WAAmB,UAAA,EAA4B;AACvE,EAAA,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AACnC;AAGO,SAAS,cAAc,IAAA,EAAqC;AACjE,EAAA,OAAO,aAAa,IAAI,CAAA;AAC1B;AAGO,SAAS,gBAAgB,IAAA,EAAwC;AACtE,EAAA,OAAO,eAAe,IAAI,CAAA;AAC5B;AA0BO,IAAM,gBAAA,GAA8D,OAAO,MAAA,CAAO;AAAA,EACvF,WAAA,EAAa,KAAA;AAAA,EACb,WAAA,EAAa,KAAA;AAAA;AAAA,EACb,YAAA,EAAc,MAAA;AAAA,EACd,YAAA,EAAc,MAAA;AAAA;AAAA,EACd,kBAAA,EAAoB,KAAA;AAAA,EACpB,WAAA,EAAa;AACf,CAAC;AAYM,IAAM,aAAA,GAAuD,OAAO,MAAA,CAAO;AAAA,EAChF,YAAA,EAAc,EAAE,SAAA,EAAW,MAAA,EAAO;AAAA,EAClC,kBAAA,EAAoB,EAAE,SAAA,EAAW,KAAA,EAAM;AAAA,EACvC,WAAA,EAAa,EAAE,SAAA,EAAW,KAAA;AAC5B,CAAC;AAQM,IAAM,qBAAA,GACX,MAAA,CAAO,MAAA,CAAO,EAAE,GAAA,EAAK,OAAO,IAAA,EAAM,MAAA,EAAQ,GAAA,EAAK,MAAA,EAAQ;AAGlD,IAAM,qBAAA,GACX,MAAA,CAAO,MAAA,CAAO,EAAE,GAAA,EAAK,QAAQ,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,MAAA,EAAQ;AAGlD,SAAS,mBAAmB,IAAA,EAA2C;AAC5E,EAAA,OAAO,iBAAiB,IAAI,CAAA;AAC9B;AAGO,SAAS,eAAe,IAAA,EAAuC;AACpE,EAAA,OAAO,cAAc,IAAI,CAAA;AAC3B;AAOO,IAAM,eAAA,GAAkB;AAQxB,IAAM,eAAA,GAAkB,MAAM,IAAA,GAAO;AASrC,SAAS,cAAA,CACd,KAAA,EACA,OAAA,EACA,QAAA,EACoB;AACpB,EAAA,MAAM,CAAA,GAAI,QAAQ,OAAO,CAAA;AACzB,EAAA,IAAI,MAAA;AACJ,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,MAAA;AAEH,MAAA,MAAA,GAAS,MAAA,CAAO,CAAA,EAAG,IAAA,EAAQ,KAAA,EAAS,KAAO,CAAA;AAC3C,MAAA;AAAA,IACF,KAAK,KAAA;AAEH,MAAA,MAAA,GAAS,MAAA,CAAO,CAAA,EAAG,IAAA,EAAQ,KAAA,EAAS,KAAO,CAAA;AAC3C,MAAA;AAAA,IACF;AACE,MAAA,OAAO,MAAA;AAAA;AAEX,EAAA,MAAM,KAAA,GAAQ,QAAA,IAAY,CAAA,GAAI,GAAA,GAAM,CAAA;AACpC,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,KAAK,CAAA;AAClC;AAQO,SAAS,mBAAA,CACd,KAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACQ;AACR,EAAA,MAAM,CAAA,GAAI,QAAQ,OAAO,CAAA;AACzB,EAAA,MAAM,MAAA,GAAS,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA;AACtD,EAAA,MAAM,KAAA,GAAQ,UAAU,IAAA,GAAO,GAAA,CAAA;AAC/B,EAAA,MAAM,OAAO,YAAA,GAAe,KAAA;AAC5B,EAAA,MAAM,KAAA,GACJ,CAAA,IAAK,eAAA,GACD,GAAA,GAAO,GAAA,GAAM,CAAA,GAAK,eAAA,GAClB,CAAA,GAAO,GAAA,IAAO,CAAA,GAAI,eAAA,CAAA,IAAqB,CAAA,GAAI,eAAA,CAAA;AACjD,EAAA,MAAM,WAAA,GAAc,KAAA,KAAU,KAAA,GAAQ,GAAA,GAAM,CAAA;AAC5C,EAAA,OAAO,IAAA,CAAK,IAAI,aAAA,EAAe,IAAA,CAAK,MAAM,IAAA,GAAO,KAAA,GAAQ,WAAW,CAAC,CAAA;AACvE;AAOA,IAAM,YAAA,GAAe,GAAA;AAErB,IAAM,aAAA,GAAgB,GAAA;AAEtB,SAAS,QAAQ,CAAA,EAAmB;AAClC,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,EAAG,OAAO,eAAA;AAC5B,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,CAAA;AACnC;AAMA,SAAS,MAAA,CAAO,CAAA,EAAW,EAAA,EAAY,GAAA,EAAa,EAAA,EAAoB;AACtE,EAAA,MAAM,IAAA,GAAO,eAAA;AACb,EAAA,IAAI,KAAK,IAAA,EAAM,OAAO,EAAA,GAAA,CAAO,GAAA,GAAM,MAAM,CAAA,GAAK,IAAA;AAC9C,EAAA,OAAO,GAAA,GAAA,CAAQ,EAAA,GAAK,GAAA,KAAQ,CAAA,GAAI,SAAU,CAAA,GAAI,IAAA,CAAA;AAChD;ACzNO,IAAM,aAAN,MAAiB;AAAA,EACb,OAAA,uBAAc,GAAA,EAAqB;AAAA,EACnC,OAAA,uBAAc,GAAA,EAAqB;AAAA,EACnC,YAAA,uBAAmB,GAAA,EAAqB;AAAA,EACxC,YAAA,uBAAmB,GAAA,EAAgC;AAAA;AAAA,EAG5D,MAAM,SAAA,CAAU,KAAA,EAAuB,KAAA,GAAoB,EAAC,EAAqB;AAC/E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,IAAA,MAAM,EAAA,GAAK,MAAM,WAAA,CAAY,MAAMC,sCAAA,CAAkB,EAAE,KAAA,EAAO,GAAG,KAAA,EAAO,CAAC,CAAA;AACzE,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAC1B,IAAA,OAAO,EAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,SAAA,CAAU,KAAA,EAAuB,KAAA,GAAoB,EAAC,EAAqB;AAC/E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,IAAA,MAAM,EAAA,GAAK,MAAM,WAAA,CAAY,MAAMC,oCAAA,CAAgB,EAAE,KAAA,EAAO,GAAG,KAAA,EAAO,CAAC,CAAA;AACvE,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAC1B,IAAA,OAAO,EAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,eAAe,KAAA,EAAyC;AAC5D,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,KAAK,CAAA;AAC1C,IAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,IAAA,MAAM,EAAA,GAAK,MAAM,WAAA,CAAY,MAAMC,uCAAkB,EAAE,KAAA,EAAO,CAAC,CAAA;AAC/D,IAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAC/B,IAAA,OAAO,EAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAA,CACJ,KAAA,EACA,KAAA,GAAyB,EAAC,EACG;AAC7B,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,KAAA,CAAM,SAAS,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,MAAA,IAAU,CAAC,CAAA,CAAA;AAC7D,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA;AACxC,IAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,IAAI,MAAMC,oCAAA,CAAgB,EAAE,KAAA,EAAO,GAAG,OAAO,CAAA;AACnD,MAAA,MAAA,GAAS,CAAA,CAAE,YAAY,CAAA,GAAI,IAAA;AAAA,IAC7B,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,GAAA,YAAeC,iDAA4B,MAAA,GAAS,IAAA;AAAA,WACnD,MAAM,GAAA;AAAA,IACb;AACA,IAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,GAAA,EAAK,MAAM,CAAA;AACjC,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,cAAA,CAAe,KAAA,EAAuB,KAAA,GAAyB,EAAC,EAAqB;AACzF,IAAA,OAAQ,MAAM,IAAA,CAAK,gBAAA,CAAiB,KAAA,EAAO,KAAK,CAAA,KAAO,IAAA;AAAA,EACzD;AACF,CAAA;AAEA,eAAe,YAAY,GAAA,EAA8D;AACvF,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,EAAI;AACzB,IAAA,OAAO,MAAA,CAAO,SAAA;AAAA,EAChB,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,GAAA,YAAeA,iDAA4B,OAAO,KAAA;AACtD,IAAA,MAAM,GAAA;AAAA,EACR;AACF;AC7CA,IAAM,oBAAA,GAAuB,GAAA;AAC7B,IAAMC,oBAAAA,GAAsB,GAAA;AAC5B,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,WAAA,GAAc,CAAA;AACpB,IAAM,WAAA,GAAc,CAAA;AAMpB,eAAsB,cAAA,CACpB,MAAA,EACA,eAAA,EACA,KAAA,EACA,QACA,IAAA,EAC+B;AAC/B,EAAA,MAAM,EAAE,QAAO,GAAI,IAAA;AACnB,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,IAAA,CAAK,UAAU,CAAA;AAErC,EAAA,IAAA,CAAK,GAAG,OAAO,CAAA;AACf,EAAA,MAAM,KAAA,GAAQ,mBAAA,CAAoB,MAAA,EAAQ,KAAK,CAAA;AAC/C,EAAA,IAAA,CAAK,GAAG,OAAO,CAAA;AACf,EAAA,cAAA,CAAe,MAAM,CAAA;AAIrB,EAAA,MAAM,EAAE,UAAA,EAAY,WAAA,EAAa,mBAAA,KAAwB,MAAM,kBAAA;AAAA,IAC7D,KAAA,CAAM,KAAA;AAAA,IACN,MAAA;AAAA,IACA,IAAA,CAAK;AAAA,GACP;AAGA,EAAA,MAAM,SAAA,GAAY,MAAM,SAAA,CAAU,KAAA,CAAM,OAAO,MAAM,CAAA;AACrD,EAAA,MAAM,QAAA,GAAW,YAAY,EAAA,GAAK,EAAA;AAElC,EAAA,IAAA,CAAK,GAAG,QAAQ,CAAA;AAChB,EAAA,MAAM,QAAA,GAAW,MAAM,gBAAA,CAAiB,KAAA,EAAO,YAAY,WAAA,EAAa;AAAA,IACtE,MAAA;AAAA,IACA,sBAAsB,IAAA,CAAK,oBAAA;AAAA,IAC3B,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,SAAA,EAAW,CAAC,QAAA,KAAa,IAAA,CAAK,IAAI,QAAA,IAAY,QAAA,GAAW,IAAI,QAAQ;AAAA,GACtE,CAAA;AACD,EAAA,cAAA,CAAe,MAAM,CAAA;AAGrB,EAAA,IAAI,QAAA,GAAgC,IAAA;AACpC,EAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,IAAA,CAAK,UAAU,QAAQ,CAAA;AACvB,IAAA,MAAM,UAAU,MAAM,WAAA;AAAA,MACpB;AAAA,QACE,IAAA,EAAM,SAAA;AAAA,QACN,MAAA,EAAQ,UAAU,KAAA,CAAM,MAAA;AAAA,QACxB,MAAA,EAAQ,UAAU,KAAA,CAAM,MAAA;AAAA,QACxB,UAAA,EAAY,UAAU,KAAA,CAAM,UAAA;AAAA,QAC5B,gBAAA,EAAkB,UAAU,KAAA,CAAM;AAAA,OACpC;AAAA,MACA,EAAE,MAAA,EAAQ,UAAA,EAAY,CAAC,CAAA,KAAM,KAAK,QAAA,GAAW,CAAA,GAAI,EAAA,EAAI,QAAQ,CAAA;AAAE,KACjE;AACA,IAAA,cAAA,CAAe,MAAM,CAAA;AACrB,IAAA,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,gBAAgB,CAAA;AACpD,IAAA,QAAA,GAAW,MAAM,gBAAA;AAAA,MACf,OAAA;AAAA,MACA,EAAC;AAAA,MACD,EAAE,MAAA,EAAQ,UAAA,EAAY,CAAC,CAAA,KAAM,KAAK,EAAA,GAAK,CAAA,GAAI,EAAA,EAAI,QAAQ,CAAA;AAAE,KAC3D;AACA,IAAA,cAAA,CAAe,MAAM,CAAA;AAAA,EACvB;AAEA,EAAA,IAAA,CAAK,IAAI,KAAK,CAAA;AACd,EAAA,MAAM,QAAA,GACJ,oBAAoB,KAAA,GAChB,QAAA;AAAA,IACE,MAAM,KAAA,CAAM,KAAA;AAAA,IACZ,MAAM,KAAA,CAAM,MAAA;AAAA,IACZ,UAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACF,GACA,SAAA;AAAA,IACE,MAAM,KAAA,CAAM,KAAA;AAAA,IACZ,MAAM,KAAA,CAAM,MAAA;AAAA,IACZ,UAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACF;AACN,EAAA,cAAA,CAAe,MAAM,CAAA;AAErB,EAAA,IAAA,CAAK,KAAK,MAAM,CAAA;AAChB,EAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,mBAAA,EAAqB,aAAA,EAAe,aAAa,IAAA,EAAK;AAClF;AAMA,eAAe,kBAAA,CACb,KAAA,EACA,MAAA,EACA,oBAAA,EAC2F;AAC3F,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,GAAI,oBAAA,GAAuB,EAAE,oBAAA,KAAyB;AAAC,GACzD;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,gBAAA,CAAiB,OAAO,KAAK,CAAA;AACtD,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,OAAO;AAAA,MACL,UAAA,EAAY,KAAA;AAAA,MACZ,WAAA,EAAa,eAAA;AAAA,MACb,qBAAqB,GAAA,CAAI;AAAA,KAC3B;AAAA,EACF;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,gBAAA,CAAiB,OAAO,KAAK,CAAA;AACtD,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,OAAO,EAAE,UAAA,EAAY,KAAA,EAAO,aAAa,KAAA,EAAO,mBAAA,EAAqB,IAAI,mBAAA,EAAoB;AAAA,EAC/F;AACA,EAAA,MAAM,IAAI,oBAAoB,uDAAuD,CAAA;AACvF;AAMA,eAAe,SAAA,CACb,OACA,MAAA,EAC2B;AAC3B,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,UAAA,GAAa,cAAA,CAAe,KAAA,CAAM,MAAA,CAAO,KAAK,CAAA;AACpD,EAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AACxB,EAAA,IAAI,CAAE,MAAM,MAAA,CAAO,SAAA,CAAU,UAAU,GAAI,OAAO,IAAA;AAClD,EAAA,IAAI,CAAE,MAAM,MAAA,CAAO,SAAA,CAAU,MAAM,GAAI,OAAO,IAAA;AAC9C,EAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AACxB;AAEA,SAAS,eAAe,KAAA,EAA+C;AACrE,EAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,MAAA;AAC7B,EAAA,IAAI,MAAM,UAAA,CAAW,MAAM,CAAA,IAAK,KAAA,KAAU,OAAO,OAAO,KAAA;AACxD,EAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,MAAA;AAC7B,EAAA,OAAO,IAAA;AACT;AAmBA,eAAe,gBAAA,CACb,KAAA,EACA,UAAA,EACA,WAAA,EACA,GAAA,EACqB;AACrB,EAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAO,GAAI,KAAA;AAC1B,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,SAAA,GAAY,CAAA,GAAI,MAAM,SAAA,GAAY,EAAA;AAC1D,EAAA,MAAM,UAAU,mBAAA,CAAoB,KAAA,EAAO,MAAA,EAAQ,GAAA,CAAI,SAAS,UAAU,CAAA;AAC1E,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,CAAO,MAAA,IAAU,CAAA;AAErC,EAAA,MAAM,MAAkB,EAAC;AACzB,EAAA,MAAM,UAAU,IAAIC,0CAAA;AAAA,IAClB;AAAA,MACE,MAAA,EAAQ;AAAA,QACN,KAAA,EAAO,WAAA;AAAA,QACP,KAAA;AAAA,QACA,MAAA;AAAA,QACA,OAAA;AAAA,QACA,SAAA,EAAW,SAAA;AAAA,QACX,GAAI,IAAI,oBAAA,GAAuB,EAAE,sBAAsB,GAAA,CAAI,oBAAA,KAAyB;AAAC;AACvF,KACF;AAAA,IACA,CAAC,KAAA,KAAU;AACT,MAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW,KAAA,CAAM,UAAU,CAAA;AAC5C,MAAA,KAAA,CAAM,OAAO,IAAI,CAAA;AACjB,MAAA,GAAA,CAAI,IAAA,CAAK,EAAE,IAAA,EAAM,WAAA,EAAa,KAAA,CAAM,WAAW,QAAA,EAAU,KAAA,CAAM,IAAA,KAAS,KAAA,EAAO,CAAA;AAC/E,MAAA,GAAA,CAAI,UAAU,IAAA,CAAK,GAAA,CAAI,GAAG,GAAA,CAAI,MAAA,GAAS,KAAK,CAAC,CAAA;AAAA,IAC/C;AAAA,GACF;AAEA,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,iBAAiB,MAAA,CAAO,iBAAA;AAC5B,EAAA,MAAM,OAAA,GAAU,IAAIC,0CAAA,CAAsB,EAAE,QAAQ,KAAA,CAAM,MAAA,EAAO,EAAG,CAAC,KAAA,KAAU;AAI7E,IAAA,IAAI,GAAA,CAAI,QAAQ,OAAA,EAAS;AACvB,MAAA,KAAA,CAAM,KAAA,EAAM;AACZ,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAK,KAAA,CAAM,SAAA;AACjB,IAAA,MAAM,QAAA,GAAW,UAAA,KAAe,CAAA,IAAK,EAAA,GAAK,cAAA,IAAkB,oBAAA;AAC5D,IAAA,IAAI,UAAU,cAAA,GAAiB,EAAA;AAC/B,IAAA,UAAA,EAAA;AAGA,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,QAAA,EAAU,CAAA;AAAA,EACpC,CAAC,CAAA;AAED,EAAA,MAAM,UAAU,MAAY;AAC1B,IAAA,OAAA,CAAQ,KAAA,EAAM;AACd,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB,CAAA;AACA,EAAA,GAAA,CAAI,QAAQ,gBAAA,CAAiB,OAAA,EAAS,SAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAE7D,EAAA,IAAI;AACF,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AAC5C,MAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,CAAA,GAAI,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA;AACxB,MAAA,IAAI,CAAC,CAAA,EAAG;AACR,MAAA,OAAA,CAAQ,MAAA;AAAA,QACN,IAAI,iBAAA,CAAkB;AAAA,UACpB,MAAM,CAAA,CAAE,IAAA;AAAA,UACR,WAAW,CAAA,CAAE,WAAA;AAAA,UACb,UAAU,CAAA,CAAE,UAAA;AAAA,UACZ,MAAM,CAAA,CAAE;AAAA,SACT;AAAA,OACH;AAAA,IACF;AACA,IAAA,MAAM,QAAQ,KAAA,EAAM;AACpB,IAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AACzB,IAAA,MAAM,QAAQ,KAAA,EAAM;AACpB,IAAA,cAAA,CAAe,IAAI,MAAM,CAAA;AAAA,EAC3B,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,YAAA,CAAa,KAAK,OAAO,CAAA;AAAA,EACjC,CAAA,SAAE;AACA,IAAA,GAAA,CAAI,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AAChD,IAAA,OAAA,CAAQ,KAAA,EAAM;AACd,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB;AAEA,EAAA,OAAO,GAAA;AACT;AA+BA,SAAS,aAAA,CAAc,UAAsB,QAAA,EAA+C;AAC1F,EAAA,MAAM,SAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,WAAA,EAAa,WAAA;AAAA,MACb,aAAa,CAAA,CAAE,WAAA;AAAA,MACf,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,MAAM,CAAA,CAAE;AAAA,KACT,CAAA;AAAA,EACH;AACA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,WAAA,EAAa,WAAA;AAAA,QACb,aAAa,CAAA,CAAE,WAAA;AAAA,QACf,QAAA,EAAU,IAAA;AAAA,QACV,MAAM,CAAA,CAAE;AAAA,OACT,CAAA;AAAA,IACH;AAAA,EACF;AAGA,EAAA,MAAA,CAAO,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,WAAA,GAAc,EAAE,WAAW,CAAA;AAEnD,EAAA,MAAM,WAA2B,EAAC;AAClC,EAAA,IAAI,OAAA,GAA+B,IAAA;AACnC,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,WAAA,GAAc,GAAI,CAAC,CAAA;AACpD,IAAA,MAAM,QAAA,GACJ,OAAA,KAAY,IAAA,IACX,CAAA,CAAE,WAAA,KAAgB,WAAA,IAAe,CAAA,CAAE,QAAA,IACpC,IAAA,GAAO,OAAA,CAAQ,QAAA,GAAW,MAAA,CAAO,iBAAiB,CAAA;AACpD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAA,GAAU,EAAE,UAAA,EAAY,CAAA,EAAG,UAAU,IAAA,EAAM,MAAA,EAAQ,EAAC,EAAE;AACtD,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,IACvB;AACA,IAAA,OAAA,EAAS,OAAO,IAAA,CAAK;AAAA,MACnB,aAAa,CAAA,CAAE,WAAA;AAAA,MACf,WAAA,EAAa,IAAA,GAAO,MAAA,CAAOF,oBAAmB,CAAA;AAAA,MAC9C,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,SAAA,EAAW,KAAA;AAAA,MACX,WAAA,EAAa,KAAA;AAAA,MACb,MAAA,EAAQ,CAAC,CAAA,CAAE,IAAI;AAAA,KAChB,CAAA;AAAA,EACH;AACA,EAAA,OAAO,QAAA;AACT;AAEA,SAAS,UACP,KAAA,EACA,MAAA,EACA,UAAA,EACA,QAAA,EACA,UACA,aAAA,EACY;AACZ,EAAA,MAAM,UAAA,GAA6B;AAAA,IACjC,WAAA,EAAa,WAAA;AAAA,IACb,QAAA,EAAU,EAAA;AAAA,IACV,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,UAAA,KAAe,KAAA,GAAQ,OAAA,GAAU,OAAA;AAAA,IAC1C,UAAA,EAAY,KAAA;AAAA,IACZ,WAAA,EAAa;AAAA,GACf;AACA,EAAA,MAAM,MAAA,GAA6B,CAAC,UAAU,CAAA;AAC9C,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,UAAA,GAA6B;AAAA,MACjC,WAAA,EAAa,WAAA;AAAA,MACb,QAAA,EAAU,EAAA;AAAA,MACV,SAAA,EAAW,CAAA;AAAA,MACX,OAAA,EAAS,QAAA;AAAA,MACT,YAAA,EAAc,SAAS,aAAa,CAAA;AAAA,MACpC,iBAAA,EAAmBb,UAAAA;AAAA,MACnB,QAAA,EAAU;AAAA,KACZ;AACA,IAAA,MAAA,CAAO,KAAK,UAAU,CAAA;AAAA,EACxB;AAEA,EAAA,MAAM,IAAA,GAAiB;AAAA,IACrB,UAAA,EAAY;AAAA,MACV,WAAA,EAAa,CAAA;AAAA,MACb,eAAA,EAAiB,CAAA;AAAA,MACjB,eAAA,EAAiB,CAAA;AAAA,MACjB,iBAAA,EAAmB,CAAA;AAAA,MACnB,OAAA,EAAS,MAAA;AAAA,MACT,cAAA,EAAgB,CAAA;AAAA,MAChB,kBAAA,EAAoB;AAAA,KACtB;AAAA,IACA,oBAAA,EAAsB,CAAA;AAAA,IACtB,IAAA,EAAM;AAAA,MACJ,aAAA,EAAea,oBAAAA;AAAA,MACf,SAAA,EAAW,kBAAA;AAAA,MACX,UAAA,EAAY;AAAA,KACd;AAAA,IACA,MAAA;AAAA,IACA,QAAA,EAAU,aAAA,CAAc,QAAA,EAAU,QAAQ,CAAA;AAAA,IAC1C,SAAA,EAAW,IAAI,UAAA,CAAW,CAAC;AAAA,GAC7B;AACA,EAAA,OAAON,kCAAc,IAAI,CAAA;AAC3B;AAEA,SAAS,SACP,KAAA,EACA,MAAA,EACA,UAAA,EACA,QAAA,EACA,UACA,aAAA,EACY;AACZ,EAAA,MAAM,UAAA,GAA4B;AAAA,IAChC,WAAA,EAAa,WAAA;AAAA,IACb,QAAA,EAAU,EAAA;AAAA,IACV,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,UAAA,KAAe,KAAA,GAAQ,OAAA,GAAU,OAAA;AAAA,IAC1C,UAAA,EAAY,KAAA;AAAA,IACZ,WAAA,EAAa,MAAA;AAAA,IACb,oBAAA,EAAsB,UAAA,KAAe,KAAA,GAAQ,KAAA,GAAQ;AAAA,GACvD;AACA,EAAA,MAAM,MAAA,GAA4B,CAAC,UAAU,CAAA;AAC7C,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,UAAA,GAA4B;AAAA,MAChC,WAAA,EAAa,WAAA;AAAA,MACb,QAAA,EAAU,EAAA;AAAA,MACV,SAAA,EAAW,CAAA;AAAA,MACX,OAAA,EAAS,QAAA;AAAA,MACT,YAAA,EAAc,SAAS,aAAa,CAAA;AAAA,MACpC,iBAAA,EAAmBP,UAAAA;AAAA,MACnB,QAAA,EAAU,aAAA;AAAA,MACV,oBAAA,EAAsB;AAAA,KACxB;AACA,IAAA,MAAA,CAAO,KAAK,UAAU,CAAA;AAAA,EACxB;AAEA,EAAA,MAAM,IAAA,GAAgB;AAAA,IACpB,UAAA,EAAY;AAAA,MACV,WAAA,EAAa,CAAA;AAAA,MACb,eAAA,EAAiB,CAAA;AAAA,MACjB,eAAA,EAAiB,CAAA;AAAA,MACjB,iBAAA,EAAmB,CAAA;AAAA,MACnB,OAAA,EAAS,UAAA;AAAA,MACT,cAAA,EAAgB,CAAA;AAAA,MAChB,kBAAA,EAAoB;AAAA,KACtB;AAAA,IACA,oBAAA,EAAsB,CAAA;AAAA,IACtB,IAAA,EAAM;AAAA,MACJ,aAAA,EAAea,oBAAAA;AAAA,MACf,SAAA,EAAW,kBAAA;AAAA,MACX,UAAA,EAAY;AAAA,KACd;AAAA,IACA,MAAA;AAAA,IACA,QAAA,EAAU,aAAA,CAAc,QAAA,EAAU,QAAQ,CAAA;AAAA,IAC1C,UAAU,EAAC;AAAA,IACX,MAAM,EAAC;AAAA,IACP,SAAA,EAAW,IAAI,UAAA,CAAW,CAAC;AAAA,GAC7B;AACA,EAAA,OAAOG,gCAAa,IAAI,CAAA;AAC1B;AAEA,SAAS,SAAS,QAAA,EAA8B;AAC9C,EAAA,OAAOZ,gCAAAA,CAAc;AAAA,IACnB,YAAA,EAAc,QAAA;AAAA,IACd,OAAA,EAAS,aAAA;AAAA,IACT,eAAA,EAAiBJ;AAAA,GAClB,CAAA;AACH;AAMA,SAAS,SACP,UAAA,EAC0C;AAC1C,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,OAAO,CAAC,SAAS,KAAA,KAAU;AACzB,IAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,IAAA,EAAM,KAAK,GAAA,CAAI,GAAA,EAAK,OAAO,CAAC,CAAA;AAC/C,IAAA,IAAA,GAAO,CAAA;AACP,IAAA,UAAA,GAAa,GAAG,KAAK,CAAA;AAAA,EACvB,CAAA;AACF;;;ACtdA,IAAMiB,gBAAAA,GAAkB,GAAA;AAEjB,IAAM,mBAAN,MAA0C;AAAA,EACtC,IAAA,GAAO,qBAAA;AAAA,EACP,QAAA,GAAW,CAAA;AAAA,EAEX,OAAA,GAAU,IAAI,UAAA,EAAW;AAAA,EAElC,MAAM,SAAA,CAAU,KAAA,EAAyB,MAAA,EAA4C;AAEnF,IAAA,IAAI,gBAAA,CAAiB,IAAI,SAAA,CAAU,KAAA,CAAM,MAAM,MAAA,CAAO,IAAI,CAAC,CAAA,EAAG;AAC5D,MAAA,OAAO,IAAA,CAAK,qBAAA,CAAsB,KAAA,CAAM,IAAA,EAAM,OAAO,IAAI,CAAA;AAAA,IAC3D;AAIA,IAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,KAAA,CAAM,IAAI,CAAA;AAC5C,IAAA,IAAI,QAAQ,OAAO,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,OAAO,MAAM,CAAA;AACjE,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,qBAAA,CAAsB,SAAA,EAAmB,UAAA,EAAsC;AACnF,IAAA,MAAM,UAAA,GAAa,cAAc,SAAS,CAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,gBAAgB,UAAU,CAAA;AACzC,IAAA,IAAI,CAAC,UAAA,IAAc,CAAC,MAAA,EAAQ,OAAO,KAAA;AAGnC,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,IAAI,CAAE,MAAM,IAAA,CAAK,OAAA,CAAQ,UAAU,YAAA,CAAa,UAAU,CAAC,CAAA,EAAI,OAAO,KAAA;AAAA,IACxE;AACA,IAAA,IAAI,MAAA,CAAO,UAAU,KAAA,EAAO;AAC1B,MAAA,IAAI,CAAE,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAA,CAAU,aAAa,MAAA,CAAO,KAAK,CAAC,CAAA,EAAI,OAAO,KAAA;AAAA,IAC1E;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,mBAAA,CACJ,MAAA,EACA,KAAA,EACA,MAAA,EACkB;AAGlB,IAAA,MAAM,WAAA,GAAc,cAAA,CAAe,MAAA,CAAO,IAAI,CAAA;AAC9C,IAAA,IAAI,WAAA,IAAe,KAAA,CAAM,QAAA,KAAa,OAAA,EAAS;AAC7C,MAAA,IAAI,CAAE,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAe,qBAAA,CAAsB,MAAM,CAAC,CAAA,EAAI,OAAO,KAAA;AAChF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAe,KAAK,CAAA;AACtD,MAAA,MAAM,SAAS,MAAA,IAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAe,KAAK,CAAA;AACjE,MAAA,OAAO,MAAA,IAAU,MAAA;AAAA,IACnB;AAGA,IAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,MAAA,CAAO,IAAI,CAAA;AAC1C,IAAA,IAAI,MAAA,IAAU,MAAA,CAAO,IAAA,KAAS,KAAA,CAAM,IAAA,EAAM;AACxC,MAAA,IAAI,CAAE,MAAM,IAAA,CAAK,OAAA,CAAQ,UAAU,qBAAA,CAAsB,MAAM,CAAC,CAAA,EAAI,OAAO,KAAA;AAC3E,MAAA,IAAI,MAAA,CAAO,UAAU,KAAA,EAAO;AAC1B,QAAA,IAAI,CAAE,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAA,CAAU,aAAa,MAAA,CAAO,KAAK,CAAC,CAAA,EAAI,OAAO,KAAA;AAAA,MAC1E;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAA,CACJ,KAAA,EACA,MAAA,EACA,OAAA,EACwB;AACxB,IAAA,MAAM,OAAA,GAAU,KAAK,GAAA,EAAI;AAIzB,IAAA,IAAI,KAAA,CAAM,OAAO,eAAA,EAAiB;AAChC,MAAA,MAAM,IAAI,2BAAA,CAA4B,KAAA,CAAM,IAAA,EAAM,eAAe,CAAA;AAAA,IACnE;AAEA,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,IAAA,cAAA,CAAe,MAAM,CAAA;AAIrB,IAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,KAAA,EAAO,OAAO,CAAA;AAGjD,IAAA,MAAM,UAAA,GAAa,cAAc,SAAS,CAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,MAAA,CAAO,IAAI,CAAA;AAC1C,IAAA,IAAI,UAAA,IAAc,UAAU,gBAAA,CAAiB,GAAA,CAAI,UAAU,SAAA,EAAW,MAAA,CAAO,IAAI,CAAC,CAAA,EAAG;AACnF,MAAA,MAAM,QAAQ,IAAI,UAAA,CAAW,MAAM,KAAA,CAAM,aAAa,CAAA;AACtD,MAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,SAAA,CAAU,WAAW,UAAA,EAAY,KAAK,CAAA,EAAG,MAAA,EAAQ,OAAO,CAAA;AACvF,MAAA,OAAO,IAAA,CAAK,YAAA,CAAa,WAAA,EAAa,MAAA,EAAQ,OAAO,CAAA;AAAA,IACvD;AAGA,IAAA,MAAM,MAAA,GAAS,mBAAmB,SAAS,CAAA;AAC3C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,QAAQ,IAAI,UAAA,CAAW,MAAM,KAAA,CAAM,aAAa,CAAA;AACtD,MAAA,MAAM,WAAA,GAAc,cAAA,CAAe,MAAA,CAAO,IAAI,CAAA;AAC9C,MAAA,IAAI,WAAA,IAAe,MAAA,CAAO,QAAA,KAAa,OAAA,EAAS;AAC9C,QAAA,OAAO,KAAK,aAAA,CAAc,MAAA,EAAQ,aAAa,KAAA,EAAO,MAAA,EAAQ,SAAS,OAAO,CAAA;AAAA,MAChF;AACA,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,SAAA;AAAA,UAC7B,mBAAA,CAAoB,QAAQ,KAAK,CAAA;AAAA,UACjC,MAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,OAAO,IAAA,CAAK,YAAA,CAAa,WAAA,EAAa,MAAA,EAAQ,OAAO,CAAA;AAAA,MACvD;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,yBAAA,CAA0B,SAAA,EAAW,MAAA,CAAO,IAAI,CAAA;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAM,SAAA,CACJ,KAAA,EACA,MAAA,EACA,OAAA,EACqB;AACrB,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,IAAA,MAAM,MAAA,GAAS,CAAC,OAAA,EAAiB,KAAA,KAC/B,QAAQ,UAAA,GAAa,EAAE,OAAA,EAAS,KAAA,EAAO,CAAA;AAEzC,IAAA,MAAA,CAAO,IAAI,OAAO,CAAA;AAClB,IAAA,cAAA,CAAe,MAAM,CAAA;AAGrB,IAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,KAAA,EAAO;AAAA,MACvC,MAAA;AAAA,MACA,YAAY,CAAC,CAAA,KAAM,OAAO,EAAA,GAAK,CAAA,GAAI,IAAI,QAAQ;AAAA,KAChD,CAAA;AACD,IAAA,MAAA,CAAO,IAAI,QAAQ,CAAA;AACnB,IAAA,cAAA,CAAe,MAAM,CAAA;AAGrB,IAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAWA,gBAAAA;AACnC,IAAA,MAAM,UAAU,cAAA,CAAe,MAAA,CAAO,KAAA,EAAO,OAAA,EAAS,QAAQ,gBAAgB,CAAA;AAC9E,IAAA,MAAM,SAAA,GAA2B;AAAA,MAC/B,MAAA;AAAA,MACA,YAAY,CAAC,CAAA,KAAM,OAAO,EAAA,GAAK,CAAA,GAAI,IAAI,QAAQ;AAAA,KACjD;AACA,IAAA,MAAM,WAAA,GAAc,MAAM,OAAA,CAAQ,MAAA,EAAQ,SAAS,EAAE,OAAA,IAAW,SAAS,CAAA;AACzE,IAAA,MAAA,CAAO,IAAI,KAAK,CAAA;AAChB,IAAA,cAAA,CAAe,MAAM,CAAA;AACrB,IAAA,MAAA,CAAO,KAAK,MAAM,CAAA;AAClB,IAAA,OAAO,WAAA;AAAA,EACT;AAAA,EAEA,YAAA,CAAa,WAAA,EAAyB,MAAA,EAA0B,OAAA,EAAgC;AAC9F,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAI,IAAA,CAAK,CAAC,WAAA,CAAY,MAAqB,CAAA,EAAG,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAM,CAAA;AAAA,MACzE,MAAA,EAAQ,MAAA;AAAA,MACR,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA;AAAA,MACzB,SAAS,IAAA,CAAK,IAAA;AAAA,MACd,mBAAA,EAAqB;AAAA;AAAA,KACvB;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,aAAA,CACJ,MAAA,EACA,aACA,KAAA,EACA,MAAA,EACA,SACA,OAAA,EACwB;AACxB,IAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,MAAA,EAAQ,YAAY,SAAA,EAAW,KAAA,EAAO,KAAK,OAAA,EAAS;AAAA,MACtF,OAAA,EAAS,QAAQ,OAAA,IAAWA,gBAAAA;AAAA,MAC5B,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,GAAI,OAAA,CAAQ,oBAAA,GACR,EAAE,oBAAA,EAAsB,WAAW,OAAA,CAAQ,oBAAoB,CAAA,EAAE,GACjE,EAAC;AAAA,MACL,UAAA,EAAY,CAAC,OAAA,EAAS,KAAA,KAAU,QAAQ,UAAA,GAAa,EAAE,OAAA,EAAS,KAAA,EAAO;AAAA,KACxE,CAAA;AAMD,IAAA,IAAI,CAAC,OAAO,aAAA,EAAe;AACzB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN;AAAA,OAEF;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAI,IAAA,CAAK,CAAC,MAAA,CAAO,KAAA,CAAM,MAAqB,CAAA,EAAG,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAM,CAAA;AAAA,MAC1E,MAAA,EAAQ,MAAA;AAAA,MACR,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA;AAAA,MACzB,SAAS,IAAA,CAAK,IAAA;AAAA,MACd,qBAAqB,MAAA,CAAO;AAAA,KAC9B;AAAA,EACF;AACF;AAQO,SAAS,wBAAA,CACd,WAA4BC,0BAAA,EACV;AAClB,EAAA,MAAM,OAAA,GAAU,IAAI,gBAAA,EAAiB;AACrC,EAAA,QAAA,CAAS,SAAS,OAAO,CAAA;AACzB,EAAA,OAAO,OAAA;AACT;AAMA,SAAS,OAAA,CACP,MAAA,EACA,OAAA,EACA,IAAA,EACA,GAAA,EACkC;AAClC,EAAA,QAAQ,OAAO,SAAA;AAAW,IACxB,KAAK,KAAA;AACH,MAAA,OAAO,UAAU,OAAO,CAAA;AAAA,IAC1B,KAAK,KAAA;AACH,MAAA,OAAO,aAAA,CAAc,OAAA,EAAS,IAAA,EAAM,GAAG,CAAA;AAAA,IACzC,KAAK,MAAA;AACH,MAAA,OAAO,cAAA,CAAe,OAAA,EAAS,IAAA,EAAM,GAAG,CAAA;AAAA,IAC1C,KAAK,KAAA;AACH,MAAA,OAAO,SAAA,CAAU,OAAA,EAAS,IAAA,EAAM,GAAG,CAAA;AAAA,IACrC,KAAK,MAAA;AACH,MAAA,OAAO,UAAA,CAAW,OAAA,EAAS,IAAA,EAAM,GAAG,CAAA;AAAA,IACtC;AACE,MAAA,MAAM,IAAI,yBAAA,CAA0B,OAAA,EAAS,MAAA,CAAO,SAAS,CAAA;AAAA;AAEnE;AAEA,SAAS,gBAAA,CAAiB,OAAa,OAAA,EAAiC;AACtE,EAAA,IAAI,OAAA,CAAQ,gBAAgB,MAAA,EAAW;AACrC,IAAA,IAAI,OAAO,OAAA,CAAQ,WAAA,KAAgB,QAAA,EAAU;AAE3C,MAAA,IAAI,QAAQ,WAAA,CAAY,QAAA,CAAS,GAAG,CAAA,SAAU,OAAA,CAAQ,WAAA;AAAA,IACxD,CAAA,MAAO;AACL,MAAA,OAAO,QAAQ,WAAA,CAAY,IAAA;AAAA,IAC7B;AAAA,EACF;AACA,EAAA,OAAO,KAAA,CAAM,IAAA;AACf;AAGA,SAAS,aAAa,KAAA,EAAkD;AACtE,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,WACP,IAAA,EACsB;AACtB,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,IAAA;AACH,MAAA,OAAO,iBAAA;AAAA,IACT,KAAK,WAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,iBAAA;AAAA,IACT;AACE,MAAA,OAAO,eAAA;AAAA;AAEb","file":"index.cjs","sourcesContent":["/**\n * Typed error classes for @catlabtech/webcvt-transcode.\n *\n * All extend core's {@link WebcvtError} with a `TRANSCODE_`-prefixed code, so\n * callers can catch by `instanceof` or match on `.code`. Never throw a bare\n * `Error` from this package.\n */\n\nimport { WebcvtError } from '@catlabtech/webcvt-core';\n\n/**\n * Thrown when the requested conversion is not in the transcode backend's\n * capability set (off-matrix pair, or a codec whose runtime probe failed).\n * `convert()` should never be reached for an unsupported pair — `canHandle`\n * gates it — but this guards the defensive path.\n */\nexport class TranscodeUnsupportedError extends WebcvtError {\n constructor(from: string, to: string) {\n super(\n 'TRANSCODE_UNSUPPORTED',\n `Transcode backend cannot convert ${from} → ${to}. This pair is not in the v1 matrix, or the required WebCodecs decoder/encoder is unavailable in this runtime.`,\n );\n this.name = 'TranscodeUnsupportedError';\n }\n}\n\n/**\n * Thrown when the input Blob exceeds the buffer-all input cap. The whole\n * pipeline is buffer-all today (every serializer takes a complete in-memory\n * model), so a hard cap protects against OOM.\n */\nexport class TranscodeInputTooLargeError extends WebcvtError {\n constructor(size: number, max: number) {\n super(\n 'TRANSCODE_INPUT_TOO_LARGE',\n `Transcode input is ${size} bytes; maximum supported is ${max} bytes.`,\n );\n this.name = 'TranscodeInputTooLargeError';\n }\n}\n\n/** Thrown when demuxing the input container fails or yields no audio. */\nexport class TranscodeDemuxError extends WebcvtError {\n constructor(message: string, options?: ErrorOptions) {\n super('TRANSCODE_DEMUX_FAILED', `Transcode demux failed: ${message}`, options);\n this.name = 'TranscodeDemuxError';\n }\n}\n\n/** Wraps a decode/encode failure surfaced by codec-webcodecs. */\nexport class TranscodeCodecError extends WebcvtError {\n constructor(message: string, options?: ErrorOptions) {\n super('TRANSCODE_CODEC_ERROR', `Transcode codec error: ${message}`, options);\n this.name = 'TranscodeCodecError';\n }\n}\n\n/** Thrown when muxing the encoded output container fails. */\nexport class TranscodeMuxError extends WebcvtError {\n constructor(message: string, options?: ErrorOptions) {\n super('TRANSCODE_MUX_FAILED', `Transcode mux failed: ${message}`, options);\n this.name = 'TranscodeMuxError';\n }\n}\n","/**\n * Abort + pipeline-error helpers shared by the decode and encode drivers.\n */\n\nimport { TranscodeCodecError } from './errors.ts';\n\n/** Throw an `AbortError` DOMException if the signal is already aborted. */\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw createAbortError();\n}\n\n/** Construct the standard `AbortError` DOMException (matches `fetch` semantics). */\nexport function createAbortError(): DOMException {\n return new DOMException('The transcode was aborted.', 'AbortError');\n}\n\n/** True for the `AbortError` DOMException thrown on cancellation. */\nexport function isAbortError(err: unknown): boolean {\n return err instanceof DOMException && err.name === 'AbortError';\n}\n\n/**\n * Normalise an error thrown from a codec phase: abort errors pass through\n * untouched; anything else is wrapped as a {@link TranscodeCodecError} carrying\n * the phase label and original cause.\n */\nexport function asCodecError(err: unknown, phase: string): Error {\n if (isAbortError(err)) return err as DOMException;\n const message = err instanceof Error ? err.message : String(err);\n return new TranscodeCodecError(`${phase}: ${message}`, { cause: err });\n}\n","/**\n * PCM intermediate representation and the AudioData ⇄ planar-float glue.\n *\n * The pipeline normalises every decoded source to planar 32-bit float\n * ({@link DecodedAudio}) — one `Float32Array` per channel. This is the format\n * `AudioData.copyTo('f32-planar')` yields and `new AudioData({format:\n * 'f32-planar'})` accepts, so it bridges the decoder output and the encoder\n * input, and interleaves cleanly to int16 for the WAV sink.\n */\n\nimport type { WavFile } from '@catlabtech/webcvt-container-wav';\n\n/** Planar 32-bit-float PCM. `channels[c][f]` is sample `f` of channel `c`. */\nexport interface DecodedAudio {\n readonly sampleRate: number;\n readonly numberOfChannels: number;\n /** Frames (samples per channel). */\n readonly numberOfFrames: number;\n /** One `Float32Array` of length `numberOfFrames` per channel. */\n readonly channels: readonly Float32Array[];\n}\n\n// ---------------------------------------------------------------------------\n// AudioData → planar float (decode side)\n// ---------------------------------------------------------------------------\n\n/** Copy every channel of an `AudioData` out as planar `Float32Array`s. */\nexport function readAudioDataPlanes(data: AudioData): Float32Array[] {\n const frames = data.numberOfFrames;\n const planes: Float32Array[] = [];\n for (let ch = 0; ch < data.numberOfChannels; ch++) {\n const plane = new Float32Array(frames);\n data.copyTo(plane, { planeIndex: ch, format: 'f32-planar' });\n planes.push(plane);\n }\n return planes;\n}\n\n/**\n * Accumulates the planar `AudioData` chunks a decoder emits into a single\n * {@link DecodedAudio}. Channel count / sample rate are taken from the first\n * chunk seen.\n */\nexport class PlanarAccumulator {\n #perChannel: Float32Array[][] = [];\n #frames = 0;\n #numChannels = 0;\n #sampleRate = 0;\n\n add(planes: Float32Array[], sampleRate: number): void {\n if (this.#numChannels === 0) {\n this.#numChannels = planes.length;\n this.#sampleRate = sampleRate;\n this.#perChannel = planes.map(() => []);\n }\n for (let ch = 0; ch < this.#numChannels; ch++) {\n this.#perChannel[ch]?.push(planes[ch] ?? planes[0] ?? new Float32Array(0));\n }\n this.#frames += planes[0]?.length ?? 0;\n }\n\n finish(fallbackSampleRate: number, fallbackChannels: number): DecodedAudio {\n if (this.#numChannels === 0) {\n return {\n sampleRate: fallbackSampleRate,\n numberOfChannels: fallbackChannels,\n numberOfFrames: 0,\n channels: Array.from({ length: fallbackChannels }, () => new Float32Array(0)),\n };\n }\n const channels = this.#perChannel.map((chunks) => concatFloat(chunks, this.#frames));\n return {\n sampleRate: this.#sampleRate,\n numberOfChannels: this.#numChannels,\n numberOfFrames: this.#frames,\n channels,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// WAV raw PCM → planar float (wav is a pcm source; no decoder needed)\n// ---------------------------------------------------------------------------\n\nconst WAVE_FORMAT_IEEE_FLOAT = 3;\n\n/** Decode a parsed WAV's interleaved PCM into planar float. */\nexport function wavToDecoded(file: WavFile): DecodedAudio {\n const { format, audioData } = file;\n const ch = Math.max(1, format.channels);\n const bits = format.bitsPerSample;\n const bytesPerSample = bits / 8;\n const frameSize = bytesPerSample * ch;\n const frames = frameSize > 0 ? Math.floor(audioData.length / frameSize) : 0;\n const isFloat = format.audioFormat === WAVE_FORMAT_IEEE_FLOAT;\n const view = new DataView(audioData.buffer, audioData.byteOffset, audioData.byteLength);\n const channels = Array.from({ length: ch }, () => new Float32Array(frames));\n\n for (let f = 0; f < frames; f++) {\n for (let c = 0; c < ch; c++) {\n const off = f * frameSize + c * bytesPerSample;\n const target = channels[c];\n if (target) target[f] = readSample(view, off, bits, isFloat);\n }\n }\n return { sampleRate: format.sampleRate, numberOfChannels: ch, numberOfFrames: frames, channels };\n}\n\n// ---------------------------------------------------------------------------\n// Planar float → interleaved int16 (WAV sink)\n// ---------------------------------------------------------------------------\n\n/** Interleave planar float to little-endian 16-bit PCM bytes for `serializeWav`. */\nexport function interleaveInt16(decoded: DecodedAudio): Uint8Array {\n const { numberOfChannels: ch, numberOfFrames: n, channels } = decoded;\n const out = new Uint8Array(n * ch * 2);\n const view = new DataView(out.buffer);\n let pos = 0;\n for (let f = 0; f < n; f++) {\n for (let c = 0; c < ch; c++) {\n view.setInt16(pos, floatToInt16(channels[c]?.[f] ?? 0), true);\n pos += 2;\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Planar float → AudioData (encode side)\n// ---------------------------------------------------------------------------\n\n/**\n * Build an `AudioData` from a frame window of a {@link DecodedAudio}, in\n * `f32-planar` layout, for feeding an `AudioEncoder`. The encoder takes\n * ownership and closes it.\n */\nexport function buildAudioData(\n decoded: DecodedAudio,\n startFrame: number,\n frameCount: number,\n timestampUs: number,\n): AudioData {\n const ch = decoded.numberOfChannels;\n const data = new Float32Array(ch * frameCount);\n for (let c = 0; c < ch; c++) {\n const plane = decoded.channels[c];\n if (plane) data.set(plane.subarray(startFrame, startFrame + frameCount), c * frameCount);\n }\n return new AudioData({\n format: 'f32-planar',\n sampleRate: decoded.sampleRate,\n numberOfFrames: frameCount,\n numberOfChannels: ch,\n timestamp: timestampUs,\n data,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction concatFloat(chunks: Float32Array[], total: number): Float32Array {\n const out = new Float32Array(total);\n let off = 0;\n for (const c of chunks) {\n out.set(c, off);\n off += c.length;\n }\n return out;\n}\n\nfunction floatToInt16(v: number): number {\n const s = Math.round(v * 32767);\n return s < -32768 ? -32768 : s > 32767 ? 32767 : s;\n}\n\nfunction readSample(view: DataView, off: number, bits: number, isFloat: boolean): number {\n if (isFloat) {\n return bits === 64 ? view.getFloat64(off, true) : view.getFloat32(off, true);\n }\n switch (bits) {\n case 8:\n return ((view.getUint8(off) - 128) / 128) as number;\n case 16:\n return view.getInt16(off, true) / 32768;\n case 24: {\n const b0 = view.getUint8(off);\n const b1 = view.getUint8(off + 1);\n const b2 = view.getUint8(off + 2);\n let val = b0 | (b1 << 8) | (b2 << 16);\n if (val & 0x800000) val -= 0x1000000; // sign-extend 24-bit\n return val / 8388608;\n }\n case 32:\n return view.getInt32(off, true) / 2147483648;\n default:\n return 0;\n }\n}\n","/**\n * Decode driver: turn a {@link DemuxResult} into planar-float {@link DecodedAudio}.\n *\n * PCM inputs (wav) short-circuit — no WebCodecs needed. Encoded inputs feed a\n * `WebCodecsAudioDecoder` chunk-by-chunk, accumulating each emitted `AudioData`\n * and `close()`-ing it promptly. The decoder is always `close()`-d in `finally`\n * (and via an abort listener that unblocks a pending `flush()`), so no codec\n * surface leaks on error or cancellation.\n */\n\nimport { WebCodecsAudioDecoder } from '@catlabtech/webcvt-codec-webcodecs';\nimport { asCodecError, throwIfAborted } from './abort.ts';\nimport type { DemuxResult } from './demux.ts';\nimport { type DecodedAudio, PlanarAccumulator, readAudioDataPlanes } from './pcm.ts';\n\nexport interface DecodeContext {\n readonly signal?: AbortSignal;\n /** Progress callback: (framesDecoded fraction 0–1). */\n readonly onProgress?: (fraction: number) => void;\n}\n\n/** Decode a demuxed source to planar float PCM. */\nexport async function decodeToPcm(demux: DemuxResult, ctx: DecodeContext): Promise<DecodedAudio> {\n throwIfAborted(ctx.signal);\n\n if (demux.kind === 'pcm') {\n ctx.onProgress?.(1);\n return demux.decoded;\n }\n\n const { config, chunks, sampleRate, numberOfChannels } = demux;\n const acc = new PlanarAccumulator();\n\n const decoder = new WebCodecsAudioDecoder({ config }, (data) => {\n acc.add(readAudioDataPlanes(data), data.sampleRate);\n data.close();\n });\n\n const onAbort = (): void => decoder.close();\n ctx.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const total = chunks.length || 1;\n for (let i = 0; i < chunks.length; i++) {\n throwIfAborted(ctx.signal);\n const spec = chunks[i];\n if (!spec) continue;\n decoder.decode(\n new EncodedAudioChunk({\n type: spec.type,\n timestamp: spec.timestampUs,\n duration: spec.durationUs,\n data: spec.data,\n }),\n );\n ctx.onProgress?.((i + 1) / total);\n }\n await decoder.flush();\n throwIfAborted(ctx.signal);\n } catch (err) {\n throw asCodecError(err, 'decode');\n } finally {\n ctx.signal?.removeEventListener('abort', onAbort);\n decoder.close();\n }\n\n return acc.finish(sampleRate, numberOfChannels);\n}\n","/**\n * Container demux for the video stage: pull encoded video/audio tracks out of\n * mp4 / webm / mkv so they can be fed to WebCodecs decoders.\n *\n * - `demuxContainerVideo` extracts the video track (required) plus its audio\n * track (optional — `null` when the container has no audio or the audio codec\n * is not decodable here, e.g. Vorbis-in-webm → video-only output).\n * - `demuxContainerAudio` extracts JUST the audio track (for routing a\n * container's audio into the existing audio matrix, e.g. mp4/m4a AAC → wav).\n *\n * Descriptions come verbatim from the container per the design note §B:\n * mp4 avcC via `codecConfig.bytes`, mp4 AAC ASC via `decoderSpecificInfo`,\n * webm/mkv via `codecPrivate` (OpusHead / avcC / ASC). All sample/block access\n * is the containers' own zero-copy iterators.\n *\n * See docs/design-notes/transcode.md §B (demux capability audit) and §D (video).\n */\n\nimport {\n type AudioChunk as MkvAudioChunk,\n type MkvAudioTrack,\n type MkvFile,\n type VideoChunk as MkvVideoChunk,\n type MkvVideoTrack,\n iterateAudioChunks as iterateMkvAudioChunks,\n iterateVideoChunks as iterateMkvVideoChunks,\n parseMkv,\n} from '@catlabtech/webcvt-container-mkv';\nimport {\n type Mp4File,\n type Mp4Track,\n deriveCodecString,\n findAudioTrack,\n findVideoTrack,\n iterateAudioSamplesAuto,\n iterateVideoSamples,\n parseMp4,\n} from '@catlabtech/webcvt-container-mp4';\nimport {\n type AudioChunk as WebmAudioChunk,\n type WebmAudioTrack,\n type WebmFile,\n type VideoChunk as WebmVideoChunk,\n type WebmVideoTrack,\n iterateAudioChunks as iterateWebmAudioChunks,\n iterateVideoChunks as iterateWebmVideoChunks,\n parseWebm,\n} from '@catlabtech/webcvt-container-webm';\nimport type { EncodedChunkSpec } from './demux.ts';\nimport { TranscodeDemuxError } from './errors.ts';\nimport type { ContainerFamily, VideoSideCodec } from './matrix.ts';\n\nconst US_PER_SEC = 1_000_000;\n/** WebCodecs decodes/encodes Opus at 48 kHz internally regardless of container. */\nconst OPUS_RATE = 48_000;\n/** Fallback per-chunk duration when a single-chunk stream gives no delta. */\nconst NOMINAL_AUDIO_FRAME_US = 20_000; // 20 ms\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** One encoded video access unit to hand to the VideoDecoder. */\nexport interface EncodedVideoChunkSpec {\n readonly type: 'key' | 'delta';\n readonly timestampUs: number;\n readonly durationUs: number;\n readonly data: Uint8Array;\n}\n\n/** Encoded audio track ready to feed an AudioDecoder (shape of DemuxResult's `encoded`). */\nexport interface EncodedAudioTrack {\n readonly config: AudioDecoderConfig;\n readonly chunks: EncodedChunkSpec[];\n readonly sampleRate: number;\n readonly numberOfChannels: number;\n}\n\n/** Encoded video track ready to feed a VideoDecoder. */\nexport interface EncodedVideoTrack {\n readonly config: VideoDecoderConfig;\n readonly chunks: EncodedVideoChunkSpec[];\n readonly width: number;\n readonly height: number;\n /** Estimated frame rate (fps) for the encoder config; 0 when underivable. */\n readonly frameRate: number;\n /** Coarse codec token for decoder probing. */\n readonly codec: VideoSideCodec;\n}\n\nexport interface ContainerVideoDemux {\n readonly video: EncodedVideoTrack;\n /** Null → no audio track, or the audio codec is not decodable here. */\n readonly audio: EncodedAudioTrack | null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/** Demux the video track (+ optional audio) of a container. */\nexport function demuxContainerVideo(\n family: ContainerFamily,\n bytes: Uint8Array,\n): ContainerVideoDemux {\n return wrap(() => {\n switch (family) {\n case 'mp4': {\n const file = parseMp4(bytes);\n return { video: mp4Video(file), audio: mp4Audio(file) };\n }\n case 'webm': {\n const file = parseWebm(bytes);\n return { video: webmVideo(file), audio: webmAudio(file) };\n }\n case 'mkv': {\n const file = parseMkv(bytes);\n return { video: mkvVideo(file), audio: mkvAudio(file) };\n }\n }\n });\n}\n\n/** Demux JUST the audio track of a container (for the audio matrix). */\nexport function demuxContainerAudioTrack(\n family: ContainerFamily,\n bytes: Uint8Array,\n): EncodedAudioTrack {\n return wrap(() => {\n let audio: EncodedAudioTrack | null;\n switch (family) {\n case 'mp4':\n audio = mp4Audio(parseMp4(bytes));\n break;\n case 'webm':\n audio = webmAudio(parseWebm(bytes));\n break;\n case 'mkv':\n audio = mkvAudio(parseMkv(bytes));\n break;\n }\n if (!audio) {\n throw new TranscodeDemuxError(\n `${family} container has no audio track decodable here (only AAC/Opus audio is supported)`,\n );\n }\n return audio;\n });\n}\n\n// ---------------------------------------------------------------------------\n// mp4\n// ---------------------------------------------------------------------------\n\nfunction mp4Video(file: Mp4File): EncodedVideoTrack {\n const track = findVideoTrack(file);\n if (!track || track.sampleEntry.kind !== 'video') {\n throw new TranscodeDemuxError('mp4 has no video track');\n }\n const entry = track.sampleEntry.entry;\n const config: VideoDecoderConfig = {\n codec: entry.codecString,\n description: entry.codecConfig.bytes,\n codedWidth: entry.width,\n codedHeight: entry.height,\n };\n\n const chunks: EncodedVideoChunkSpec[] = [];\n for (const s of iterateVideoSamples(track, file.fileBytes)) {\n chunks.push({\n type: s.isKeyframe ? 'key' : 'delta',\n timestampUs: Math.round(s.presentationTimeUs),\n durationUs: Math.round(s.durationUs),\n data: s.data,\n });\n }\n if (chunks.length === 0) throw new TranscodeDemuxError('mp4 video track has no samples');\n\n return {\n config,\n chunks,\n width: entry.width,\n height: entry.height,\n frameRate: estimateFrameRate(chunks),\n codec: mp4VideoCodec(entry.format),\n };\n}\n\nfunction mp4Audio(file: Mp4File): EncodedAudioTrack | null {\n const track: Mp4Track | null = findAudioTrack(file);\n if (!track || track.sampleEntry.kind !== 'audio') return null;\n const entry = track.sampleEntry.entry;\n const codec = deriveCodecString(entry.objectTypeIndication, entry.decoderSpecificInfo);\n const numberOfChannels = Math.max(1, entry.channelCount);\n const sampleRate = entry.sampleRate;\n\n const chunks: EncodedChunkSpec[] = [];\n for (const s of iterateAudioSamplesAuto(file, track)) {\n chunks.push({\n type: 'key',\n timestampUs: Math.round(s.timestampUs),\n durationUs: Math.round(s.durationUs),\n data: s.data,\n });\n }\n if (chunks.length === 0) return null;\n\n return {\n config: { codec, description: entry.decoderSpecificInfo, sampleRate, numberOfChannels },\n chunks,\n sampleRate,\n numberOfChannels,\n };\n}\n\nfunction mp4VideoCodec(format: string): VideoSideCodec {\n if (format.startsWith('avc')) return 'h264';\n if (format.startsWith('hev') || format.startsWith('hvc')) return 'hevc';\n if (format === 'vp09') return 'vp9';\n if (format === 'av01') return 'av1';\n return 'h264';\n}\n\n// ---------------------------------------------------------------------------\n// webm\n// ---------------------------------------------------------------------------\n\nfunction webmVideo(file: WebmFile): EncodedVideoTrack {\n const track = file.tracks.find((t): t is WebmVideoTrack => t.trackType === 1);\n if (!track) throw new TranscodeDemuxError('webm has no video track');\n const { codec, config } = webmVideoConfig(track);\n\n const chunks = collectVideoChunks(iterateWebmVideoChunks(file, track.trackNumber));\n if (chunks.length === 0) throw new TranscodeDemuxError('webm video track has no blocks');\n\n return {\n config,\n chunks,\n width: track.pixelWidth,\n height: track.pixelHeight,\n frameRate: estimateFrameRate(chunks),\n codec,\n };\n}\n\nfunction webmVideoConfig(track: WebmVideoTrack): {\n codec: VideoSideCodec;\n config: VideoDecoderConfig;\n} {\n const base = { codedWidth: track.pixelWidth, codedHeight: track.pixelHeight };\n switch (track.codecId) {\n case 'V_VP8':\n return { codec: 'vp8', config: { codec: 'vp8', ...base } };\n case 'V_VP9':\n return { codec: 'vp9', config: { codec: 'vp09.00.10.08', ...base } };\n case 'V_AV01':\n return {\n codec: 'av1',\n config: {\n codec: 'av01.0.04M.08',\n ...(track.codecPrivate ? { description: track.codecPrivate } : {}),\n ...base,\n },\n };\n }\n}\n\nfunction webmAudio(file: WebmFile): EncodedAudioTrack | null {\n const track = file.tracks.find((t): t is WebmAudioTrack => t.trackType === 2);\n if (!track) return null;\n if (track.codecId !== 'A_OPUS') return null; // Vorbis-in-webm decode deferred.\n const numberOfChannels = Math.max(1, track.channels);\n const chunks = deriveAudioDurations(\n collectAudioChunks(iterateWebmAudioChunks(file, track.trackNumber)),\n );\n if (chunks.length === 0) return null;\n\n return {\n config: {\n codec: 'opus',\n description: track.codecPrivate,\n sampleRate: OPUS_RATE,\n numberOfChannels,\n },\n chunks,\n sampleRate: OPUS_RATE,\n numberOfChannels,\n };\n}\n\n// ---------------------------------------------------------------------------\n// mkv\n// ---------------------------------------------------------------------------\n\nfunction mkvVideo(file: MkvFile): EncodedVideoTrack {\n const track = file.tracks.find((t): t is MkvVideoTrack => t.trackType === 1);\n if (!track) throw new TranscodeDemuxError('mkv has no video track');\n const config: VideoDecoderConfig = {\n codec: track.webcodecsCodecString,\n ...(mkvNeedsDescription(track.codecId) && track.codecPrivate\n ? { description: track.codecPrivate }\n : {}),\n codedWidth: track.pixelWidth,\n codedHeight: track.pixelHeight,\n };\n\n const chunks = collectVideoChunks(iterateMkvVideoChunks(file, track.trackNumber));\n if (chunks.length === 0) throw new TranscodeDemuxError('mkv video track has no blocks');\n\n return {\n config,\n chunks,\n width: track.pixelWidth,\n height: track.pixelHeight,\n frameRate: estimateFrameRate(chunks),\n codec: mkvVideoCodec(track.codecId),\n };\n}\n\nfunction mkvAudio(file: MkvFile): EncodedAudioTrack | null {\n const track = file.tracks.find((t): t is MkvAudioTrack => t.trackType === 2);\n if (!track) return null;\n\n let config: AudioDecoderConfig;\n let sampleRate: number;\n const numberOfChannels = Math.max(1, track.channels);\n if (track.codecId === 'A_OPUS') {\n sampleRate = OPUS_RATE;\n config = { codec: 'opus', description: track.codecPrivate, sampleRate, numberOfChannels };\n } else if (track.codecId === 'A_AAC') {\n sampleRate = track.samplingFrequency;\n config = {\n codec: track.webcodecsCodecString,\n description: track.codecPrivate,\n sampleRate,\n numberOfChannels,\n };\n } else {\n return null; // Vorbis / MP3 / FLAC-in-mkv decode deferred.\n }\n\n const chunks = deriveAudioDurations(\n collectAudioChunks(iterateMkvAudioChunks(file, track.trackNumber)),\n );\n if (chunks.length === 0) return null;\n\n return { config, chunks, sampleRate, numberOfChannels };\n}\n\nfunction mkvNeedsDescription(codecId: MkvVideoTrack['codecId']): boolean {\n return codecId === 'V_MPEG4/ISO/AVC' || codecId === 'V_MPEGH/ISO/HEVC' || codecId === 'V_AV01';\n}\n\nfunction mkvVideoCodec(codecId: MkvVideoTrack['codecId']): VideoSideCodec {\n switch (codecId) {\n case 'V_MPEG4/ISO/AVC':\n return 'h264';\n case 'V_MPEGH/ISO/HEVC':\n return 'hevc';\n case 'V_VP8':\n return 'vp8';\n case 'V_VP9':\n return 'vp9';\n case 'V_AV01':\n return 'av1';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction collectVideoChunks(\n gen: Generator<WebmVideoChunk | MkvVideoChunk>,\n): EncodedVideoChunkSpec[] {\n const raw = [...gen];\n const specs: EncodedVideoChunkSpec[] = [];\n for (let i = 0; i < raw.length; i++) {\n const c = raw[i];\n if (!c) continue;\n const next = raw[i + 1];\n const durationUs = next\n ? Math.max(1, next.timestampUs - c.timestampUs)\n : (specs.at(-1)?.durationUs ?? NOMINAL_AUDIO_FRAME_US);\n specs.push({ type: c.type, timestampUs: c.timestampUs, durationUs, data: c.data });\n }\n return specs;\n}\n\nfunction collectAudioChunks(gen: Generator<WebmAudioChunk | MkvAudioChunk>): EncodedChunkSpec[] {\n return [...gen].map((c) => ({\n type: 'key' as const,\n timestampUs: c.timestampUs,\n durationUs: 0, // filled by deriveAudioDurations\n data: c.data,\n }));\n}\n\n/** Fill each audio chunk's duration from the delta to the next chunk. */\nfunction deriveAudioDurations(chunks: EncodedChunkSpec[]): EncodedChunkSpec[] {\n return chunks.map((c, i) => {\n const next = chunks[i + 1];\n const durationUs = next\n ? Math.max(1, next.timestampUs - c.timestampUs)\n : chunks[i - 1]\n ? Math.max(1, c.timestampUs - (chunks[i - 1]?.timestampUs ?? 0))\n : NOMINAL_AUDIO_FRAME_US;\n return { ...c, durationUs };\n });\n}\n\nfunction estimateFrameRate(chunks: readonly EncodedVideoChunkSpec[]): number {\n if (chunks.length < 2) return 0;\n const first = chunks[0];\n const last = chunks[chunks.length - 1];\n if (!first || !last) return 0;\n const spanUs = last.timestampUs + last.durationUs - first.timestampUs;\n if (spanUs <= 0) return 0;\n return Math.round((chunks.length / spanUs) * US_PER_SEC);\n}\n\nfunction wrap<T>(run: () => T): T {\n try {\n return run();\n } catch (err) {\n if (err instanceof TranscodeDemuxError) throw err;\n throw new TranscodeDemuxError(err instanceof Error ? err.message : String(err), { cause: err });\n }\n}\n","/**\n * Demux: parse an input container into either raw PCM (wav) or a list of\n * encoded chunks + an `AudioDecoderConfig` for the AudioDecoder.\n *\n * All audio parsers here are eager (they return `frames[]`/`packets[]`), which\n * suits the buffer-all v1. mp3 and aac carry no explicit PTS, so timestamps are\n * derived from samples-per-frame; flac uses `sampleNumber`; opus uses granule.\n *\n * See docs/design-notes/transcode.md §B (demux capability audit).\n */\n\nimport { buildAudioSpecificConfig, parseAdts } from '@catlabtech/webcvt-container-aac';\nimport {\n BLOCK_TYPE_STREAMINFO,\n type FlacStreamInfo,\n STREAMINFO_SIZE,\n encodeBlockHeader,\n encodeStreamInfo,\n parseFlac,\n} from '@catlabtech/webcvt-container-flac';\nimport { parseMp3 } from '@catlabtech/webcvt-container-mp3';\nimport { parseOgg } from '@catlabtech/webcvt-container-ogg';\nimport { parseWav } from '@catlabtech/webcvt-container-wav';\nimport { TranscodeDemuxError } from './errors.ts';\nimport type { ContainerFamily, SideCodec } from './matrix.ts';\nimport { type DecodedAudio, wavToDecoded } from './pcm.ts';\nimport { demuxContainerAudioTrack } from './video-demux.ts';\n\n/** One encoded access unit to hand to the AudioDecoder. */\nexport interface EncodedChunkSpec {\n readonly type: 'key' | 'delta';\n readonly timestampUs: number;\n readonly durationUs: number;\n readonly data: Uint8Array;\n}\n\nexport type DemuxResult =\n | { readonly kind: 'pcm'; readonly decoded: DecodedAudio }\n | {\n readonly kind: 'encoded';\n readonly config: AudioDecoderConfig;\n readonly chunks: EncodedChunkSpec[];\n readonly sampleRate: number;\n readonly numberOfChannels: number;\n };\n\nconst US_PER_SEC = 1_000_000;\n\n/** Demux `bytes` for the given input codec. */\nexport function demuxAudio(inputCodec: SideCodec, bytes: Uint8Array): DemuxResult {\n try {\n switch (inputCodec) {\n case 'pcm':\n return { kind: 'pcm', decoded: wavToDecoded(parseWav(bytes)) };\n case 'mp3':\n return demuxMp3(bytes);\n case 'aac':\n return demuxAac(bytes);\n case 'flac':\n return demuxFlac(bytes);\n case 'opus':\n return demuxOpus(bytes);\n default:\n throw new TranscodeDemuxError(`no demuxer for input codec \"${inputCodec}\"`);\n }\n } catch (err) {\n if (err instanceof TranscodeDemuxError) throw err;\n throw new TranscodeDemuxError(err instanceof Error ? err.message : String(err), { cause: err });\n }\n}\n\n/**\n * Demux a container's (mp4/webm/mkv) audio track into encoded chunks + an\n * `AudioDecoderConfig`, so a container's audio can be routed into the existing\n * audio matrix (e.g. mp4/m4a AAC → wav, webm/mkv Opus → opus). The heavy\n * lifting lives in {@link demuxContainerAudioTrack}; this adapts it to the\n * shared {@link DemuxResult} shape the decode driver consumes.\n */\nexport function demuxContainerAudio(family: ContainerFamily, bytes: Uint8Array): DemuxResult {\n const track = demuxContainerAudioTrack(family, bytes);\n return {\n kind: 'encoded',\n config: track.config,\n chunks: track.chunks,\n sampleRate: track.sampleRate,\n numberOfChannels: track.numberOfChannels,\n };\n}\n\n// ---------------------------------------------------------------------------\n// mp3\n// ---------------------------------------------------------------------------\n\nfunction demuxMp3(bytes: Uint8Array): DemuxResult {\n const { frames } = parseMp3(bytes);\n if (frames.length === 0) throw new TranscodeDemuxError('mp3 has no audio frames');\n const first = frames[0]?.header;\n if (!first) throw new TranscodeDemuxError('mp3 has no audio frames');\n const sampleRate = first.sampleRate;\n const numberOfChannels = first.channelMode === 'mono' ? 1 : 2;\n\n const chunks: EncodedChunkSpec[] = [];\n let sample = 0;\n for (const frame of frames) {\n const spf = frame.header.samplesPerFrame;\n chunks.push({\n type: 'key',\n timestampUs: Math.round((sample / sampleRate) * US_PER_SEC),\n durationUs: Math.round((spf / sampleRate) * US_PER_SEC),\n data: frame.data,\n });\n sample += spf;\n }\n\n return {\n kind: 'encoded',\n config: { codec: 'mp3', sampleRate, numberOfChannels },\n chunks,\n sampleRate,\n numberOfChannels,\n };\n}\n\n// ---------------------------------------------------------------------------\n// aac (ADTS)\n// ---------------------------------------------------------------------------\n\nconst AAC_SAMPLES_PER_FRAME = 1024;\n\nfunction demuxAac(bytes: Uint8Array): DemuxResult {\n const { frames } = parseAdts(bytes);\n if (frames.length === 0) throw new TranscodeDemuxError('aac has no ADTS frames');\n const header = frames[0]?.header;\n if (!header) throw new TranscodeDemuxError('aac has no ADTS frames');\n const sampleRate = header.sampleRate;\n const numberOfChannels = Math.max(1, header.channelConfiguration);\n const description = buildAudioSpecificConfig(header);\n\n const chunks: EncodedChunkSpec[] = [];\n let sample = 0;\n for (const frame of frames) {\n const headerSize = frame.header.hasCrc ? 9 : 7;\n chunks.push({\n type: 'key',\n timestampUs: Math.round((sample / sampleRate) * US_PER_SEC),\n durationUs: Math.round((AAC_SAMPLES_PER_FRAME / sampleRate) * US_PER_SEC),\n data: frame.data.subarray(headerSize), // raw AU (strip ADTS header)\n });\n sample += AAC_SAMPLES_PER_FRAME;\n }\n\n return {\n kind: 'encoded',\n config: { codec: 'mp4a.40.2', sampleRate, numberOfChannels, description },\n chunks,\n sampleRate,\n numberOfChannels,\n };\n}\n\n// ---------------------------------------------------------------------------\n// flac\n// ---------------------------------------------------------------------------\n\nfunction demuxFlac(bytes: Uint8Array): DemuxResult {\n const { streamInfo, frames } = parseFlac(bytes);\n if (frames.length === 0) throw new TranscodeDemuxError('flac has no frames');\n const sampleRate = streamInfo.sampleRate;\n const numberOfChannels = streamInfo.channels;\n const description = buildFlacDescription(streamInfo);\n\n const chunks: EncodedChunkSpec[] = [];\n for (const frame of frames) {\n chunks.push({\n type: 'key',\n timestampUs: Math.round((frame.sampleNumber / sampleRate) * US_PER_SEC),\n durationUs: Math.round((frame.blockSize / sampleRate) * US_PER_SEC),\n data: frame.data,\n });\n }\n\n return {\n kind: 'encoded',\n config: { codec: 'flac', sampleRate, numberOfChannels, description },\n chunks,\n sampleRate,\n numberOfChannels,\n };\n}\n\n/**\n * WebCodecs FLAC decoder `description`: the `fLaC` signature followed by the\n * STREAMINFO metadata block (header + 34-byte body). Reuses container-flac's\n * own STREAMINFO encoder so the bytes match the parser exactly.\n */\nfunction buildFlacDescription(info: FlacStreamInfo): Uint8Array {\n const magic = new Uint8Array([0x66, 0x4c, 0x61, 0x43]); // \"fLaC\"\n const header = encodeBlockHeader(true, BLOCK_TYPE_STREAMINFO, STREAMINFO_SIZE);\n const body = encodeStreamInfo(info);\n const out = new Uint8Array(magic.length + header.length + body.length);\n out.set(magic, 0);\n out.set(header, magic.length);\n out.set(body, magic.length + header.length);\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// opus-in-ogg\n// ---------------------------------------------------------------------------\n\nconst OPUS_RATE = 48_000;\nconst OPUS_NOMINAL_FRAME = 960; // 20 ms @ 48 kHz — fallback when granule is absent.\n\nfunction demuxOpus(bytes: Uint8Array): DemuxResult {\n const { streams } = parseOgg(bytes);\n const stream = streams[0];\n if (!stream) throw new TranscodeDemuxError('ogg has no logical stream');\n if (stream.codec !== 'opus') {\n throw new TranscodeDemuxError(\n `ogg stream codec \"${stream.codec}\" is not decodable here (only opus-in-ogg is supported)`,\n );\n }\n const numberOfChannels = Math.max(1, stream.channels);\n\n const chunks: EncodedChunkSpec[] = [];\n let sample = 0;\n for (const pkt of stream.packets) {\n // Prefer granule (48 kHz samples at packet end) to derive duration; else\n // fall back to a nominal 20 ms frame.\n let end = sample + OPUS_NOMINAL_FRAME;\n if (pkt.granulePosition >= 0n) {\n const g = Number(pkt.granulePosition);\n if (g > sample) end = g;\n }\n const durationSamples = Math.max(1, end - sample);\n chunks.push({\n type: 'key',\n timestampUs: Math.round((sample / OPUS_RATE) * US_PER_SEC),\n durationUs: Math.round((durationSamples / OPUS_RATE) * US_PER_SEC),\n data: pkt.data,\n });\n sample = end;\n }\n\n return {\n kind: 'encoded',\n config: {\n codec: 'opus',\n sampleRate: OPUS_RATE,\n numberOfChannels,\n description: stream.identification,\n },\n chunks,\n sampleRate: OPUS_RATE,\n numberOfChannels,\n };\n}\n","/**\n * Encode sinks: consume planar-float {@link DecodedAudio} and produce the\n * output container bytes.\n *\n * - **wav** — interleave to int16 → `serializeWav`. No WebCodecs.\n * - **opus-in-ogg / opus-in-webm** — `AudioEncoder{codec:'opus'}` → collect\n * `EncodedAudioChunk`s → build an `OggFile` / `WebmFile` (OpusHead as the\n * Ogg identification packet / WebM `CodecPrivate`) → serialize.\n * - **aac (ADTS)** — `AudioEncoder{codec:'mp4a.40.2', aac:{format:'adts'}}`;\n * the encoder emits ADTS-framed chunks, so concatenation is the file.\n * - **flac** — `AudioEncoder{codec:'flac'}`; the FLAC stream header arrives as\n * the first chunk's `decoderConfig.description`, frames as chunk data\n * (probe-gated, best-effort — see notes).\n *\n * Encoders take ownership of each `AudioData` and always `close()` it; the\n * encoder is `close()`-d in `finally` and via an abort listener.\n */\n\nimport { WebCodecsAudioEncoder } from '@catlabtech/webcvt-codec-webcodecs';\nimport {\n type OggFile,\n buildOpusHead,\n buildOpusTags,\n serializeOgg,\n} from '@catlabtech/webcvt-container-ogg';\nimport { type WavFile, serializeWav } from '@catlabtech/webcvt-container-wav';\nimport {\n type WebmAudioTrack,\n type WebmCluster,\n type WebmFile,\n serializeWebm,\n} from '@catlabtech/webcvt-container-webm';\nimport { asCodecError, throwIfAborted } from './abort.ts';\nimport { TranscodeCodecError } from './errors.ts';\nimport { type DecodedAudio, buildAudioData, interleaveInt16 } from './pcm.ts';\n\nexport interface EncodeContext {\n readonly signal?: AbortSignal;\n readonly onProgress?: (fraction: number) => void;\n}\n\nexport interface EncodeOptions {\n /** Encoder bitrate in bits/s (opus/aac). Omitted for lossless. */\n readonly bitrate?: number;\n}\n\n// ---------------------------------------------------------------------------\n// WAV sink (pure PCM — no WebCodecs)\n// ---------------------------------------------------------------------------\n\n/** Interleave to 16-bit PCM and serialize a canonical RIFF/WAV file. */\nexport function encodeWav(decoded: DecodedAudio): Uint8Array {\n const audioData = interleaveInt16(decoded);\n const channels = Math.max(1, decoded.numberOfChannels);\n const bitsPerSample = 16 as const;\n const blockAlign = (channels * bitsPerSample) / 8;\n const file: WavFile = {\n format: {\n audioFormat: 1,\n channels,\n sampleRate: decoded.sampleRate,\n bitsPerSample,\n blockAlign,\n byteRate: decoded.sampleRate * blockAlign,\n },\n audioData,\n };\n return serializeWav(file);\n}\n\n// ---------------------------------------------------------------------------\n// Shared AudioEncoder driver\n// ---------------------------------------------------------------------------\n\nexport interface EncodedOut {\n readonly data: Uint8Array;\n readonly timestampUs: number;\n readonly durationUs: number;\n}\n\ninterface EncodeChunksResult {\n readonly chunks: EncodedOut[];\n /** First chunk's `decoderConfig.description`, when the encoder supplies one. */\n readonly description?: Uint8Array;\n}\n\n/**\n * Feed `decoded` to an `AudioEncoder` in ~20 ms windows and collect the emitted\n * chunks (bytes + timing) plus the setup description from the first chunk.\n */\nasync function encodeAudioChunks(\n decoded: DecodedAudio,\n config: AudioEncoderConfig,\n ctx: EncodeContext,\n): Promise<EncodeChunksResult> {\n throwIfAborted(ctx.signal);\n\n const out: EncodedOut[] = [];\n let description: Uint8Array | undefined;\n\n const encoder = new WebCodecsAudioEncoder({ config }, (chunk, metadata) => {\n const bytes = new Uint8Array(chunk.byteLength);\n chunk.copyTo(bytes);\n out.push({\n data: bytes,\n timestampUs: chunk.timestamp,\n durationUs: chunk.duration ?? 0,\n });\n const desc = metadata?.decoderConfig?.description;\n if (description === undefined && desc !== undefined) {\n description = new Uint8Array(\n desc instanceof ArrayBuffer ? desc : (desc as ArrayBufferView).buffer,\n desc instanceof ArrayBuffer ? 0 : (desc as ArrayBufferView).byteOffset,\n desc instanceof ArrayBuffer ? desc.byteLength : (desc as ArrayBufferView).byteLength,\n ).slice();\n }\n });\n\n const onAbort = (): void => encoder.close();\n ctx.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const framesPerChunk = Math.max(1, Math.round(decoded.sampleRate / 50)); // 20 ms\n const total = decoded.numberOfFrames || 1;\n for (let start = 0; start < decoded.numberOfFrames; start += framesPerChunk) {\n throwIfAborted(ctx.signal);\n const count = Math.min(framesPerChunk, decoded.numberOfFrames - start);\n const timestampUs = Math.round((start / decoded.sampleRate) * 1_000_000);\n encoder.encode(buildAudioData(decoded, start, count, timestampUs));\n ctx.onProgress?.(Math.min(1, (start + count) / total));\n }\n await encoder.flush();\n throwIfAborted(ctx.signal);\n } catch (err) {\n throw asCodecError(err, 'encode');\n } finally {\n ctx.signal?.removeEventListener('abort', onAbort);\n encoder.close();\n }\n\n return { chunks: out, description };\n}\n\n// ---------------------------------------------------------------------------\n// Opus encode + mux\n// ---------------------------------------------------------------------------\n\nexport const OPUS_RATE = 48_000;\nexport const OPUS_PRE_SKIP = 3840; // libopus default pre-skip @48 kHz.\nconst OGG_SERIAL = 1;\nconst WEBM_TIMECODE_SCALE = 1_000_000; // 1 ms ticks.\nconst WEBM_CLUSTER_MAX_TICKS = 30_000; // keep per-block int16 delta well within range.\n\n/**\n * Encode planar-float PCM to Opus chunks (bytes + timing). Exported so the video\n * pipeline can reuse the exact audio-encode path for a webm/mkv Opus track.\n */\nexport function encodeOpusChunks(\n decoded: DecodedAudio,\n opts: EncodeOptions,\n ctx: EncodeContext,\n): Promise<EncodedOut[]> {\n return encodeOpus(decoded, opts, ctx);\n}\n\nasync function encodeOpus(\n decoded: DecodedAudio,\n opts: EncodeOptions,\n ctx: EncodeContext,\n): Promise<EncodedOut[]> {\n const config: AudioEncoderConfig = {\n codec: 'opus',\n sampleRate: decoded.sampleRate,\n numberOfChannels: Math.max(1, decoded.numberOfChannels),\n ...(opts.bitrate ? { bitrate: opts.bitrate } : {}),\n };\n const { chunks } = await encodeAudioChunks(decoded, config, ctx);\n return chunks;\n}\n\n/** any decodable audio → opus-in-ogg. */\nexport async function encodeOpusOgg(\n decoded: DecodedAudio,\n opts: EncodeOptions,\n ctx: EncodeContext,\n): Promise<Uint8Array> {\n const channels = Math.max(1, decoded.numberOfChannels);\n const chunks = await encodeOpus(decoded, opts, ctx);\n const identification = buildOpusHead({\n channelCount: channels,\n preSkip: OPUS_PRE_SKIP,\n inputSampleRate: decoded.sampleRate,\n });\n const comments = buildOpusTags('webcvt-transcode', [\n { key: 'ENCODER', value: 'webcvt-transcode' },\n ]);\n\n const packets = chunks.map((c) => ({\n data: c.data,\n // Opus granule = decoded 48 kHz samples (incl. pre-skip) at packet end.\n granulePosition: BigInt(\n Math.round(((c.timestampUs + c.durationUs) / 1_000_000) * OPUS_RATE) + OPUS_PRE_SKIP,\n ),\n serialNumber: OGG_SERIAL,\n }));\n\n const file: OggFile = {\n streams: [\n {\n serialNumber: OGG_SERIAL,\n codec: 'opus',\n identification,\n comments,\n setup: undefined,\n packets,\n preSkip: OPUS_PRE_SKIP,\n sampleRate: OPUS_RATE,\n channels,\n },\n ],\n };\n return serializeOgg(file);\n}\n\n/** any decodable audio → opus-in-webm. */\nexport async function encodeOpusWebm(\n decoded: DecodedAudio,\n opts: EncodeOptions,\n ctx: EncodeContext,\n): Promise<Uint8Array> {\n const channels = Math.max(1, decoded.numberOfChannels);\n const chunks = await encodeOpus(decoded, opts, ctx);\n const codecPrivate = buildOpusHead({\n channelCount: channels,\n preSkip: OPUS_PRE_SKIP,\n inputSampleRate: decoded.sampleRate,\n });\n\n // Split clusters so every SimpleBlock's timecode delta (ticks) fits int16.\n const clusters: WebmCluster[] = [];\n let current: WebmCluster | null = null;\n for (const c of chunks) {\n const tick = BigInt(Math.round(c.timestampUs / 1000)); // µs → ms ticks\n if (current === null || tick - current.timecode > BigInt(WEBM_CLUSTER_MAX_TICKS)) {\n current = { fileOffset: 0, timecode: tick, blocks: [] };\n clusters.push(current);\n }\n current.blocks.push({\n trackNumber: 1,\n timestampNs: tick * BigInt(WEBM_TIMECODE_SCALE),\n keyframe: true,\n invisible: false,\n discardable: false,\n frames: [c.data],\n });\n }\n\n const track: WebmAudioTrack = {\n trackNumber: 1,\n trackUid: 1n,\n trackType: 2,\n codecId: 'A_OPUS',\n codecPrivate,\n samplingFrequency: OPUS_RATE,\n channels,\n };\n\n const file: WebmFile = {\n ebmlHeader: {\n ebmlVersion: 1,\n ebmlReadVersion: 1,\n ebmlMaxIdLength: 4,\n ebmlMaxSizeLength: 8,\n docType: 'webm',\n docTypeVersion: 4,\n docTypeReadVersion: 2,\n },\n segmentPayloadOffset: 0, // placeholder — ignored on write.\n info: {\n timecodeScale: WEBM_TIMECODE_SCALE,\n muxingApp: 'webcvt-transcode',\n writingApp: 'webcvt-transcode',\n },\n tracks: [track],\n clusters,\n fileBytes: new Uint8Array(0), // placeholder — ignored on write.\n };\n return serializeWebm(file);\n}\n\n// ---------------------------------------------------------------------------\n// AAC (encoder-native ADTS)\n// ---------------------------------------------------------------------------\n\n/** any decodable audio → aac (ADTS). Encoder emits ADTS frames; concat = file. */\nexport async function encodeAac(\n decoded: DecodedAudio,\n opts: EncodeOptions,\n ctx: EncodeContext,\n): Promise<Uint8Array> {\n const config = {\n codec: 'mp4a.40.2',\n sampleRate: decoded.sampleRate,\n numberOfChannels: Math.max(1, decoded.numberOfChannels),\n ...(opts.bitrate ? { bitrate: opts.bitrate } : {}),\n // Ask the encoder for self-framed ADTS output so concatenation is a valid\n // .aac file (no container muxer needed).\n aac: { format: 'adts' as const },\n } as AudioEncoderConfig;\n\n const { chunks } = await encodeAudioChunks(decoded, config, ctx);\n return concatBytes(chunks.map((c) => c.data));\n}\n\n// ---------------------------------------------------------------------------\n// FLAC (probe-gated, best-effort)\n// ---------------------------------------------------------------------------\n\n/**\n * any decodable audio → flac. The WebCodecs FLAC encoder delivers the stream\n * header (`fLaC` + STREAMINFO) via the first chunk's `decoderConfig.description`\n * and the FLAC frames as chunk data, so the file is `description ++ frames`.\n *\n * This path is gated by the encoder probe in `canHandle`; if FLAC encode is\n * unsupported (most non-Chromium runtimes) routing falls through to ffmpeg-wasm\n * and this is never reached. The exact chunk→frame mapping is unverified in\n * Node (no real encoder) — see docs/design-notes/transcode.md §Needs verification.\n */\nexport async function encodeFlac(\n decoded: DecodedAudio,\n _opts: EncodeOptions,\n ctx: EncodeContext,\n): Promise<Uint8Array> {\n const config: AudioEncoderConfig = {\n codec: 'flac',\n sampleRate: decoded.sampleRate,\n numberOfChannels: Math.max(1, decoded.numberOfChannels),\n };\n const { chunks, description } = await encodeAudioChunks(decoded, config, ctx);\n if (description === undefined) {\n throw new TranscodeCodecError(\n 'flac encoder did not supply a stream header (decoderConfig.description); cannot mux FLAC',\n );\n }\n return concatBytes([description, ...chunks.map((c) => c.data)]);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction concatBytes(parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((s, p) => s + p.length, 0);\n const out = new Uint8Array(total);\n let off = 0;\n for (const p of parts) {\n out.set(p, off);\n off += p.length;\n }\n return out;\n}\n","/**\n * Static v1 capability matrix + codec/bitrate resolution for the audio\n * transcode paths.\n *\n * `canHandle` is two-stage: this frozen matrix is the cheap O(1) first gate\n * (rejects off-matrix pairs like `→ mp3`/`→ mp4` and every video pair before\n * any `isConfigSupported` round-trip), and the concrete both-sided codec probe\n * is the second gate (see backend.ts). See docs/design-notes/transcode.md §D.\n */\n\n/** Codec token for a demux/mux side. `'pcm'` = raw PCM (wav), no WebCodecs. */\nexport type SideCodec = 'pcm' | 'opus' | 'aac' | 'flac' | 'mp3';\n\n/** Output container family we can mux from scratch. */\nexport type OutputContainer = 'wav' | 'ogg' | 'webm' | 'aac' | 'flac';\n\nexport interface OutputTarget {\n readonly container: OutputContainer;\n /** Codec the WebCodecs encoder must produce (`'pcm'` = interleave, no encode). */\n readonly codec: SideCodec;\n}\n\n// ---------------------------------------------------------------------------\n// Decodable audio inputs → the codec fed to the AudioDecoder (or 'pcm').\n// ---------------------------------------------------------------------------\n\n/**\n * MIME → input codec for the containers this stage can demux. `audio/ogg` is\n * assumed to carry Opus (Vorbis-in-Ogg decode needs a multi-packet setup\n * description and is deferred). mp4/m4a/webm/mkv audio-track extraction is\n * deferred to the video stage (shared demuxers).\n */\nexport const INPUT_CODECS: Readonly<Record<string, SideCodec>> = Object.freeze({\n 'audio/wav': 'pcm',\n 'audio/x-wav': 'pcm',\n 'audio/wave': 'pcm',\n 'audio/mpeg': 'mp3',\n 'audio/mp3': 'mp3',\n 'audio/x-mpeg': 'mp3',\n 'audio/aac': 'aac',\n 'audio/x-aac': 'aac',\n 'audio/ogg': 'opus',\n 'audio/opus': 'opus',\n 'audio/flac': 'flac',\n 'audio/x-flac': 'flac',\n});\n\n// ---------------------------------------------------------------------------\n// Muxable audio outputs → container + encoder codec.\n// ---------------------------------------------------------------------------\n\n/**\n * MIME → output target. `→ mp3` and `→ ogg(vorbis)` are intentionally absent\n * (no WebCodecs encoder); `→ mp4/m4a` is absent (no from-scratch mp4 muxer yet).\n */\nexport const OUTPUT_TARGETS: Readonly<Record<string, OutputTarget>> = Object.freeze({\n 'audio/wav': { container: 'wav', codec: 'pcm' },\n 'audio/x-wav': { container: 'wav', codec: 'pcm' },\n 'audio/wave': { container: 'wav', codec: 'pcm' },\n 'audio/ogg': { container: 'ogg', codec: 'opus' },\n 'audio/opus': { container: 'ogg', codec: 'opus' },\n 'audio/webm': { container: 'webm', codec: 'opus' },\n 'audio/aac': { container: 'aac', codec: 'aac' },\n 'audio/flac': { container: 'flac', codec: 'flac' },\n});\n\n/**\n * Frozen set of `\"${inputMime}|${outputMime}\"` keys — the full product of every\n * decodable input against every muxable output. This is the static gate.\n */\nexport const TRANSCODE_MATRIX: ReadonlySet<string> = Object.freeze(\n new Set<string>(\n Object.keys(INPUT_CODECS).flatMap((inMime) =>\n Object.keys(OUTPUT_TARGETS).map((outMime) => `${inMime}|${outMime}`),\n ),\n ),\n);\n\n/** Build the matrix key for a pair. */\nexport function matrixKey(inputMime: string, outputMime: string): string {\n return `${inputMime}|${outputMime}`;\n}\n\n/** Lookup the input codec for a MIME, or `undefined` if not decodable here. */\nexport function inputCodecFor(mime: string): SideCodec | undefined {\n return INPUT_CODECS[mime];\n}\n\n/** Lookup the output target for a MIME, or `undefined` if not muxable here. */\nexport function outputTargetFor(mime: string): OutputTarget | undefined {\n return OUTPUT_TARGETS[mime];\n}\n\n// ---------------------------------------------------------------------------\n// Video + container-track matrix (video stage).\n//\n// These are DELIBERATELY separate from INPUT_CODECS / OUTPUT_TARGETS /\n// TRANSCODE_MATRIX above (which stay the frozen audio-only matrix). A container\n// input (mp4/webm/mkv) is not a single audio codec — it may carry a video and\n// an audio track — so it is routed through its own lookups. `canHandle`/`convert`\n// consult BOTH the audio matrix and these container lookups.\n// ---------------------------------------------------------------------------\n\n/** Demuxable container family (its sample/block iterators feed the pipeline). */\nexport type ContainerFamily = 'mp4' | 'webm' | 'mkv';\n\n/** WebCodecs video codec token for a demux/mux side. */\nexport type VideoSideCodec = 'h264' | 'vp9' | 'vp8' | 'av1' | 'hevc';\n\n/**\n * Container input MIME → family. Covers the video containers (video/mp4,\n * video/webm, video/x-matroska) and the audio-only projections that share a\n * demuxer (audio/mp4 = m4a, audio/webm). A container input can be transcoded\n * to a video target (its video track) OR have its audio track routed into the\n * existing audio matrix. Kept out of INPUT_CODECS so `inputCodecFor('video/mp4')`\n * stays `undefined` (a container is not one audio codec).\n */\nexport const CONTAINER_INPUTS: Readonly<Record<string, ContainerFamily>> = Object.freeze({\n 'video/mp4': 'mp4',\n 'audio/mp4': 'mp4', // m4a — audio-only track extraction\n 'video/webm': 'webm',\n 'audio/webm': 'webm', // webm audio-only extraction\n 'video/x-matroska': 'mkv',\n 'video/mkv': 'mkv',\n});\n\n/** Output container family for a video target (VP9 default, VP8 fallback). */\nexport interface VideoTarget {\n readonly container: 'webm' | 'mkv';\n}\n\n/**\n * Video output MIME → container. `→ mp4` is intentionally absent (no from-scratch\n * mp4 muxer yet — deferred to a later stage). The encoder codec (VP9 preferred,\n * VP8 fallback) is resolved at convert time by probing, not fixed here.\n */\nexport const VIDEO_TARGETS: Readonly<Record<string, VideoTarget>> = Object.freeze({\n 'video/webm': { container: 'webm' },\n 'video/x-matroska': { container: 'mkv' },\n 'video/mkv': { container: 'mkv' },\n});\n\n/**\n * Assumed audio-track codec per container family, used only by `canHandle`\n * probing (the true codec is known after demux). mp4 audio is ~always AAC and\n * webm/mkv audio is ~always Opus. A mismatch (e.g. Vorbis-in-webm) is rejected\n * at demux — the same optimistic-probe contract the ogg(opus) input already uses.\n */\nexport const CONTAINER_AUDIO_CODEC: Readonly<Record<ContainerFamily, Exclude<SideCodec, 'pcm'>>> =\n Object.freeze({ mp4: 'aac', webm: 'opus', mkv: 'opus' });\n\n/** Assumed video-track codec per family, for `canHandle` decoder probing. */\nexport const CONTAINER_VIDEO_CODEC: Readonly<Record<ContainerFamily, VideoSideCodec>> =\n Object.freeze({ mp4: 'h264', webm: 'vp9', mkv: 'h264' });\n\n/** Lookup the container family for an input MIME, or `undefined`. */\nexport function containerFamilyFor(mime: string): ContainerFamily | undefined {\n return CONTAINER_INPUTS[mime];\n}\n\n/** Lookup the video output target for a MIME, or `undefined`. */\nexport function videoTargetFor(mime: string): VideoTarget | undefined {\n return VIDEO_TARGETS[mime];\n}\n\n// ---------------------------------------------------------------------------\n// Options → encoder config mapping\n// ---------------------------------------------------------------------------\n\n/** Default quality when `ConvertOptions.quality` is omitted (mid-ladder). */\nexport const DEFAULT_QUALITY = 0.7;\n\n/**\n * Buffer-all input cap. Every serializer takes a complete in-memory model, so a\n * hard cap protects against OOM. 256 MiB per the design note's conservative\n * default; revisit when a streaming muxer exists (decoded PCM expands well\n * beyond the compressed input size).\n */\nexport const MAX_INPUT_BYTES = 256 * 1024 * 1024;\n\n/**\n * Map `quality` (0–1) to a codec bitrate in bits/s. The ladder is piecewise so\n * the default `quality = 0.7` lands exactly on the mid-ladder figure from the\n * design note (Opus 128 kbps, AAC 128 kbps stereo), with q=0 and q=1 at the\n * ladder ends. Mono is scaled to ~0.6×. Lossless FLAC returns `undefined`\n * (bitrate is not applicable).\n */\nexport function resolveBitrate(\n codec: SideCodec,\n quality: number,\n channels: number,\n): number | undefined {\n const q = clamp01(quality);\n let stereo: number;\n switch (codec) {\n case 'opus':\n // 64 → 128 → 256 kbps across q 0 → 0.7 → 1.\n stereo = ladder(q, 64_000, 128_000, 256_000);\n break;\n case 'aac':\n // 96 → 128 → 256 kbps across q 0 → 0.7 → 1.\n stereo = ladder(q, 96_000, 128_000, 256_000);\n break;\n default:\n return undefined; // pcm / flac: no bitrate.\n }\n const scale = channels <= 1 ? 0.6 : 1;\n return Math.round(stereo * scale);\n}\n\n/**\n * Map video geometry + `quality` to a VP9/VP8 bitrate in bits/s. Resolution\n * drives the base (design note ladder: 720p ≈ 3 Mbps for VP9), scaled ±40% by\n * quality around the default `0.7`, with VP8 at ≈1.3× VP9. Clamped to a sane\n * floor so tiny test clips still get a positive bitrate.\n */\nexport function resolveVideoBitrate(\n width: number,\n height: number,\n quality: number,\n codec: 'vp9' | 'vp8',\n): number {\n const q = clamp01(quality);\n const pixels = Math.max(1, width) * Math.max(1, height);\n const ratio = pixels / (1280 * 720);\n const base = VP9_720P_BPS * ratio;\n const scale =\n q <= DEFAULT_QUALITY\n ? 0.6 + (0.4 * q) / DEFAULT_QUALITY // q 0 → 0.6, q 0.7 → 1.0\n : 1.0 + (0.4 * (q - DEFAULT_QUALITY)) / (1 - DEFAULT_QUALITY); // q 1 → 1.4\n const codecFactor = codec === 'vp8' ? 1.3 : 1;\n return Math.max(VIDEO_MIN_BPS, Math.round(base * scale * codecFactor));\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** VP9 base bitrate at 720p, quality 0.7. */\nconst VP9_720P_BPS = 3_000_000;\n/** Floor so tiny clips still get a positive, encodable bitrate. */\nconst VIDEO_MIN_BPS = 100_000;\n\nfunction clamp01(v: number): number {\n if (Number.isNaN(v)) return DEFAULT_QUALITY;\n return Math.max(0, Math.min(1, v));\n}\n\n/**\n * Piecewise-linear ladder through (0, lo), (0.7, mid), (1, hi). The knee at 0.7\n * makes the default quality resolve to `mid` exactly.\n */\nfunction ladder(q: number, lo: number, mid: number, hi: number): number {\n const KNEE = DEFAULT_QUALITY;\n if (q <= KNEE) return lo + ((mid - lo) * q) / KNEE;\n return mid + ((hi - mid) * (q - KNEE)) / (1 - KNEE);\n}\n","/**\n * Per-session memoisation of WebCodecs `isConfigSupported` probes.\n *\n * `canHandle` runs for every registry lookup, so an uncached backend would fire\n * an `isConfigSupported` round-trip on each call. Codec support does not change\n * within a session, so results are cached forever (keyed by codec token +\n * direction). A `WebCodecsNotSupportedError` — the signal for a runtime with no\n * WebCodecs (Node, Safari < 26 for audio) — is caught and cached as `false`, so\n * the backend falls through to ffmpeg-wasm cleanly instead of throwing.\n */\n\nimport {\n type AudioCodecName,\n type ProbeResult,\n type VideoCodecName,\n WebCodecsNotSupportedError,\n probeAudioCodec,\n probeAudioDecoder,\n probeVideoCodec,\n probeVideoDecoder,\n} from '@catlabtech/webcvt-codec-webcodecs';\n\nexport interface ProbeHints {\n readonly sampleRate?: number;\n readonly numberOfChannels?: number;\n}\n\nexport interface VideoProbeHints {\n readonly width?: number;\n readonly height?: number;\n readonly bitrate?: number;\n readonly framerate?: number;\n readonly hardwareAcceleration?: HardwareAcceleration;\n}\n\n/**\n * Caches audio decode/encode capability probes for one backend instance\n * (== one session). Not shared across instances so tests stay isolated.\n */\nexport class ProbeCache {\n readonly #decode = new Map<string, boolean>();\n readonly #encode = new Map<string, boolean>();\n readonly #videoDecode = new Map<string, boolean>();\n readonly #videoEncode = new Map<string, ProbeResult | null>();\n\n /** True iff the current runtime can DECODE `codec`. Memoised. */\n async canDecode(codec: AudioCodecName, hints: ProbeHints = {}): Promise<boolean> {\n const cached = this.#decode.get(codec);\n if (cached !== undefined) return cached;\n const ok = await probeSafely(() => probeAudioDecoder({ codec, ...hints }));\n this.#decode.set(codec, ok);\n return ok;\n }\n\n /** True iff the current runtime can ENCODE `codec` (probeAudioCodec). Memoised. */\n async canEncode(codec: AudioCodecName, hints: ProbeHints = {}): Promise<boolean> {\n const cached = this.#encode.get(codec);\n if (cached !== undefined) return cached;\n const ok = await probeSafely(() => probeAudioCodec({ codec, ...hints }));\n this.#encode.set(codec, ok);\n return ok;\n }\n\n /** True iff the current runtime can DECODE video `codec`. Memoised. */\n async canDecodeVideo(codec: VideoCodecName): Promise<boolean> {\n const cached = this.#videoDecode.get(codec);\n if (cached !== undefined) return cached;\n const ok = await probeSafely(() => probeVideoDecoder({ codec }));\n this.#videoDecode.set(codec, ok);\n return ok;\n }\n\n /**\n * Full encode probe for a video `codec` at the given geometry — returns the\n * {@link ProbeResult} (with `hardwareAccelerated`) or `null` when unsupported\n * / no WebCodecs. Memoised by codec + geometry so `canHandle` (default dims)\n * and the pipeline (real dims) each cache their own lookup.\n */\n async probeEncodeVideo(\n codec: VideoCodecName,\n hints: VideoProbeHints = {},\n ): Promise<ProbeResult | null> {\n const key = `${codec}:${hints.width ?? 0}x${hints.height ?? 0}`;\n const cached = this.#videoEncode.get(key);\n if (cached !== undefined) return cached;\n let result: ProbeResult | null;\n try {\n const r = await probeVideoCodec({ codec, ...hints });\n result = r.supported ? r : null;\n } catch (err) {\n if (err instanceof WebCodecsNotSupportedError) result = null;\n else throw err;\n }\n this.#videoEncode.set(key, result);\n return result;\n }\n\n /** True iff the current runtime can ENCODE video `codec`. Memoised. */\n async canEncodeVideo(codec: VideoCodecName, hints: VideoProbeHints = {}): Promise<boolean> {\n return (await this.probeEncodeVideo(codec, hints)) !== null;\n }\n}\n\nasync function probeSafely(run: () => Promise<{ supported: boolean }>): Promise<boolean> {\n try {\n const result = await run();\n return result.supported;\n } catch (err) {\n if (err instanceof WebCodecsNotSupportedError) return false;\n throw err;\n }\n}\n","/**\n * Video transcode pipeline: mp4/webm/mkv → webm/mkv (VP9|VP8 + Opus).\n *\n * Flow: demux both tracks → decode H.264/VP8/VP9 video to `VideoFrame`s and feed\n * them straight into a VP9 (fallback VP8) `VideoEncoder`, closing every frame the\n * moment it is handed off (the wrapper's `finally` closes it — VideoFrames leak\n * GPU surfaces otherwise). If the source carries audio AND both the audio decoder\n * and the Opus encoder probe as supported, the audio track is decoded to PCM and\n * re-encoded to Opus (reusing the audio stage); otherwise a **video-only** webm/mkv\n * is emitted (Safari-style video-only WebCodecs) and surfaced via\n * {@link VideoTranscodeResult.audioIncluded}.\n *\n * The muxer is buffer-all: encoded chunks accumulate into a model, then one\n * `serializeWebm`/`serializeMkv` call. Clusters split on video keyframes and\n * whenever a per-block tick delta would approach the int16 SimpleBlock limit.\n *\n * See docs/design-notes/transcode.md §D (category 1, flagship) and §E.\n */\n\nimport { WebCodecsVideoDecoder, WebCodecsVideoEncoder } from '@catlabtech/webcvt-codec-webcodecs';\nimport {\n type MkvAudioTrack,\n type MkvCluster,\n type MkvFile,\n type MkvVideoTrack,\n serializeMkv,\n} from '@catlabtech/webcvt-container-mkv';\nimport { buildOpusHead } from '@catlabtech/webcvt-container-ogg';\nimport {\n type WebmAudioTrack,\n type WebmCluster,\n type WebmFile,\n type WebmVideoTrack,\n serializeWebm,\n} from '@catlabtech/webcvt-container-webm';\nimport { asCodecError, throwIfAborted } from './abort.ts';\nimport { decodeToPcm } from './decode.ts';\nimport { type EncodedOut, OPUS_PRE_SKIP, OPUS_RATE, encodeOpusChunks } from './encode.ts';\nimport { TranscodeCodecError } from './errors.ts';\nimport { type ContainerFamily, resolveVideoBitrate } from './matrix.ts';\nimport type { ProbeCache } from './probe-cache.ts';\nimport {\n type ContainerVideoDemux,\n type EncodedAudioTrack,\n demuxContainerVideo,\n} from './video-demux.ts';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport interface VideoTranscodeOptions {\n readonly quality: number;\n readonly signal?: AbortSignal;\n readonly hardwareAcceleration?: HardwareAcceleration;\n /** (percent 0–100, phase) — already monotone. */\n readonly onProgress?: (percent: number, phase: string) => void;\n}\n\nexport interface VideoTranscodeResult {\n readonly bytes: Uint8Array;\n readonly hardwareAccelerated: boolean;\n /** False → the source had audio we could not transcode; output is video-only. */\n readonly audioIncluded: boolean;\n}\n\nconst KEYFRAME_INTERVAL_US = 2_000_000; // request a keyframe at most every 2 s.\nconst WEBM_TIMECODE_SCALE = 1_000_000; // 1 ms ticks.\nconst CLUSTER_MAX_TICKS = 30_000; // keep every SimpleBlock delta well inside int16.\nconst VIDEO_TRACK = 1;\nconst AUDIO_TRACK = 2;\n\n/**\n * Transcode a container's video (and, when possible, audio) track to a fresh\n * webm/mkv with VP9|VP8 video + Opus audio.\n */\nexport async function transcodeVideo(\n family: ContainerFamily,\n outputContainer: 'webm' | 'mkv',\n bytes: Uint8Array,\n probes: ProbeCache,\n opts: VideoTranscodeOptions,\n): Promise<VideoTranscodeResult> {\n const { signal } = opts;\n const emit = monotone(opts.onProgress);\n\n emit(0, 'demux');\n const demux = demuxContainerVideo(family, bytes);\n emit(5, 'demux');\n throwIfAborted(signal);\n\n // Choose the video encoder: prefer VP9, fall back to VP8. Both are probed at\n // the real geometry so we also learn hardware acceleration.\n const { videoCodec, codecString, hardwareAccelerated } = await selectVideoEncoder(\n demux.video,\n probes,\n opts.hardwareAcceleration,\n );\n\n // Decide up front whether the audio track can ride along (probe-gated).\n const audioPlan = await planAudio(demux.audio, probes);\n const videoCap = audioPlan ? 60 : 90; // reserve the tail for audio when present.\n\n emit(5, 'decode');\n const videoOut = await encodeVideoTrack(demux, videoCodec, codecString, {\n signal,\n hardwareAcceleration: opts.hardwareAcceleration,\n quality: opts.quality,\n onEncoded: (fraction) => emit(5 + fraction * (videoCap - 5), 'encode'),\n });\n throwIfAborted(signal);\n\n // Audio sub-pipeline (decode → Opus), reusing the audio stage.\n let audioOut: EncodedOut[] | null = null;\n let audioChannels = 2;\n if (audioPlan) {\n emit(videoCap, 'decode');\n const decoded = await decodeToPcm(\n {\n kind: 'encoded',\n config: audioPlan.track.config,\n chunks: audioPlan.track.chunks,\n sampleRate: audioPlan.track.sampleRate,\n numberOfChannels: audioPlan.track.numberOfChannels,\n },\n { signal, onProgress: (f) => emit(videoCap + f * 10, 'decode') },\n );\n throwIfAborted(signal);\n audioChannels = Math.max(1, decoded.numberOfChannels);\n audioOut = await encodeOpusChunks(\n decoded,\n {},\n { signal, onProgress: (f) => emit(70 + f * 20, 'encode') },\n );\n throwIfAborted(signal);\n }\n\n emit(90, 'mux');\n const outBytes =\n outputContainer === 'mkv'\n ? buildMkv(\n demux.video.width,\n demux.video.height,\n videoCodec,\n videoOut,\n audioOut,\n audioChannels,\n )\n : buildWebm(\n demux.video.width,\n demux.video.height,\n videoCodec,\n videoOut,\n audioOut,\n audioChannels,\n );\n throwIfAborted(signal);\n\n emit(100, 'done');\n return { bytes: outBytes, hardwareAccelerated, audioIncluded: audioOut !== null };\n}\n\n// ---------------------------------------------------------------------------\n// Encoder selection\n// ---------------------------------------------------------------------------\n\nasync function selectVideoEncoder(\n video: ContainerVideoDemux['video'],\n probes: ProbeCache,\n hardwareAcceleration: HardwareAcceleration | undefined,\n): Promise<{ videoCodec: 'vp9' | 'vp8'; codecString: string; hardwareAccelerated: boolean }> {\n const hints = {\n width: video.width,\n height: video.height,\n ...(hardwareAcceleration ? { hardwareAcceleration } : {}),\n };\n const vp9 = await probes.probeEncodeVideo('vp9', hints);\n if (vp9) {\n return {\n videoCodec: 'vp9',\n codecString: 'vp09.00.10.08',\n hardwareAccelerated: vp9.hardwareAccelerated,\n };\n }\n const vp8 = await probes.probeEncodeVideo('vp8', hints);\n if (vp8) {\n return { videoCodec: 'vp8', codecString: 'vp8', hardwareAccelerated: vp8.hardwareAccelerated };\n }\n throw new TranscodeCodecError('no VP9/VP8 video encoder is supported in this runtime');\n}\n\ninterface AudioPlan {\n readonly track: EncodedAudioTrack;\n}\n\nasync function planAudio(\n audio: EncodedAudioTrack | null,\n probes: ProbeCache,\n): Promise<AudioPlan | null> {\n if (!audio) return null;\n const inputCodec = audioCodecName(audio.config.codec);\n if (!inputCodec) return null;\n if (!(await probes.canDecode(inputCodec))) return null;\n if (!(await probes.canEncode('opus'))) return null;\n return { track: audio };\n}\n\nfunction audioCodecName(codec: string): 'aac' | 'opus' | 'flac' | null {\n if (codec === 'opus') return 'opus';\n if (codec.startsWith('mp4a') || codec === 'aac') return 'aac';\n if (codec === 'flac') return 'flac';\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Video decode → encode\n// ---------------------------------------------------------------------------\n\ninterface VideoOut {\n readonly data: Uint8Array;\n readonly timestampUs: number;\n readonly keyframe: boolean;\n}\n\ninterface VideoEncodeCtx {\n readonly signal?: AbortSignal;\n readonly hardwareAcceleration?: HardwareAcceleration;\n readonly quality: number;\n readonly onEncoded: (fraction: number) => void;\n}\n\nasync function encodeVideoTrack(\n demux: ContainerVideoDemux,\n videoCodec: 'vp9' | 'vp8',\n codecString: string,\n ctx: VideoEncodeCtx,\n): Promise<VideoOut[]> {\n const { video } = demux;\n const { width, height } = video;\n const frameRate = video.frameRate > 0 ? video.frameRate : 30;\n const bitrate = resolveVideoBitrate(width, height, ctx.quality, videoCodec);\n const total = video.chunks.length || 1;\n\n const out: VideoOut[] = [];\n const encoder = new WebCodecsVideoEncoder(\n {\n config: {\n codec: codecString,\n width,\n height,\n bitrate,\n framerate: frameRate,\n ...(ctx.hardwareAcceleration ? { hardwareAcceleration: ctx.hardwareAcceleration } : {}),\n },\n },\n (chunk) => {\n const data = new Uint8Array(chunk.byteLength);\n chunk.copyTo(data);\n out.push({ data, timestampUs: chunk.timestamp, keyframe: chunk.type === 'key' });\n ctx.onEncoded(Math.min(1, out.length / total));\n },\n );\n\n let frameIndex = 0;\n let lastKeyframeUs = Number.NEGATIVE_INFINITY;\n const decoder = new WebCodecsVideoDecoder({ config: video.config }, (frame) => {\n // If an abort raced in (the signal listener closes the encoder mid-flush),\n // don't feed the now-closed encoder — just release the frame. The feed loop\n // then throws the AbortError on its next `throwIfAborted`.\n if (ctx.signal?.aborted) {\n frame.close();\n return;\n }\n const ts = frame.timestamp;\n const keyFrame = frameIndex === 0 || ts - lastKeyframeUs >= KEYFRAME_INTERVAL_US;\n if (keyFrame) lastKeyframeUs = ts;\n frameIndex++;\n // The encoder wrapper takes ownership and closes the frame in its finally,\n // so we never reuse it and no GPU surface leaks.\n encoder.encode(frame, { keyFrame });\n });\n\n const onAbort = (): void => {\n decoder.close();\n encoder.close();\n };\n ctx.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n for (let i = 0; i < video.chunks.length; i++) {\n throwIfAborted(ctx.signal);\n const c = video.chunks[i];\n if (!c) continue;\n decoder.decode(\n new EncodedVideoChunk({\n type: c.type,\n timestamp: c.timestampUs,\n duration: c.durationUs,\n data: c.data,\n }),\n );\n }\n await decoder.flush();\n throwIfAborted(ctx.signal);\n await encoder.flush();\n throwIfAborted(ctx.signal);\n } catch (err) {\n throw asCodecError(err, 'video');\n } finally {\n ctx.signal?.removeEventListener('abort', onAbort);\n decoder.close();\n encoder.close();\n }\n\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Mux — shared cluster builder + webm/mkv adapters\n// ---------------------------------------------------------------------------\n\ninterface OutBlock {\n readonly trackNumber: number;\n readonly timestampUs: number;\n readonly keyframe: boolean;\n readonly data: Uint8Array;\n}\n\ninterface BuiltCluster {\n readonly fileOffset: number;\n readonly timecode: bigint;\n readonly blocks: Array<{\n trackNumber: number;\n timestampNs: bigint;\n keyframe: boolean;\n invisible: boolean;\n discardable: boolean;\n frames: Uint8Array[];\n }>;\n}\n\n/**\n * Merge video + audio blocks in timestamp order and split into clusters. A new\n * cluster begins on a video keyframe or whenever the tick delta from the current\n * cluster start would approach the int16 SimpleBlock limit.\n */\nfunction buildClusters(videoOut: VideoOut[], audioOut: EncodedOut[] | null): BuiltCluster[] {\n const blocks: OutBlock[] = [];\n for (const v of videoOut) {\n blocks.push({\n trackNumber: VIDEO_TRACK,\n timestampUs: v.timestampUs,\n keyframe: v.keyframe,\n data: v.data,\n });\n }\n if (audioOut) {\n for (const a of audioOut) {\n blocks.push({\n trackNumber: AUDIO_TRACK,\n timestampUs: a.timestampUs,\n keyframe: true,\n data: a.data,\n });\n }\n }\n // Stable sort by timestamp; video (pushed first) wins ties so a cluster opens\n // on the keyframe rather than a co-timed audio block.\n blocks.sort((x, y) => x.timestampUs - y.timestampUs);\n\n const clusters: BuiltCluster[] = [];\n let current: BuiltCluster | null = null;\n for (const b of blocks) {\n const tick = BigInt(Math.round(b.timestampUs / 1000)); // µs → 1 ms ticks\n const startNew =\n current === null ||\n (b.trackNumber === VIDEO_TRACK && b.keyframe) ||\n tick - current.timecode > BigInt(CLUSTER_MAX_TICKS);\n if (startNew) {\n current = { fileOffset: 0, timecode: tick, blocks: [] };\n clusters.push(current);\n }\n current?.blocks.push({\n trackNumber: b.trackNumber,\n timestampNs: tick * BigInt(WEBM_TIMECODE_SCALE),\n keyframe: b.keyframe,\n invisible: false,\n discardable: false,\n frames: [b.data],\n });\n }\n return clusters;\n}\n\nfunction buildWebm(\n width: number,\n height: number,\n videoCodec: 'vp9' | 'vp8',\n videoOut: VideoOut[],\n audioOut: EncodedOut[] | null,\n audioChannels: number,\n): Uint8Array {\n const videoTrack: WebmVideoTrack = {\n trackNumber: VIDEO_TRACK,\n trackUid: 1n,\n trackType: 1,\n codecId: videoCodec === 'vp8' ? 'V_VP8' : 'V_VP9',\n pixelWidth: width,\n pixelHeight: height,\n };\n const tracks: WebmFile['tracks'] = [videoTrack];\n if (audioOut) {\n const audioTrack: WebmAudioTrack = {\n trackNumber: AUDIO_TRACK,\n trackUid: 2n,\n trackType: 2,\n codecId: 'A_OPUS',\n codecPrivate: opusHead(audioChannels),\n samplingFrequency: OPUS_RATE,\n channels: audioChannels,\n };\n tracks.push(audioTrack);\n }\n\n const file: WebmFile = {\n ebmlHeader: {\n ebmlVersion: 1,\n ebmlReadVersion: 1,\n ebmlMaxIdLength: 4,\n ebmlMaxSizeLength: 8,\n docType: 'webm',\n docTypeVersion: 4,\n docTypeReadVersion: 2,\n },\n segmentPayloadOffset: 0,\n info: {\n timecodeScale: WEBM_TIMECODE_SCALE,\n muxingApp: 'webcvt-transcode',\n writingApp: 'webcvt-transcode',\n },\n tracks,\n clusters: buildClusters(videoOut, audioOut) as WebmCluster[],\n fileBytes: new Uint8Array(0),\n };\n return serializeWebm(file);\n}\n\nfunction buildMkv(\n width: number,\n height: number,\n videoCodec: 'vp9' | 'vp8',\n videoOut: VideoOut[],\n audioOut: EncodedOut[] | null,\n audioChannels: number,\n): Uint8Array {\n const videoTrack: MkvVideoTrack = {\n trackNumber: VIDEO_TRACK,\n trackUid: 1n,\n trackType: 1,\n codecId: videoCodec === 'vp8' ? 'V_VP8' : 'V_VP9',\n pixelWidth: width,\n pixelHeight: height,\n webcodecsCodecString: videoCodec === 'vp8' ? 'vp8' : 'vp09.00.10.08',\n };\n const tracks: MkvFile['tracks'] = [videoTrack];\n if (audioOut) {\n const audioTrack: MkvAudioTrack = {\n trackNumber: AUDIO_TRACK,\n trackUid: 2n,\n trackType: 2,\n codecId: 'A_OPUS',\n codecPrivate: opusHead(audioChannels),\n samplingFrequency: OPUS_RATE,\n channels: audioChannels,\n webcodecsCodecString: 'opus',\n };\n tracks.push(audioTrack);\n }\n\n const file: MkvFile = {\n ebmlHeader: {\n ebmlVersion: 1,\n ebmlReadVersion: 1,\n ebmlMaxIdLength: 4,\n ebmlMaxSizeLength: 8,\n docType: 'matroska',\n docTypeVersion: 4,\n docTypeReadVersion: 2,\n },\n segmentPayloadOffset: 0,\n info: {\n timecodeScale: WEBM_TIMECODE_SCALE,\n muxingApp: 'webcvt-transcode',\n writingApp: 'webcvt-transcode',\n },\n tracks,\n clusters: buildClusters(videoOut, audioOut) as MkvCluster[],\n chapters: [],\n tags: [],\n fileBytes: new Uint8Array(0),\n };\n return serializeMkv(file);\n}\n\nfunction opusHead(channels: number): Uint8Array {\n return buildOpusHead({\n channelCount: channels,\n preSkip: OPUS_PRE_SKIP,\n inputSampleRate: OPUS_RATE,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Monotone progress\n// ---------------------------------------------------------------------------\n\nfunction monotone(\n onProgress: ((percent: number, phase: string) => void) | undefined,\n): (percent: number, phase: string) => void {\n let last = 0;\n return (percent, phase) => {\n const p = Math.max(last, Math.min(100, percent));\n last = p;\n onProgress?.(p, phase);\n };\n}\n","/**\n * TranscodeBackend — the WebCodecs-first audio transcode backend.\n *\n * `canHandle` is two-stage + cached: (1) the static {@link TRANSCODE_MATRIX}\n * gate rejects off-matrix pairs in O(1) with no probing; (2) both-sided\n * concrete codec probes (`probeAudioDecoder` for the input, `probeAudioCodec`\n * for the output) confirm the runtime actually supports the pair — this is what\n * makes Safari-audio and no-WebCodecs runtimes fall through to ffmpeg-wasm.\n * Probe results are memoised per session.\n *\n * `convert` runs the four-phase pipeline demux → decode → encode → mux, enforces\n * the input cap first, honours `options.signal`, and closes codecs on exit.\n */\n\nimport type { AudioCodecName } from '@catlabtech/webcvt-codec-webcodecs';\nimport type {\n Backend,\n BackendRegistry,\n ConvertOptions,\n ConvertResult,\n FormatDescriptor,\n} from '@catlabtech/webcvt-core';\nimport { defaultRegistry } from '@catlabtech/webcvt-core';\nimport { throwIfAborted } from './abort.ts';\nimport { decodeToPcm } from './decode.ts';\nimport { demuxAudio, demuxContainerAudio } from './demux.ts';\nimport {\n type EncodeContext,\n encodeAac,\n encodeFlac,\n encodeOpusOgg,\n encodeOpusWebm,\n encodeWav,\n} from './encode.ts';\nimport { TranscodeInputTooLargeError, TranscodeUnsupportedError } from './errors.ts';\nimport {\n CONTAINER_AUDIO_CODEC,\n CONTAINER_VIDEO_CODEC,\n type ContainerFamily,\n MAX_INPUT_BYTES,\n type OutputTarget,\n type SideCodec,\n TRANSCODE_MATRIX,\n type VideoTarget,\n containerFamilyFor,\n inputCodecFor,\n matrixKey,\n outputTargetFor,\n resolveBitrate,\n videoTargetFor,\n} from './matrix.ts';\nimport type { DecodedAudio } from './pcm.ts';\nimport { ProbeCache } from './probe-cache.ts';\nimport { transcodeVideo } from './video.ts';\n\nconst DEFAULT_QUALITY = 0.7;\n\nexport class TranscodeBackend implements Backend {\n readonly name = 'webcodecs-transcode';\n readonly priority = 0;\n\n readonly #probes = new ProbeCache();\n\n async canHandle(input: FormatDescriptor, output: FormatDescriptor): Promise<boolean> {\n // Audio-only matrix (wav/mp3/aac/flac/ogg → wav/opus/webm/aac/flac).\n if (TRANSCODE_MATRIX.has(matrixKey(input.mime, output.mime))) {\n return this.#canHandleAudioMatrix(input.mime, output.mime);\n }\n // Container inputs (mp4/m4a/webm/mkv): video transcode OR audio-track\n // extraction into the audio matrix. Kept separate so the frozen audio\n // matrix (and `inputCodecFor('video/mp4')`) stays unchanged.\n const family = containerFamilyFor(input.mime);\n if (family) return this.#canHandleContainer(family, input, output);\n return false;\n }\n\n /** Stage-2 both-sided probe for the frozen audio matrix. */\n async #canHandleAudioMatrix(inputMime: string, outputMime: string): Promise<boolean> {\n const inputCodec = inputCodecFor(inputMime);\n const target = outputTargetFor(outputMime);\n if (!inputCodec || !target) return false;\n\n // A pcm side (wav) needs no codec — skip it.\n if (inputCodec !== 'pcm') {\n if (!(await this.#probes.canDecode(asAudioCodec(inputCodec)))) return false;\n }\n if (target.codec !== 'pcm') {\n if (!(await this.#probes.canEncode(asAudioCodec(target.codec)))) return false;\n }\n return true;\n }\n\n /** Container input: gate a video-target or an audio-track-extraction pair. */\n async #canHandleContainer(\n family: ContainerFamily,\n input: FormatDescriptor,\n output: FormatDescriptor,\n ): Promise<boolean> {\n // Video output → transcode the container's video track. Requires a\n // video-bearing input (m4a / audio-only containers cannot supply video).\n const videoTarget = videoTargetFor(output.mime);\n if (videoTarget && input.category === 'video') {\n if (!(await this.#probes.canDecodeVideo(CONTAINER_VIDEO_CODEC[family]))) return false;\n const canVp9 = await this.#probes.canEncodeVideo('vp9');\n const canVp8 = canVp9 || (await this.#probes.canEncodeVideo('vp8'));\n return canVp9 || canVp8;\n }\n\n // Audio output → extract the container's audio track into the audio matrix.\n const target = outputTargetFor(output.mime);\n if (target && output.mime !== input.mime) {\n if (!(await this.#probes.canDecode(CONTAINER_AUDIO_CODEC[family]))) return false;\n if (target.codec !== 'pcm') {\n if (!(await this.#probes.canEncode(asAudioCodec(target.codec)))) return false;\n }\n return true;\n }\n return false;\n }\n\n async convert(\n input: Blob,\n output: FormatDescriptor,\n options: ConvertOptions,\n ): Promise<ConvertResult> {\n const startMs = Date.now();\n\n // Input cap FIRST — reject before touching the bytes so a hostile `.size`\n // never triggers an allocation.\n if (input.size > MAX_INPUT_BYTES) {\n throw new TranscodeInputTooLargeError(input.size, MAX_INPUT_BYTES);\n }\n\n const signal = options.signal;\n throwIfAborted(signal);\n\n // Backends dispatch on Blob.type (core re-types the blob to the resolved\n // input MIME before calling convert). Fall back to options.inputFormat.\n const inputMime = resolveInputMime(input, options);\n\n // 1. Audio-only matrix (wav/mp3/aac/flac/ogg audio).\n const inputCodec = inputCodecFor(inputMime);\n const target = outputTargetFor(output.mime);\n if (inputCodec && target && TRANSCODE_MATRIX.has(matrixKey(inputMime, output.mime))) {\n const bytes = new Uint8Array(await input.arrayBuffer());\n const outputBytes = await this.#runAudio(demuxAudio(inputCodec, bytes), target, options);\n return this.#audioResult(outputBytes, output, startMs);\n }\n\n // 2. Container inputs (mp4/m4a/webm/mkv).\n const family = containerFamilyFor(inputMime);\n if (family) {\n const bytes = new Uint8Array(await input.arrayBuffer());\n const videoTarget = videoTargetFor(output.mime);\n if (videoTarget && output.category === 'video') {\n return this.#convertVideo(family, videoTarget, bytes, output, options, startMs);\n }\n if (target) {\n const outputBytes = await this.#runAudio(\n demuxContainerAudio(family, bytes),\n target,\n options,\n );\n return this.#audioResult(outputBytes, output, startMs);\n }\n }\n\n throw new TranscodeUnsupportedError(inputMime, output.mime);\n }\n\n /** Shared audio demux→decode→encode→mux for both audio-matrix and container-audio. */\n async #runAudio(\n demux: ReturnType<typeof demuxAudio>,\n target: OutputTarget,\n options: ConvertOptions,\n ): Promise<Uint8Array> {\n const signal = options.signal;\n const report = (percent: number, phase: string): void =>\n options.onProgress?.({ percent, phase });\n\n report(10, 'demux');\n throwIfAborted(signal);\n\n // Decode (10 → 45%).\n const decoded = await decodeToPcm(demux, {\n signal,\n onProgress: (f) => report(10 + f * 35, 'decode'),\n });\n report(45, 'decode');\n throwIfAborted(signal);\n\n // Encode (45 → 90%) then mux, folded into the sink.\n const quality = options.quality ?? DEFAULT_QUALITY;\n const bitrate = resolveBitrate(target.codec, quality, decoded.numberOfChannels);\n const encodeCtx: EncodeContext = {\n signal,\n onProgress: (f) => report(45 + f * 45, 'encode'),\n };\n const outputBytes = await runSink(target, decoded, { bitrate }, encodeCtx);\n report(90, 'mux');\n throwIfAborted(signal);\n report(100, 'done');\n return outputBytes;\n }\n\n #audioResult(outputBytes: Uint8Array, output: FormatDescriptor, startMs: number): ConvertResult {\n return {\n blob: new Blob([outputBytes.buffer as ArrayBuffer], { type: output.mime }),\n format: output,\n durationMs: Date.now() - startMs,\n backend: this.name,\n hardwareAccelerated: false, // audio decode/encode is always software today.\n };\n }\n\n /** Video transcode dispatch (mp4/webm/mkv → webm/mkv, VP9|VP8 + Opus). */\n async #convertVideo(\n family: ContainerFamily,\n videoTarget: VideoTarget,\n bytes: Uint8Array,\n output: FormatDescriptor,\n options: ConvertOptions,\n startMs: number,\n ): Promise<ConvertResult> {\n const result = await transcodeVideo(family, videoTarget.container, bytes, this.#probes, {\n quality: options.quality ?? DEFAULT_QUALITY,\n signal: options.signal,\n ...(options.hardwareAcceleration\n ? { hardwareAcceleration: mapHwAccel(options.hardwareAcceleration) }\n : {}),\n onProgress: (percent, phase) => options.onProgress?.({ percent, phase }),\n });\n\n // Video-only fallback surface: when the source had audio we could not\n // transcode (Safari-style video-only WebCodecs, or a non-decodable audio\n // codec), the output is video-only. There is no ConvertResult field for\n // this by design — it is surfaced via a console warning + the docs/report.\n if (!result.audioIncluded) {\n console.warn(\n '[webcvt-transcode] emitted a VIDEO-ONLY output: the source audio track could not be ' +\n 'transcoded (no WebCodecs AudioDecoder/AudioEncoder, or an unsupported audio codec).',\n );\n }\n\n return {\n blob: new Blob([result.bytes.buffer as ArrayBuffer], { type: output.mime }),\n format: output,\n durationMs: Date.now() - startMs,\n backend: this.name,\n hardwareAccelerated: result.hardwareAccelerated,\n };\n }\n}\n\n/**\n * Construct a TranscodeBackend and register it with the given registry (or\n * core's `defaultRegistry` when omitted). Returns the backend so the caller can\n * later `registry.unregister('webcodecs-transcode')`. Nothing registers on\n * import — call this explicitly.\n */\nexport function registerTranscodeBackend(\n registry: BackendRegistry = defaultRegistry,\n): TranscodeBackend {\n const backend = new TranscodeBackend();\n registry.register(backend);\n return backend;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction runSink(\n target: OutputTarget,\n decoded: DecodedAudio,\n opts: { bitrate?: number },\n ctx: EncodeContext,\n): Promise<Uint8Array> | Uint8Array {\n switch (target.container) {\n case 'wav':\n return encodeWav(decoded);\n case 'ogg':\n return encodeOpusOgg(decoded, opts, ctx);\n case 'webm':\n return encodeOpusWebm(decoded, opts, ctx);\n case 'aac':\n return encodeAac(decoded, opts, ctx);\n case 'flac':\n return encodeFlac(decoded, opts, ctx);\n default:\n throw new TranscodeUnsupportedError('audio', target.container);\n }\n}\n\nfunction resolveInputMime(input: Blob, options: ConvertOptions): string {\n if (options.inputFormat !== undefined) {\n if (typeof options.inputFormat === 'string') {\n // Extension or MIME string — only MIME is meaningful for demuxer routing.\n if (options.inputFormat.includes('/')) return options.inputFormat;\n } else {\n return options.inputFormat.mime;\n }\n }\n return input.type;\n}\n\n/** SideCodec (non-pcm) → codec-webcodecs AudioCodecName. */\nfunction asAudioCodec(codec: Exclude<SideCodec, 'pcm'>): AudioCodecName {\n return codec;\n}\n\n/** Core's `HardwareAcceleration` hint → the WebCodecs `hardwareAcceleration` enum. */\nfunction mapHwAccel(\n pref: NonNullable<ConvertOptions['hardwareAcceleration']>,\n): HardwareAcceleration {\n switch (pref) {\n case 'no':\n return 'prefer-software';\n case 'preferred':\n case 'required':\n return 'prefer-hardware';\n default:\n return 'no-preference';\n }\n}\n"]}
@@ -0,0 +1,172 @@
1
+ import { Backend, FormatDescriptor, ConvertOptions, ConvertResult, BackendRegistry, WebcvtError } from '@catlabtech/webcvt-core';
2
+
3
+ /**
4
+ * TranscodeBackend — the WebCodecs-first audio transcode backend.
5
+ *
6
+ * `canHandle` is two-stage + cached: (1) the static {@link TRANSCODE_MATRIX}
7
+ * gate rejects off-matrix pairs in O(1) with no probing; (2) both-sided
8
+ * concrete codec probes (`probeAudioDecoder` for the input, `probeAudioCodec`
9
+ * for the output) confirm the runtime actually supports the pair — this is what
10
+ * makes Safari-audio and no-WebCodecs runtimes fall through to ffmpeg-wasm.
11
+ * Probe results are memoised per session.
12
+ *
13
+ * `convert` runs the four-phase pipeline demux → decode → encode → mux, enforces
14
+ * the input cap first, honours `options.signal`, and closes codecs on exit.
15
+ */
16
+
17
+ declare class TranscodeBackend implements Backend {
18
+ #private;
19
+ readonly name = "webcodecs-transcode";
20
+ readonly priority = 0;
21
+ canHandle(input: FormatDescriptor, output: FormatDescriptor): Promise<boolean>;
22
+ convert(input: Blob, output: FormatDescriptor, options: ConvertOptions): Promise<ConvertResult>;
23
+ }
24
+ /**
25
+ * Construct a TranscodeBackend and register it with the given registry (or
26
+ * core's `defaultRegistry` when omitted). Returns the backend so the caller can
27
+ * later `registry.unregister('webcodecs-transcode')`. Nothing registers on
28
+ * import — call this explicitly.
29
+ */
30
+ declare function registerTranscodeBackend(registry?: BackendRegistry): TranscodeBackend;
31
+
32
+ /**
33
+ * Typed error classes for @catlabtech/webcvt-transcode.
34
+ *
35
+ * All extend core's {@link WebcvtError} with a `TRANSCODE_`-prefixed code, so
36
+ * callers can catch by `instanceof` or match on `.code`. Never throw a bare
37
+ * `Error` from this package.
38
+ */
39
+
40
+ /**
41
+ * Thrown when the requested conversion is not in the transcode backend's
42
+ * capability set (off-matrix pair, or a codec whose runtime probe failed).
43
+ * `convert()` should never be reached for an unsupported pair — `canHandle`
44
+ * gates it — but this guards the defensive path.
45
+ */
46
+ declare class TranscodeUnsupportedError extends WebcvtError {
47
+ constructor(from: string, to: string);
48
+ }
49
+ /**
50
+ * Thrown when the input Blob exceeds the buffer-all input cap. The whole
51
+ * pipeline is buffer-all today (every serializer takes a complete in-memory
52
+ * model), so a hard cap protects against OOM.
53
+ */
54
+ declare class TranscodeInputTooLargeError extends WebcvtError {
55
+ constructor(size: number, max: number);
56
+ }
57
+ /** Thrown when demuxing the input container fails or yields no audio. */
58
+ declare class TranscodeDemuxError extends WebcvtError {
59
+ constructor(message: string, options?: ErrorOptions);
60
+ }
61
+ /** Wraps a decode/encode failure surfaced by codec-webcodecs. */
62
+ declare class TranscodeCodecError extends WebcvtError {
63
+ constructor(message: string, options?: ErrorOptions);
64
+ }
65
+ /** Thrown when muxing the encoded output container fails. */
66
+ declare class TranscodeMuxError extends WebcvtError {
67
+ constructor(message: string, options?: ErrorOptions);
68
+ }
69
+
70
+ /**
71
+ * Static v1 capability matrix + codec/bitrate resolution for the audio
72
+ * transcode paths.
73
+ *
74
+ * `canHandle` is two-stage: this frozen matrix is the cheap O(1) first gate
75
+ * (rejects off-matrix pairs like `→ mp3`/`→ mp4` and every video pair before
76
+ * any `isConfigSupported` round-trip), and the concrete both-sided codec probe
77
+ * is the second gate (see backend.ts). See docs/design-notes/transcode.md §D.
78
+ */
79
+ /** Codec token for a demux/mux side. `'pcm'` = raw PCM (wav), no WebCodecs. */
80
+ type SideCodec = 'pcm' | 'opus' | 'aac' | 'flac' | 'mp3';
81
+ /** Output container family we can mux from scratch. */
82
+ type OutputContainer = 'wav' | 'ogg' | 'webm' | 'aac' | 'flac';
83
+ interface OutputTarget {
84
+ readonly container: OutputContainer;
85
+ /** Codec the WebCodecs encoder must produce (`'pcm'` = interleave, no encode). */
86
+ readonly codec: SideCodec;
87
+ }
88
+ /**
89
+ * MIME → input codec for the containers this stage can demux. `audio/ogg` is
90
+ * assumed to carry Opus (Vorbis-in-Ogg decode needs a multi-packet setup
91
+ * description and is deferred). mp4/m4a/webm/mkv audio-track extraction is
92
+ * deferred to the video stage (shared demuxers).
93
+ */
94
+ declare const INPUT_CODECS: Readonly<Record<string, SideCodec>>;
95
+ /**
96
+ * MIME → output target. `→ mp3` and `→ ogg(vorbis)` are intentionally absent
97
+ * (no WebCodecs encoder); `→ mp4/m4a` is absent (no from-scratch mp4 muxer yet).
98
+ */
99
+ declare const OUTPUT_TARGETS: Readonly<Record<string, OutputTarget>>;
100
+ /**
101
+ * Frozen set of `"${inputMime}|${outputMime}"` keys — the full product of every
102
+ * decodable input against every muxable output. This is the static gate.
103
+ */
104
+ declare const TRANSCODE_MATRIX: ReadonlySet<string>;
105
+ /** Build the matrix key for a pair. */
106
+ declare function matrixKey(inputMime: string, outputMime: string): string;
107
+ /** Lookup the input codec for a MIME, or `undefined` if not decodable here. */
108
+ declare function inputCodecFor(mime: string): SideCodec | undefined;
109
+ /** Lookup the output target for a MIME, or `undefined` if not muxable here. */
110
+ declare function outputTargetFor(mime: string): OutputTarget | undefined;
111
+ /** Demuxable container family (its sample/block iterators feed the pipeline). */
112
+ type ContainerFamily = 'mp4' | 'webm' | 'mkv';
113
+ /** WebCodecs video codec token for a demux/mux side. */
114
+ type VideoSideCodec = 'h264' | 'vp9' | 'vp8' | 'av1' | 'hevc';
115
+ /**
116
+ * Container input MIME → family. Covers the video containers (video/mp4,
117
+ * video/webm, video/x-matroska) and the audio-only projections that share a
118
+ * demuxer (audio/mp4 = m4a, audio/webm). A container input can be transcoded
119
+ * to a video target (its video track) OR have its audio track routed into the
120
+ * existing audio matrix. Kept out of INPUT_CODECS so `inputCodecFor('video/mp4')`
121
+ * stays `undefined` (a container is not one audio codec).
122
+ */
123
+ declare const CONTAINER_INPUTS: Readonly<Record<string, ContainerFamily>>;
124
+ /** Output container family for a video target (VP9 default, VP8 fallback). */
125
+ interface VideoTarget {
126
+ readonly container: 'webm' | 'mkv';
127
+ }
128
+ /**
129
+ * Video output MIME → container. `→ mp4` is intentionally absent (no from-scratch
130
+ * mp4 muxer yet — deferred to a later stage). The encoder codec (VP9 preferred,
131
+ * VP8 fallback) is resolved at convert time by probing, not fixed here.
132
+ */
133
+ declare const VIDEO_TARGETS: Readonly<Record<string, VideoTarget>>;
134
+ /**
135
+ * Assumed audio-track codec per container family, used only by `canHandle`
136
+ * probing (the true codec is known after demux). mp4 audio is ~always AAC and
137
+ * webm/mkv audio is ~always Opus. A mismatch (e.g. Vorbis-in-webm) is rejected
138
+ * at demux — the same optimistic-probe contract the ogg(opus) input already uses.
139
+ */
140
+ declare const CONTAINER_AUDIO_CODEC: Readonly<Record<ContainerFamily, Exclude<SideCodec, 'pcm'>>>;
141
+ /** Assumed video-track codec per family, for `canHandle` decoder probing. */
142
+ declare const CONTAINER_VIDEO_CODEC: Readonly<Record<ContainerFamily, VideoSideCodec>>;
143
+ /** Lookup the container family for an input MIME, or `undefined`. */
144
+ declare function containerFamilyFor(mime: string): ContainerFamily | undefined;
145
+ /** Lookup the video output target for a MIME, or `undefined`. */
146
+ declare function videoTargetFor(mime: string): VideoTarget | undefined;
147
+ /** Default quality when `ConvertOptions.quality` is omitted (mid-ladder). */
148
+ declare const DEFAULT_QUALITY = 0.7;
149
+ /**
150
+ * Buffer-all input cap. Every serializer takes a complete in-memory model, so a
151
+ * hard cap protects against OOM. 256 MiB per the design note's conservative
152
+ * default; revisit when a streaming muxer exists (decoded PCM expands well
153
+ * beyond the compressed input size).
154
+ */
155
+ declare const MAX_INPUT_BYTES: number;
156
+ /**
157
+ * Map `quality` (0–1) to a codec bitrate in bits/s. The ladder is piecewise so
158
+ * the default `quality = 0.7` lands exactly on the mid-ladder figure from the
159
+ * design note (Opus 128 kbps, AAC 128 kbps stereo), with q=0 and q=1 at the
160
+ * ladder ends. Mono is scaled to ~0.6×. Lossless FLAC returns `undefined`
161
+ * (bitrate is not applicable).
162
+ */
163
+ declare function resolveBitrate(codec: SideCodec, quality: number, channels: number): number | undefined;
164
+ /**
165
+ * Map video geometry + `quality` to a VP9/VP8 bitrate in bits/s. Resolution
166
+ * drives the base (design note ladder: 720p ≈ 3 Mbps for VP9), scaled ±40% by
167
+ * quality around the default `0.7`, with VP8 at ≈1.3× VP9. Clamped to a sane
168
+ * floor so tiny test clips still get a positive bitrate.
169
+ */
170
+ declare function resolveVideoBitrate(width: number, height: number, quality: number, codec: 'vp9' | 'vp8'): number;
171
+
172
+ export { CONTAINER_AUDIO_CODEC, CONTAINER_INPUTS, CONTAINER_VIDEO_CODEC, type ContainerFamily, DEFAULT_QUALITY, INPUT_CODECS, MAX_INPUT_BYTES, OUTPUT_TARGETS, type OutputContainer, type OutputTarget, type SideCodec, TRANSCODE_MATRIX, TranscodeBackend, TranscodeCodecError, TranscodeDemuxError, TranscodeInputTooLargeError, TranscodeMuxError, TranscodeUnsupportedError, VIDEO_TARGETS, type VideoSideCodec, type VideoTarget, containerFamilyFor, inputCodecFor, matrixKey, outputTargetFor, registerTranscodeBackend, resolveBitrate, resolveVideoBitrate, videoTargetFor };