framefields 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENCE +202 -0
- package/README.md +740 -0
- package/dist/audio/index.d.mts +5 -0
- package/dist/audio/index.mjs +14 -0
- package/dist/audio-Dvwwz8xU.d.mts +37 -0
- package/dist/audio-Dvwwz8xU.d.mts.map +1 -0
- package/dist/audio-TAvPwzLR.mjs +214 -0
- package/dist/audio-TAvPwzLR.mjs.map +1 -0
- package/dist/audio-x28ZgQBP.mjs +85 -0
- package/dist/audio-x28ZgQBP.mjs.map +1 -0
- package/dist/chunk-GMkBE123.mjs +47 -0
- package/dist/client-C74hb7fy.mjs +66 -0
- package/dist/client-C74hb7fy.mjs.map +1 -0
- package/dist/dist-1iUYuPct.mjs +1859 -0
- package/dist/dist-1iUYuPct.mjs.map +1 -0
- package/dist/dist-Bx6J0VcM.mjs +1859 -0
- package/dist/dist-Bx6J0VcM.mjs.map +1 -0
- package/dist/dist-C_hjvkdN.mjs +2220 -0
- package/dist/dist-C_hjvkdN.mjs.map +1 -0
- package/dist/dist-DKm2IyEJ.mjs +94 -0
- package/dist/dist-DKm2IyEJ.mjs.map +1 -0
- package/dist/dist-cjs-B5EVqDFp.mjs +85 -0
- package/dist/dist-cjs-B5EVqDFp.mjs.map +1 -0
- package/dist/dist-cjs-BGJkdexX.mjs +437 -0
- package/dist/dist-cjs-BGJkdexX.mjs.map +1 -0
- package/dist/dist-cjs-BKmGCgtm.mjs +9069 -0
- package/dist/dist-cjs-BKmGCgtm.mjs.map +1 -0
- package/dist/dist-cjs-BUc0_kg-.mjs +1091 -0
- package/dist/dist-cjs-BUc0_kg-.mjs.map +1 -0
- package/dist/dist-cjs-BUwe2XhR.mjs +153 -0
- package/dist/dist-cjs-BUwe2XhR.mjs.map +1 -0
- package/dist/dist-cjs-BWgoUCXJ.mjs +137 -0
- package/dist/dist-cjs-BWgoUCXJ.mjs.map +1 -0
- package/dist/dist-cjs-CmZEMtO6.mjs +6 -0
- package/dist/dist-cjs-D7kEM-Mj.mjs +181 -0
- package/dist/dist-cjs-D7kEM-Mj.mjs.map +1 -0
- package/dist/dist-cjs-DFUmy89O.mjs +48 -0
- package/dist/dist-cjs-DFUmy89O.mjs.map +1 -0
- package/dist/dist-cjs-Df7144zM.mjs +209 -0
- package/dist/dist-cjs-Df7144zM.mjs.map +1 -0
- package/dist/dist-cjs-DgxjcvBN.mjs +98 -0
- package/dist/dist-cjs-DgxjcvBN.mjs.map +1 -0
- package/dist/dist-cjs-DsMdld8l.mjs +5015 -0
- package/dist/dist-cjs-DsMdld8l.mjs.map +1 -0
- package/dist/dist-cjs-Dzs5P3K0.mjs +51 -0
- package/dist/dist-cjs-Dzs5P3K0.mjs.map +1 -0
- package/dist/dist-cjs-ECMuIF57.mjs +323 -0
- package/dist/dist-cjs-ECMuIF57.mjs.map +1 -0
- package/dist/dist-cjs-lYvO8aDo.mjs +64 -0
- package/dist/dist-cjs-lYvO8aDo.mjs.map +1 -0
- package/dist/dist-cjs-qEJrwjGk.mjs +66 -0
- package/dist/dist-cjs-qEJrwjGk.mjs.map +1 -0
- package/dist/dist-cjs-x5cwlqA5.mjs +43 -0
- package/dist/dist-cjs-x5cwlqA5.mjs.map +1 -0
- package/dist/dist-gjHmorxL.mjs +27479 -0
- package/dist/dist-gjHmorxL.mjs.map +1 -0
- package/dist/effects/index.d.mts +5 -0
- package/dist/effects/index.mjs +35 -0
- package/dist/effects-CHWORCYd.mjs +811 -0
- package/dist/effects-CHWORCYd.mjs.map +1 -0
- package/dist/event-streams-D-APZ7Ke.mjs +204 -0
- package/dist/event-streams-D-APZ7Ke.mjs.map +1 -0
- package/dist/fonts/index.d.mts +2 -0
- package/dist/fonts/index.mjs +3 -0
- package/dist/fonts-DrGTBJJk.mjs +188 -0
- package/dist/fonts-DrGTBJJk.mjs.map +1 -0
- package/dist/index-B0BNPEoH.d.mts +2117 -0
- package/dist/index-B0BNPEoH.d.mts.map +1 -0
- package/dist/index-BMVVmc4G.d.mts +72 -0
- package/dist/index-BMVVmc4G.d.mts.map +1 -0
- package/dist/index-D1ZsMpke.d.mts +264 -0
- package/dist/index-D1ZsMpke.d.mts.map +1 -0
- package/dist/index-D2jDC7O5.d.mts +3643 -0
- package/dist/index-D2jDC7O5.d.mts.map +1 -0
- package/dist/index-D2wJqSl5.d.mts +114 -0
- package/dist/index-D2wJqSl5.d.mts.map +1 -0
- package/dist/index-DKFGNyMB.d.mts +309 -0
- package/dist/index-DKFGNyMB.d.mts.map +1 -0
- package/dist/index-DiSKzDGR.d.mts +65 -0
- package/dist/index-DiSKzDGR.d.mts.map +1 -0
- package/dist/index.d.mts +4425 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2623 -0
- package/dist/index.mjs.map +1 -0
- package/dist/package-C58KmGKw.mjs +6 -0
- package/dist/package-C58KmGKw.mjs.map +1 -0
- package/dist/preview/index.d.mts +90 -0
- package/dist/preview/index.d.mts.map +1 -0
- package/dist/preview/index.mjs +15 -0
- package/dist/preview-engine/audio.mjs +1 -0
- package/dist/preview-engine/child_process-AIL2NBWS.mjs +1 -0
- package/dist/preview-engine/chunk-24P6DAB3.mjs +1 -0
- package/dist/preview-engine/chunk-37EFVZWT.mjs +1 -0
- package/dist/preview-engine/chunk-3O5OKR6D.mjs +223 -0
- package/dist/preview-engine/chunk-47VT677S.mjs +8 -0
- package/dist/preview-engine/chunk-4BEJJKEU.mjs +315 -0
- package/dist/preview-engine/chunk-4GEWSUX5.mjs +1 -0
- package/dist/preview-engine/chunk-55CCFPUX.mjs +237 -0
- package/dist/preview-engine/chunk-5JD65JSJ.mjs +110 -0
- package/dist/preview-engine/chunk-5UP7FSGT.mjs +294 -0
- package/dist/preview-engine/chunk-5XDHHOF2.mjs +367 -0
- package/dist/preview-engine/chunk-6YJP57MZ.mjs +729 -0
- package/dist/preview-engine/chunk-6ZOXGAYA.mjs +112 -0
- package/dist/preview-engine/chunk-AOLAHYVV.mjs +529 -0
- package/dist/preview-engine/chunk-B6PLCMBM.mjs +1 -0
- package/dist/preview-engine/chunk-BJKH76OM.mjs +264 -0
- package/dist/preview-engine/chunk-BUIQ5TUH.mjs +104 -0
- package/dist/preview-engine/chunk-BVF64D6H.mjs +1 -0
- package/dist/preview-engine/chunk-CA5N7JRZ.mjs +138 -0
- package/dist/preview-engine/chunk-CNSHAFEA.mjs +1 -0
- package/dist/preview-engine/chunk-CURR5X7D.mjs +1 -0
- package/dist/preview-engine/chunk-CVGM2U4J.mjs +47 -0
- package/dist/preview-engine/chunk-CYY366IE.mjs +1 -0
- package/dist/preview-engine/chunk-D5PHI6ET.mjs +109 -0
- package/dist/preview-engine/chunk-D7MZHP2Y.mjs +275 -0
- package/dist/preview-engine/chunk-DPPH3NK2.mjs +182 -0
- package/dist/preview-engine/chunk-DPST2XLC.mjs +418 -0
- package/dist/preview-engine/chunk-DRLEOHN5.mjs +1 -0
- package/dist/preview-engine/chunk-EDIZNO3P.mjs +1 -0
- package/dist/preview-engine/chunk-EHIIT4ZR.mjs +52 -0
- package/dist/preview-engine/chunk-FKZ4XXPE.mjs +1 -0
- package/dist/preview-engine/chunk-G3HW4VER.mjs +60 -0
- package/dist/preview-engine/chunk-G76HSKOS.mjs +184 -0
- package/dist/preview-engine/chunk-GYG2IIBR.mjs +1 -0
- package/dist/preview-engine/chunk-H2F5NVQ6.mjs +63 -0
- package/dist/preview-engine/chunk-H5BPCY7N.mjs +188 -0
- package/dist/preview-engine/chunk-HAXK42HG.mjs +997 -0
- package/dist/preview-engine/chunk-HXMDPMLB.mjs +1 -0
- package/dist/preview-engine/chunk-HYBAPT6I.mjs +1 -0
- package/dist/preview-engine/chunk-I4FH6HYU.mjs +73 -0
- package/dist/preview-engine/chunk-IYVN2QEL.mjs +1 -0
- package/dist/preview-engine/chunk-JPXQPP6J.mjs +1 -0
- package/dist/preview-engine/chunk-JWNHTRED.mjs +164 -0
- package/dist/preview-engine/chunk-KZOLCZIV.mjs +103 -0
- package/dist/preview-engine/chunk-L62MRHGZ.mjs +89 -0
- package/dist/preview-engine/chunk-LEEZXHQO.mjs +117 -0
- package/dist/preview-engine/chunk-LKYN3BM2.mjs +1 -0
- package/dist/preview-engine/chunk-LP3EP33S.mjs +610 -0
- package/dist/preview-engine/chunk-M2GRYRLM.mjs +111 -0
- package/dist/preview-engine/chunk-MC7TZZLD.mjs +134 -0
- package/dist/preview-engine/chunk-MT2DZQHO.mjs +1 -0
- package/dist/preview-engine/chunk-MTJHQATU.mjs +1 -0
- package/dist/preview-engine/chunk-N4LHIPHZ.mjs +340 -0
- package/dist/preview-engine/chunk-N4PWLBZ7.mjs +5 -0
- package/dist/preview-engine/chunk-NQZKBFC6.mjs +40 -0
- package/dist/preview-engine/chunk-NWRSVVTF.mjs +186 -0
- package/dist/preview-engine/chunk-P3HBP725.mjs +1 -0
- package/dist/preview-engine/chunk-PIAJWALT.mjs +1 -0
- package/dist/preview-engine/chunk-PJ3DVG45.mjs +1 -0
- package/dist/preview-engine/chunk-QP2NI4XD.mjs +82 -0
- package/dist/preview-engine/chunk-SA3JUR6D.mjs +52 -0
- package/dist/preview-engine/chunk-SRT2OCQW.mjs +1 -0
- package/dist/preview-engine/chunk-SWD76532.mjs +98 -0
- package/dist/preview-engine/chunk-SXX7HX34.mjs +191 -0
- package/dist/preview-engine/chunk-SZ7YRPKO.mjs +3 -0
- package/dist/preview-engine/chunk-TMRLZV5X.mjs +1 -0
- package/dist/preview-engine/chunk-U446SQP3.mjs +292 -0
- package/dist/preview-engine/chunk-UDNCEHUI.mjs +141 -0
- package/dist/preview-engine/chunk-V3H7WWOT.mjs +271 -0
- package/dist/preview-engine/chunk-V7ZVVUQU.mjs +108 -0
- package/dist/preview-engine/chunk-VJGK7MLJ.mjs +3 -0
- package/dist/preview-engine/chunk-VSSB73UU.mjs +58 -0
- package/dist/preview-engine/chunk-VXUJWPIK.mjs +1 -0
- package/dist/preview-engine/chunk-XD4GKD6H.mjs +5 -0
- package/dist/preview-engine/chunk-XKO4RYKN.mjs +3 -0
- package/dist/preview-engine/chunk-XOEEGC4Z.mjs +1 -0
- package/dist/preview-engine/chunk-YAQFFQPG.mjs +1 -0
- package/dist/preview-engine/chunk-YKMBRUAE.mjs +1 -0
- package/dist/preview-engine/chunk-YSTLMWCG.mjs +1 -0
- package/dist/preview-engine/chunk-Z4ERCLNF.mjs +1 -0
- package/dist/preview-engine/chunk-ZEYUXJIV.mjs +1 -0
- package/dist/preview-engine/chunk-ZX6APG6E.mjs +117 -0
- package/dist/preview-engine/effects.mjs +1 -0
- package/dist/preview-engine/esbuild-GWV7CM7D.mjs +1 -0
- package/dist/preview-engine/fonts.mjs +1 -0
- package/dist/preview-engine/framefields.mjs +1959 -0
- package/dist/preview-engine/onnxruntime-node-56GSZEH3.mjs +1 -0
- package/dist/preview-engine/player.mjs +155 -0
- package/dist/preview-engine/renderers-2AUSIYZN.mjs +1 -0
- package/dist/preview-engine/renderers-2QN6KZJP.mjs +1 -0
- package/dist/preview-engine/renderers-32SKW7ML.mjs +1 -0
- package/dist/preview-engine/renderers-5QYK6766.mjs +1 -0
- package/dist/preview-engine/renderers-6BJA6MSU.mjs +251 -0
- package/dist/preview-engine/renderers-6QAF3LQ2.mjs +1 -0
- package/dist/preview-engine/renderers-7AO5746S.mjs +296 -0
- package/dist/preview-engine/renderers-AFYKNM6N.mjs +1 -0
- package/dist/preview-engine/renderers-AGMH5CRH.mjs +1 -0
- package/dist/preview-engine/renderers-AHSGP6LY.mjs +126 -0
- package/dist/preview-engine/renderers-ASTBICLA.mjs +1 -0
- package/dist/preview-engine/renderers-BHVPLYNN.mjs +1 -0
- package/dist/preview-engine/renderers-D7PVQFVU.mjs +1 -0
- package/dist/preview-engine/renderers-DB4ABTNA.mjs +1 -0
- package/dist/preview-engine/renderers-F2NFJI5L.mjs +1 -0
- package/dist/preview-engine/renderers-FI7YHNLY.mjs +1 -0
- package/dist/preview-engine/renderers-GBHULMPH.mjs +1 -0
- package/dist/preview-engine/renderers-GUKQUMGG.mjs +55 -0
- package/dist/preview-engine/renderers-HGT7QDY3.mjs +1 -0
- package/dist/preview-engine/renderers-HOYLA7ZK.mjs +1 -0
- package/dist/preview-engine/renderers-KKI2D3MZ.mjs +1 -0
- package/dist/preview-engine/renderers-KRAJNV4E.mjs +1 -0
- package/dist/preview-engine/renderers-KUGZKSVE.mjs +1 -0
- package/dist/preview-engine/renderers-L2EQQIOC.mjs +1 -0
- package/dist/preview-engine/renderers-LK3NRMGR.mjs +1 -0
- package/dist/preview-engine/renderers-LX654SZ3.mjs +1 -0
- package/dist/preview-engine/renderers-MCFQFYEL.mjs +1 -0
- package/dist/preview-engine/renderers-O6HOYIPS.mjs +1 -0
- package/dist/preview-engine/renderers-OEVXCGE2.mjs +1 -0
- package/dist/preview-engine/renderers-QVD6C4CS.mjs +1 -0
- package/dist/preview-engine/renderers-R3XEYD5V.mjs +248 -0
- package/dist/preview-engine/renderers-RBFWJWVM.mjs +1 -0
- package/dist/preview-engine/renderers-RX3VLVLO.mjs +1 -0
- package/dist/preview-engine/renderers-SM6JP64K.mjs +1 -0
- package/dist/preview-engine/renderers-TKMAATVS.mjs +1 -0
- package/dist/preview-engine/renderers-UGZUPONY.mjs +1 -0
- package/dist/preview-engine/renderers-UTFXZE3G.mjs +1 -0
- package/dist/preview-engine/renderers-UWPH7HBH.mjs +1 -0
- package/dist/preview-engine/renderers-UZGECFVO.mjs +1 -0
- package/dist/preview-engine/renderers-VGU3LNLT.mjs +1 -0
- package/dist/preview-engine/renderers-W3VVM5HB.mjs +1 -0
- package/dist/preview-engine/renderers-WJUTT5BB.mjs +1 -0
- package/dist/preview-engine/renderers-XA2M4YXK.mjs +1 -0
- package/dist/preview-engine/renderers-XIHRFEFQ.mjs +1 -0
- package/dist/preview-engine/renderers-XJTA5MFG.mjs +1 -0
- package/dist/preview-engine/renderers-XLTY5APF.mjs +1 -0
- package/dist/preview-engine/renderers-XZ3VXFGZ.mjs +1 -0
- package/dist/preview-engine/renderers-YKUQUCTO.mjs +124 -0
- package/dist/preview-engine/renderers-YVN3EIOP.mjs +1 -0
- package/dist/preview-engine/renderers-YWRP23SZ.mjs +125 -0
- package/dist/preview-engine/renderers-ZPWOUWZJ.mjs +120 -0
- package/dist/preview-engine/resvg-js-VMU4A77S.mjs +1 -0
- package/dist/preview-engine/server-utils-2FAIV45N.mjs +1 -0
- package/dist/preview-engine/sharp-V6ZTBNDW.mjs +1 -0
- package/dist/preview-engine/shims/fs-promises.mjs +1 -0
- package/dist/preview-engine/shims/fs.mjs +1 -0
- package/dist/preview-engine/shims/module.mjs +1 -0
- package/dist/preview-engine/shims/os.mjs +1 -0
- package/dist/preview-engine/shims/path.mjs +1 -0
- package/dist/preview-engine/shims/url.mjs +1 -0
- package/dist/preview-engine/signals.mjs +1 -0
- package/dist/preview-engine/webgpu-NSSANM4F.mjs +1 -0
- package/dist/preview-uQM210iy.mjs +2149 -0
- package/dist/preview-uQM210iy.mjs.map +1 -0
- package/dist/program-Dl510wmI.mjs +5183 -0
- package/dist/program-Dl510wmI.mjs.map +1 -0
- package/dist/renderer/index.d.mts +3 -0
- package/dist/renderer/index.mjs +6 -0
- package/dist/renderer-3BNskNuJ.mjs +3 -0
- package/dist/renderer-7DOcIxFG.mjs +288 -0
- package/dist/renderer-7DOcIxFG.mjs.map +1 -0
- package/dist/renderer-9dHlMQGX.mjs +3 -0
- package/dist/renderer-B1CvhW4p.mjs +677 -0
- package/dist/renderer-B1CvhW4p.mjs.map +1 -0
- package/dist/renderer-B2XzjK0z.mjs +3 -0
- package/dist/renderer-B80s47yo.mjs +166 -0
- package/dist/renderer-B80s47yo.mjs.map +1 -0
- package/dist/renderer-B9-QSJcG.mjs +479 -0
- package/dist/renderer-B9-QSJcG.mjs.map +1 -0
- package/dist/renderer-BAQmR0Zo.mjs +3 -0
- package/dist/renderer-BDLnExoP.mjs +127 -0
- package/dist/renderer-BDLnExoP.mjs.map +1 -0
- package/dist/renderer-BGXU6vcW.mjs +270 -0
- package/dist/renderer-BGXU6vcW.mjs.map +1 -0
- package/dist/renderer-BGvORwkQ.mjs +3 -0
- package/dist/renderer-BLikd6BK.mjs +3 -0
- package/dist/renderer-BMovYRoR.mjs +3 -0
- package/dist/renderer-BQHbp-Sp.mjs +243 -0
- package/dist/renderer-BQHbp-Sp.mjs.map +1 -0
- package/dist/renderer-BREIjsUU.mjs +252 -0
- package/dist/renderer-BREIjsUU.mjs.map +1 -0
- package/dist/renderer-BSbTJBWc.mjs +3 -0
- package/dist/renderer-BTu2EVhF.mjs +3 -0
- package/dist/renderer-BU1rwNRT.mjs +3 -0
- package/dist/renderer-BXMmISWG.mjs +499 -0
- package/dist/renderer-BXMmISWG.mjs.map +1 -0
- package/dist/renderer-BZJm3m4f.mjs +3 -0
- package/dist/renderer-B_NuVaIP.mjs +744 -0
- package/dist/renderer-B_NuVaIP.mjs.map +1 -0
- package/dist/renderer-BfJSUjPN.mjs +3 -0
- package/dist/renderer-BqyAgNt3.mjs +3 -0
- package/dist/renderer-BryTM2g7.mjs +3 -0
- package/dist/renderer-BsgIcBKH.mjs +391 -0
- package/dist/renderer-BsgIcBKH.mjs.map +1 -0
- package/dist/renderer-ByDhfrPE.mjs +422 -0
- package/dist/renderer-ByDhfrPE.mjs.map +1 -0
- package/dist/renderer-C-H680_l.mjs +3 -0
- package/dist/renderer-C17wL9QX.mjs +181 -0
- package/dist/renderer-C17wL9QX.mjs.map +1 -0
- package/dist/renderer-C2n-EHxg.mjs +1 -0
- package/dist/renderer-CB5aWAaf.mjs +343 -0
- package/dist/renderer-CB5aWAaf.mjs.map +1 -0
- package/dist/renderer-CB7lH5K8.mjs +3 -0
- package/dist/renderer-CDLrNgfo.mjs +3 -0
- package/dist/renderer-CDOUAN7X.mjs +454 -0
- package/dist/renderer-CDOUAN7X.mjs.map +1 -0
- package/dist/renderer-CH8sdfYX.mjs +387 -0
- package/dist/renderer-CH8sdfYX.mjs.map +1 -0
- package/dist/renderer-CIvaRnP_.mjs +261 -0
- package/dist/renderer-CIvaRnP_.mjs.map +1 -0
- package/dist/renderer-CMzEjdzi.mjs +369 -0
- package/dist/renderer-CMzEjdzi.mjs.map +1 -0
- package/dist/renderer-COkcU3db.mjs +3302 -0
- package/dist/renderer-COkcU3db.mjs.map +1 -0
- package/dist/renderer-CQCoggIa.mjs +3 -0
- package/dist/renderer-CQdVj2JS.mjs +3 -0
- package/dist/renderer-CQiTodg9.mjs +337 -0
- package/dist/renderer-CQiTodg9.mjs.map +1 -0
- package/dist/renderer-CV2m6k1V.mjs +3 -0
- package/dist/renderer-CYY-poLe.mjs +3 -0
- package/dist/renderer-CZgB5st8.mjs +3 -0
- package/dist/renderer-C_Ki91kc.mjs +3 -0
- package/dist/renderer-CclIvsLO.mjs +3 -0
- package/dist/renderer-Cj-whdVr.mjs +655 -0
- package/dist/renderer-Cj-whdVr.mjs.map +1 -0
- package/dist/renderer-CkykdR_D.mjs +3 -0
- package/dist/renderer-Cl1oUXMi.mjs +1143 -0
- package/dist/renderer-Cl1oUXMi.mjs.map +1 -0
- package/dist/renderer-CmApuKjS.mjs +3 -0
- package/dist/renderer-CpkiHRhh.mjs +269 -0
- package/dist/renderer-CpkiHRhh.mjs.map +1 -0
- package/dist/renderer-CszOjcRW.mjs +3 -0
- package/dist/renderer-CtVkU_GA.mjs +44 -0
- package/dist/renderer-CtVkU_GA.mjs.map +1 -0
- package/dist/renderer-Cu074POw.mjs +3 -0
- package/dist/renderer-CwQhzcUn.mjs +644 -0
- package/dist/renderer-CwQhzcUn.mjs.map +1 -0
- package/dist/renderer-CzPWB0Ss.mjs +273 -0
- package/dist/renderer-CzPWB0Ss.mjs.map +1 -0
- package/dist/renderer-D4qLmox-.mjs +3 -0
- package/dist/renderer-D6bWQtr-.mjs +3 -0
- package/dist/renderer-D6cJ6MSq.mjs +3 -0
- package/dist/renderer-D7EX8IjU.mjs +240 -0
- package/dist/renderer-D7EX8IjU.mjs.map +1 -0
- package/dist/renderer-DDp7_TUi.d.mts +10 -0
- package/dist/renderer-DDp7_TUi.d.mts.map +1 -0
- package/dist/renderer-DFKsLrUs.mjs +256 -0
- package/dist/renderer-DFKsLrUs.mjs.map +1 -0
- package/dist/renderer-DPSsf8-t.mjs +3 -0
- package/dist/renderer-DQLGnEFc.mjs +3 -0
- package/dist/renderer-DY2SVYUW.mjs +3 -0
- package/dist/renderer-DZGtBUCx.mjs +792 -0
- package/dist/renderer-DZGtBUCx.mjs.map +1 -0
- package/dist/renderer-DabG62XS.mjs +406 -0
- package/dist/renderer-DabG62XS.mjs.map +1 -0
- package/dist/renderer-DbaQLI4z.mjs +771 -0
- package/dist/renderer-DbaQLI4z.mjs.map +1 -0
- package/dist/renderer-DjI45OYC.mjs +71 -0
- package/dist/renderer-DjI45OYC.mjs.map +1 -0
- package/dist/renderer-Dm08-hAU.mjs +323 -0
- package/dist/renderer-Dm08-hAU.mjs.map +1 -0
- package/dist/renderer-DoAY5JbB.mjs +4 -0
- package/dist/renderer-Dp_FfvF-.mjs +401 -0
- package/dist/renderer-Dp_FfvF-.mjs.map +1 -0
- package/dist/renderer-Dt6fzgX5.mjs +756 -0
- package/dist/renderer-Dt6fzgX5.mjs.map +1 -0
- package/dist/renderer-DuplLRbp.mjs +3 -0
- package/dist/renderer-DvfUbZ31.mjs +3 -0
- package/dist/renderer-DxjVQV6f.mjs +311 -0
- package/dist/renderer-DxjVQV6f.mjs.map +1 -0
- package/dist/renderer-Fco4EmAu.mjs +23868 -0
- package/dist/renderer-Fco4EmAu.mjs.map +1 -0
- package/dist/renderer-HFfcJlmR.mjs +981 -0
- package/dist/renderer-HFfcJlmR.mjs.map +1 -0
- package/dist/renderer-I-Sw3JBB.mjs +145 -0
- package/dist/renderer-I-Sw3JBB.mjs.map +1 -0
- package/dist/renderer-OWQmmg4Z.mjs +697 -0
- package/dist/renderer-OWQmmg4Z.mjs.map +1 -0
- package/dist/renderer-Q_uUQipO.mjs +3 -0
- package/dist/renderer-Ryo2CEFD.mjs +586 -0
- package/dist/renderer-Ryo2CEFD.mjs.map +1 -0
- package/dist/renderer-Tp6OXWNZ.mjs +257 -0
- package/dist/renderer-Tp6OXWNZ.mjs.map +1 -0
- package/dist/renderer-UQFCgeNx.mjs +3 -0
- package/dist/renderer-WkVrkCVA.mjs +83 -0
- package/dist/renderer-WkVrkCVA.mjs.map +1 -0
- package/dist/renderer-XcmYTd6P.mjs +3818 -0
- package/dist/renderer-XcmYTd6P.mjs.map +1 -0
- package/dist/renderer-_uvdg48N.mjs +333 -0
- package/dist/renderer-_uvdg48N.mjs.map +1 -0
- package/dist/renderer-bZU_ndxf.mjs +8 -0
- package/dist/renderer-bZU_ndxf.mjs.map +1 -0
- package/dist/renderer-eMsnzJg9.mjs +3 -0
- package/dist/renderer-ho_jXJ0H.mjs +254 -0
- package/dist/renderer-ho_jXJ0H.mjs.map +1 -0
- package/dist/renderer-k2JL79kM.mjs +306 -0
- package/dist/renderer-k2JL79kM.mjs.map +1 -0
- package/dist/renderer-pHiz78e0.mjs +3 -0
- package/dist/renderer-pxXf9dvk.mjs +394 -0
- package/dist/renderer-pxXf9dvk.mjs.map +1 -0
- package/dist/renderer-vCFTm0oe.mjs +226 -0
- package/dist/renderer-vCFTm0oe.mjs.map +1 -0
- package/dist/renderer-vvpdx1vk.mjs +379 -0
- package/dist/renderer-vvpdx1vk.mjs.map +1 -0
- package/dist/renderer-x2s9LmVL.mjs +1121 -0
- package/dist/renderer-x2s9LmVL.mjs.map +1 -0
- package/dist/renderers-BWg16W-V-BXG_cjhM.mjs +49 -0
- package/dist/renderers-BWg16W-V-BXG_cjhM.mjs.map +1 -0
- package/dist/signals/index.d.mts +7 -0
- package/dist/signals/index.mjs +10 -0
- package/dist/signals-BwbdO3AN.mjs +224 -0
- package/dist/signals-BwbdO3AN.mjs.map +1 -0
- package/dist/signin-CZj4Oc5s.mjs +865 -0
- package/dist/signin-CZj4Oc5s.mjs.map +1 -0
- package/dist/sso-oidc-C0_31ThY.mjs +1051 -0
- package/dist/sso-oidc-C0_31ThY.mjs.map +1 -0
- package/dist/sts-DD4ggEXC.mjs +6 -0
- package/dist/sts-nXw8RDJI.mjs +1395 -0
- package/dist/sts-nXw8RDJI.mjs.map +1 -0
- package/package.json +173 -0
|
@@ -0,0 +1,1859 @@
|
|
|
1
|
+
import { Ht as updateClockSignals, Ot as isSignal, Pt as resolveMediaMimeType, bt as getActiveMediaMetadata, f as DEFAULT_DURATION_MS, wt as getMediaType } from "./dist-Bx6J0VcM.mjs";
|
|
2
|
+
import { i as webgpuRegistry, t as audioRegistry } from "./renderer-CtVkU_GA.mjs";
|
|
3
|
+
import { $ as registerHeadlessFont, A as drawLottieNode, B as inputStore, D as drawCaptionNode, M as drawSignalNode, N as drawSvgNode, O as drawGifNode, P as drawVideoNode, b as SlugGeometry, et as shaderStore, it as GetFontAssetUrl, j as drawParagraphNode, k as drawImageNode, ot as getEnv, st as resolveMediaSourceUrl, tt as signalRegistry, y as SlugFontCache } from "./dist-gjHmorxL.mjs";
|
|
4
|
+
import { AudioSampleSink } from "mediabunny";
|
|
5
|
+
|
|
6
|
+
//#region ../renderers/dist/index.mjs
|
|
7
|
+
const mapBlendModeToSkia = (mode) => {
|
|
8
|
+
if (!mode) return "srcOver";
|
|
9
|
+
switch (mode) {
|
|
10
|
+
case "source-over": return "srcOver";
|
|
11
|
+
case "source-in": return "srcIn";
|
|
12
|
+
case "source-out": return "srcOut";
|
|
13
|
+
case "source-atop": return "srcATop";
|
|
14
|
+
case "destination-over": return "dstOver";
|
|
15
|
+
case "destination-in": return "dstIn";
|
|
16
|
+
case "destination-out": return "dstOut";
|
|
17
|
+
case "destination-atop": return "dstATop";
|
|
18
|
+
case "copy": return "src";
|
|
19
|
+
case "xor": return "xor";
|
|
20
|
+
case "multiply": return "multiply";
|
|
21
|
+
case "screen": return "screen";
|
|
22
|
+
case "overlay": return "overlay";
|
|
23
|
+
case "darken": return "darken";
|
|
24
|
+
case "lighten":
|
|
25
|
+
case "lighter": return "lighten";
|
|
26
|
+
case "color-dodge": return "colorDodge";
|
|
27
|
+
case "color-burn": return "colorBurn";
|
|
28
|
+
case "hard-light": return "hardLight";
|
|
29
|
+
case "soft-light": return "softLight";
|
|
30
|
+
case "difference": return "difference";
|
|
31
|
+
case "exclusion": return "exclusion";
|
|
32
|
+
case "hue": return "hue";
|
|
33
|
+
case "saturation": return "saturation";
|
|
34
|
+
case "color": return "color";
|
|
35
|
+
case "luminosity": return "luminosity";
|
|
36
|
+
default: return "srcOver";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const requiresIsolation = (mode) => {
|
|
40
|
+
return mode === "destination-in" || mode === "source-in";
|
|
41
|
+
};
|
|
42
|
+
function computeStrokeRect(w, h, cornerRadius, strokeWidth, align = "outside") {
|
|
43
|
+
if (align === "inside") {
|
|
44
|
+
const half = strokeWidth / 2;
|
|
45
|
+
return {
|
|
46
|
+
x: half,
|
|
47
|
+
y: half,
|
|
48
|
+
width: Math.max(0, w - strokeWidth),
|
|
49
|
+
height: Math.max(0, h - strokeWidth),
|
|
50
|
+
radius: cornerRadius === 0 ? 0 : Math.max(0, cornerRadius - half)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (align === "outside") {
|
|
54
|
+
const half = strokeWidth / 2;
|
|
55
|
+
return {
|
|
56
|
+
x: -half,
|
|
57
|
+
y: -half,
|
|
58
|
+
width: w + strokeWidth,
|
|
59
|
+
height: h + strokeWidth,
|
|
60
|
+
radius: cornerRadius === 0 ? 0 : cornerRadius + half
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
x: 0,
|
|
65
|
+
y: 0,
|
|
66
|
+
width: w,
|
|
67
|
+
height: h,
|
|
68
|
+
radius: cornerRadius
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const { cbrt, sqrt, PI: π } = Math;
|
|
72
|
+
const x2t = (x, a, b, c, d) => {
|
|
73
|
+
const q = a + b * x;
|
|
74
|
+
const s = q ** 2 + c;
|
|
75
|
+
if (s > 0) {
|
|
76
|
+
const root = sqrt(s);
|
|
77
|
+
return cbrt(q + root) + cbrt(q - root) - d;
|
|
78
|
+
}
|
|
79
|
+
const l = cbrt(sqrt(q * q - s));
|
|
80
|
+
const angle = q ? Math.atan(sqrt(-s) / q) : -π / 2;
|
|
81
|
+
let φ;
|
|
82
|
+
if (b < 0) φ = (q > 0 ? 2 * π : π) - angle;
|
|
83
|
+
else if (d < 0) φ = (q > 0 ? 2 * π : -3 * π) + angle;
|
|
84
|
+
else φ = (q > 0 ? 0 : π) + angle;
|
|
85
|
+
return 2 * l * Math.cos(φ / 3) - d;
|
|
86
|
+
};
|
|
87
|
+
const Y = (t, ay, by, cy) => ((ay * t + 3 * by) * t + cy) * t;
|
|
88
|
+
const linearEasing = (x) => x;
|
|
89
|
+
function bezier(mX1, mY1, mX2, mY2) {
|
|
90
|
+
if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) throw new Error("bezier x values must be in [0, 1] range");
|
|
91
|
+
if (mX1 === mY1 && mX2 === mY2) return linearEasing;
|
|
92
|
+
const a = 6 * (3 * mX1 - 3 * mX2 + 1);
|
|
93
|
+
const b = 6 * (mX2 - 2 * mX1);
|
|
94
|
+
const c = 3 * mX1;
|
|
95
|
+
const a2 = a * a;
|
|
96
|
+
const b2 = b * b;
|
|
97
|
+
const d = b / a;
|
|
98
|
+
const e = 3 * b * c / a2 - b2 * b / (a2 * a);
|
|
99
|
+
const w1 = 2 * c / a - b2 / a2;
|
|
100
|
+
const w = w1 * w1 * w1;
|
|
101
|
+
const o = 3 / a;
|
|
102
|
+
const ay = 3 * mY1 - 3 * mY2 + 1;
|
|
103
|
+
const by = mY2 - 2 * mY1;
|
|
104
|
+
const cy = 3 * mY1;
|
|
105
|
+
const X2T = a ? x2t : linearEasing;
|
|
106
|
+
return function BezierEasing(x) {
|
|
107
|
+
if (x === 0 || x === 1) return x;
|
|
108
|
+
return Y(X2T(x, e, o, w, d), ay, by, cy);
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const Easing = {
|
|
112
|
+
linear: linearEasing,
|
|
113
|
+
ease: bezier(.25, .1, .25, 1),
|
|
114
|
+
quad: (t) => t * t,
|
|
115
|
+
cubic: (t) => t * t * t,
|
|
116
|
+
poly: (n) => (t) => t ** n,
|
|
117
|
+
sin: (t) => 1 - Math.cos(t * Math.PI / 2),
|
|
118
|
+
circle: (t) => 1 - Math.sqrt(1 - t * t),
|
|
119
|
+
exp: (t) => 2 ** (10 * (t - 1)),
|
|
120
|
+
elastic: (bounciness = 1) => {
|
|
121
|
+
const p = bounciness * Math.PI;
|
|
122
|
+
return (t) => 1 - Math.cos(t * Math.PI / 2) ** 3 * Math.cos(t * p);
|
|
123
|
+
},
|
|
124
|
+
back: (s = 1.70158) => (t) => t * t * ((s + 1) * t - s),
|
|
125
|
+
bounce: (t) => {
|
|
126
|
+
if (t < 1 / 2.75) return 7.5625 * t * t;
|
|
127
|
+
if (t < 2 / 2.75) {
|
|
128
|
+
const t2$1 = t - 1.5 / 2.75;
|
|
129
|
+
return 7.5625 * t2$1 * t2$1 + .75;
|
|
130
|
+
}
|
|
131
|
+
if (t < 2.5 / 2.75) {
|
|
132
|
+
const t2$1 = t - 2.25 / 2.75;
|
|
133
|
+
return 7.5625 * t2$1 * t2$1 + .9375;
|
|
134
|
+
}
|
|
135
|
+
const t2 = t - 2.625 / 2.75;
|
|
136
|
+
return 7.5625 * t2 * t2 + .984375;
|
|
137
|
+
},
|
|
138
|
+
bezier,
|
|
139
|
+
in: (fn) => fn,
|
|
140
|
+
out: (fn) => (t) => 1 - fn(1 - t),
|
|
141
|
+
inOut: (fn) => (t) => t < .5 ? fn(t * 2) / 2 : 1 - fn((1 - t) * 2) / 2
|
|
142
|
+
};
|
|
143
|
+
function interpolate(value, inputRange, outputRange, options) {
|
|
144
|
+
const extrapolateLeft = options?.extrapolateLeft ?? "extend";
|
|
145
|
+
const extrapolateRight = options?.extrapolateRight ?? "extend";
|
|
146
|
+
if (inputRange.length !== outputRange.length) throw new Error("inputRange and outputRange must have the same length");
|
|
147
|
+
if (inputRange.length < 2) throw new Error("inputRange must have at least 2 elements");
|
|
148
|
+
const firstInput = inputRange[0];
|
|
149
|
+
const lastInput = inputRange[inputRange.length - 1];
|
|
150
|
+
if (value < firstInput) {
|
|
151
|
+
if (extrapolateLeft === "clamp") return outputRange[0];
|
|
152
|
+
if (extrapolateLeft === "identity") return value;
|
|
153
|
+
}
|
|
154
|
+
if (value > lastInput) {
|
|
155
|
+
if (extrapolateRight === "clamp") return outputRange[outputRange.length - 1];
|
|
156
|
+
if (extrapolateRight === "identity") return value;
|
|
157
|
+
}
|
|
158
|
+
let i = 1;
|
|
159
|
+
for (; i < inputRange.length - 1; i++) if (value < inputRange[i]) break;
|
|
160
|
+
const x0 = inputRange[i - 1];
|
|
161
|
+
const x1 = inputRange[i];
|
|
162
|
+
const y0 = outputRange[i - 1];
|
|
163
|
+
const y1 = outputRange[i];
|
|
164
|
+
if (x0 === x1) return y0;
|
|
165
|
+
let progress = (value - x0) / (x1 - x0);
|
|
166
|
+
if (options?.easing) progress = options.easing(progress);
|
|
167
|
+
return y0 + progress * (y1 - y0);
|
|
168
|
+
}
|
|
169
|
+
const Vector3Math = {
|
|
170
|
+
create(x = 0, y = 0, z = 0) {
|
|
171
|
+
return [
|
|
172
|
+
x,
|
|
173
|
+
y,
|
|
174
|
+
z
|
|
175
|
+
];
|
|
176
|
+
},
|
|
177
|
+
copy(v) {
|
|
178
|
+
return [
|
|
179
|
+
v[0],
|
|
180
|
+
v[1],
|
|
181
|
+
v[2]
|
|
182
|
+
];
|
|
183
|
+
},
|
|
184
|
+
set(out, x, y, z) {
|
|
185
|
+
out[0] = x;
|
|
186
|
+
out[1] = y;
|
|
187
|
+
out[2] = z;
|
|
188
|
+
return out;
|
|
189
|
+
},
|
|
190
|
+
add(a, b) {
|
|
191
|
+
return [
|
|
192
|
+
a[0] + b[0],
|
|
193
|
+
a[1] + b[1],
|
|
194
|
+
a[2] + b[2]
|
|
195
|
+
];
|
|
196
|
+
},
|
|
197
|
+
subtract(a, b) {
|
|
198
|
+
return [
|
|
199
|
+
a[0] - b[0],
|
|
200
|
+
a[1] - b[1],
|
|
201
|
+
a[2] - b[2]
|
|
202
|
+
];
|
|
203
|
+
},
|
|
204
|
+
multiplyScalar(v, s) {
|
|
205
|
+
return [
|
|
206
|
+
v[0] * s,
|
|
207
|
+
v[1] * s,
|
|
208
|
+
v[2] * s
|
|
209
|
+
];
|
|
210
|
+
},
|
|
211
|
+
dot(a, b) {
|
|
212
|
+
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
213
|
+
},
|
|
214
|
+
cross(a, b) {
|
|
215
|
+
return [
|
|
216
|
+
a[1] * b[2] - a[2] * b[1],
|
|
217
|
+
a[2] * b[0] - a[0] * b[2],
|
|
218
|
+
a[0] * b[1] - a[1] * b[0]
|
|
219
|
+
];
|
|
220
|
+
},
|
|
221
|
+
lengthSq(v) {
|
|
222
|
+
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
|
|
223
|
+
},
|
|
224
|
+
length(v) {
|
|
225
|
+
return Math.hypot(v[0], v[1], v[2]);
|
|
226
|
+
},
|
|
227
|
+
distance(a, b) {
|
|
228
|
+
return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
|
|
229
|
+
},
|
|
230
|
+
normalize(v) {
|
|
231
|
+
const len = Math.hypot(v[0], v[1], v[2]);
|
|
232
|
+
if (len === 0) return [
|
|
233
|
+
0,
|
|
234
|
+
0,
|
|
235
|
+
0
|
|
236
|
+
];
|
|
237
|
+
const inv = 1 / len;
|
|
238
|
+
return [
|
|
239
|
+
v[0] * inv,
|
|
240
|
+
v[1] * inv,
|
|
241
|
+
v[2] * inv
|
|
242
|
+
];
|
|
243
|
+
},
|
|
244
|
+
lerp(a, b, t) {
|
|
245
|
+
return [
|
|
246
|
+
a[0] + (b[0] - a[0]) * t,
|
|
247
|
+
a[1] + (b[1] - a[1]) * t,
|
|
248
|
+
a[2] + (b[2] - a[2]) * t
|
|
249
|
+
];
|
|
250
|
+
},
|
|
251
|
+
equals(a, b, epsilon = 1e-6) {
|
|
252
|
+
return Math.abs(a[0] - b[0]) <= epsilon && Math.abs(a[1] - b[1]) <= epsilon && Math.abs(a[2] - b[2]) <= epsilon;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* Column-major 4x4 matrix mathematics for WebGPU 3D rendering and camera projections.
|
|
257
|
+
* Memory layout matches WGSL `mat4x4<f32>`:
|
|
258
|
+
* [ 0, 4, 8, 12 ]
|
|
259
|
+
* [ 1, 5, 9, 13 ]
|
|
260
|
+
* [ 2, 6, 10, 14 ]
|
|
261
|
+
* [ 3, 7, 11, 15 ]
|
|
262
|
+
*/
|
|
263
|
+
const Matrix4Math = {
|
|
264
|
+
identity() {
|
|
265
|
+
return [
|
|
266
|
+
1,
|
|
267
|
+
0,
|
|
268
|
+
0,
|
|
269
|
+
0,
|
|
270
|
+
0,
|
|
271
|
+
1,
|
|
272
|
+
0,
|
|
273
|
+
0,
|
|
274
|
+
0,
|
|
275
|
+
0,
|
|
276
|
+
1,
|
|
277
|
+
0,
|
|
278
|
+
0,
|
|
279
|
+
0,
|
|
280
|
+
0,
|
|
281
|
+
1
|
|
282
|
+
];
|
|
283
|
+
},
|
|
284
|
+
copy(m) {
|
|
285
|
+
return [...m];
|
|
286
|
+
},
|
|
287
|
+
multiply(a, b) {
|
|
288
|
+
const out = new Array(16);
|
|
289
|
+
for (let row = 0; row < 4; row++) for (let col = 0; col < 4; col++) out[col * 4 + row] = a[0 + row] * b[col * 4 + 0] + a[4 + row] * b[col * 4 + 1] + a[8 + row] * b[col * 4 + 2] + a[12 + row] * b[col * 4 + 3];
|
|
290
|
+
return out;
|
|
291
|
+
},
|
|
292
|
+
translate(tx, ty, tz = 0) {
|
|
293
|
+
return [
|
|
294
|
+
1,
|
|
295
|
+
0,
|
|
296
|
+
0,
|
|
297
|
+
0,
|
|
298
|
+
0,
|
|
299
|
+
1,
|
|
300
|
+
0,
|
|
301
|
+
0,
|
|
302
|
+
0,
|
|
303
|
+
0,
|
|
304
|
+
1,
|
|
305
|
+
0,
|
|
306
|
+
tx,
|
|
307
|
+
ty,
|
|
308
|
+
tz,
|
|
309
|
+
1
|
|
310
|
+
];
|
|
311
|
+
},
|
|
312
|
+
scale(sx, sy, sz = 1) {
|
|
313
|
+
return [
|
|
314
|
+
sx,
|
|
315
|
+
0,
|
|
316
|
+
0,
|
|
317
|
+
0,
|
|
318
|
+
0,
|
|
319
|
+
sy,
|
|
320
|
+
0,
|
|
321
|
+
0,
|
|
322
|
+
0,
|
|
323
|
+
0,
|
|
324
|
+
sz,
|
|
325
|
+
0,
|
|
326
|
+
0,
|
|
327
|
+
0,
|
|
328
|
+
0,
|
|
329
|
+
1
|
|
330
|
+
];
|
|
331
|
+
},
|
|
332
|
+
rotateX(rad) {
|
|
333
|
+
const c = Math.cos(rad);
|
|
334
|
+
const s = Math.sin(rad);
|
|
335
|
+
return [
|
|
336
|
+
1,
|
|
337
|
+
0,
|
|
338
|
+
0,
|
|
339
|
+
0,
|
|
340
|
+
0,
|
|
341
|
+
c,
|
|
342
|
+
s,
|
|
343
|
+
0,
|
|
344
|
+
0,
|
|
345
|
+
-s,
|
|
346
|
+
c,
|
|
347
|
+
0,
|
|
348
|
+
0,
|
|
349
|
+
0,
|
|
350
|
+
0,
|
|
351
|
+
1
|
|
352
|
+
];
|
|
353
|
+
},
|
|
354
|
+
rotateY(rad) {
|
|
355
|
+
const c = Math.cos(rad);
|
|
356
|
+
const s = Math.sin(rad);
|
|
357
|
+
return [
|
|
358
|
+
c,
|
|
359
|
+
0,
|
|
360
|
+
-s,
|
|
361
|
+
0,
|
|
362
|
+
0,
|
|
363
|
+
1,
|
|
364
|
+
0,
|
|
365
|
+
0,
|
|
366
|
+
s,
|
|
367
|
+
0,
|
|
368
|
+
c,
|
|
369
|
+
0,
|
|
370
|
+
0,
|
|
371
|
+
0,
|
|
372
|
+
0,
|
|
373
|
+
1
|
|
374
|
+
];
|
|
375
|
+
},
|
|
376
|
+
rotateZ(rad) {
|
|
377
|
+
const c = Math.cos(rad);
|
|
378
|
+
const s = Math.sin(rad);
|
|
379
|
+
return [
|
|
380
|
+
c,
|
|
381
|
+
s,
|
|
382
|
+
0,
|
|
383
|
+
0,
|
|
384
|
+
-s,
|
|
385
|
+
c,
|
|
386
|
+
0,
|
|
387
|
+
0,
|
|
388
|
+
0,
|
|
389
|
+
0,
|
|
390
|
+
1,
|
|
391
|
+
0,
|
|
392
|
+
0,
|
|
393
|
+
0,
|
|
394
|
+
0,
|
|
395
|
+
1
|
|
396
|
+
];
|
|
397
|
+
},
|
|
398
|
+
rotateAxis(axis, rad) {
|
|
399
|
+
const norm = Vector3Math.normalize(axis);
|
|
400
|
+
const x = norm[0];
|
|
401
|
+
const y = norm[1];
|
|
402
|
+
const z = norm[2];
|
|
403
|
+
const c = Math.cos(rad);
|
|
404
|
+
const s = Math.sin(rad);
|
|
405
|
+
const t = 1 - c;
|
|
406
|
+
return [
|
|
407
|
+
t * x * x + c,
|
|
408
|
+
t * x * y + s * z,
|
|
409
|
+
t * x * z - s * y,
|
|
410
|
+
0,
|
|
411
|
+
t * x * y - s * z,
|
|
412
|
+
t * y * y + c,
|
|
413
|
+
t * y * z + s * x,
|
|
414
|
+
0,
|
|
415
|
+
t * x * z + s * y,
|
|
416
|
+
t * y * z - s * x,
|
|
417
|
+
t * z * z + c,
|
|
418
|
+
0,
|
|
419
|
+
0,
|
|
420
|
+
0,
|
|
421
|
+
0,
|
|
422
|
+
1
|
|
423
|
+
];
|
|
424
|
+
},
|
|
425
|
+
lookAt(eye, target, up = [
|
|
426
|
+
0,
|
|
427
|
+
-1,
|
|
428
|
+
0
|
|
429
|
+
]) {
|
|
430
|
+
let f = Vector3Math.subtract(target, eye);
|
|
431
|
+
if (Vector3Math.lengthSq(f) === 0) f = [
|
|
432
|
+
0,
|
|
433
|
+
0,
|
|
434
|
+
1
|
|
435
|
+
];
|
|
436
|
+
else f = Vector3Math.normalize(f);
|
|
437
|
+
let r = Vector3Math.cross(f, up);
|
|
438
|
+
if (Vector3Math.lengthSq(r) === 0) r = [
|
|
439
|
+
1,
|
|
440
|
+
0,
|
|
441
|
+
0
|
|
442
|
+
];
|
|
443
|
+
else r = Vector3Math.normalize(r);
|
|
444
|
+
const u = Vector3Math.cross(r, f);
|
|
445
|
+
return [
|
|
446
|
+
r[0],
|
|
447
|
+
u[0],
|
|
448
|
+
f[0],
|
|
449
|
+
0,
|
|
450
|
+
r[1],
|
|
451
|
+
u[1],
|
|
452
|
+
f[1],
|
|
453
|
+
0,
|
|
454
|
+
r[2],
|
|
455
|
+
u[2],
|
|
456
|
+
f[2],
|
|
457
|
+
0,
|
|
458
|
+
-Vector3Math.dot(r, eye),
|
|
459
|
+
-Vector3Math.dot(u, eye),
|
|
460
|
+
-Vector3Math.dot(f, eye),
|
|
461
|
+
1
|
|
462
|
+
];
|
|
463
|
+
},
|
|
464
|
+
perspective(fovYRad, aspect, near, far) {
|
|
465
|
+
const f = 1 / Math.tan(fovYRad / 2);
|
|
466
|
+
const rangeInv = 1 / (far - near);
|
|
467
|
+
return [
|
|
468
|
+
f / aspect,
|
|
469
|
+
0,
|
|
470
|
+
0,
|
|
471
|
+
0,
|
|
472
|
+
0,
|
|
473
|
+
f,
|
|
474
|
+
0,
|
|
475
|
+
0,
|
|
476
|
+
0,
|
|
477
|
+
0,
|
|
478
|
+
far * rangeInv,
|
|
479
|
+
1,
|
|
480
|
+
0,
|
|
481
|
+
0,
|
|
482
|
+
-near * far * rangeInv,
|
|
483
|
+
0
|
|
484
|
+
];
|
|
485
|
+
},
|
|
486
|
+
orthographic(left, right, bottom, top, near, far) {
|
|
487
|
+
const lr = 1 / (right - left);
|
|
488
|
+
const bt = 1 / (top - bottom);
|
|
489
|
+
const nf = 1 / (far - near);
|
|
490
|
+
return [
|
|
491
|
+
2 * lr,
|
|
492
|
+
0,
|
|
493
|
+
0,
|
|
494
|
+
0,
|
|
495
|
+
0,
|
|
496
|
+
2 * bt,
|
|
497
|
+
0,
|
|
498
|
+
0,
|
|
499
|
+
0,
|
|
500
|
+
0,
|
|
501
|
+
nf,
|
|
502
|
+
0,
|
|
503
|
+
-(right + left) * lr,
|
|
504
|
+
-(top + bottom) * bt,
|
|
505
|
+
-near * nf,
|
|
506
|
+
1
|
|
507
|
+
];
|
|
508
|
+
},
|
|
509
|
+
invert(m) {
|
|
510
|
+
const inv = new Array(16);
|
|
511
|
+
inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
|
|
512
|
+
inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
|
|
513
|
+
inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
|
|
514
|
+
inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
|
|
515
|
+
inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
|
|
516
|
+
inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
|
|
517
|
+
inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
|
|
518
|
+
inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
|
|
519
|
+
inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
|
|
520
|
+
inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
|
|
521
|
+
inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
|
|
522
|
+
inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
|
|
523
|
+
inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
|
|
524
|
+
inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
|
|
525
|
+
inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
|
|
526
|
+
inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];
|
|
527
|
+
let det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
|
|
528
|
+
if (Math.abs(det) < 1e-12) return null;
|
|
529
|
+
det = 1 / det;
|
|
530
|
+
for (let i = 0; i < 16; i++) inv[i] *= det;
|
|
531
|
+
return inv;
|
|
532
|
+
},
|
|
533
|
+
transpose(m) {
|
|
534
|
+
return [
|
|
535
|
+
m[0],
|
|
536
|
+
m[4],
|
|
537
|
+
m[8],
|
|
538
|
+
m[12],
|
|
539
|
+
m[1],
|
|
540
|
+
m[5],
|
|
541
|
+
m[9],
|
|
542
|
+
m[13],
|
|
543
|
+
m[2],
|
|
544
|
+
m[6],
|
|
545
|
+
m[10],
|
|
546
|
+
m[14],
|
|
547
|
+
m[3],
|
|
548
|
+
m[7],
|
|
549
|
+
m[11],
|
|
550
|
+
m[15]
|
|
551
|
+
];
|
|
552
|
+
},
|
|
553
|
+
projectPoint(m, p) {
|
|
554
|
+
const x = p[0];
|
|
555
|
+
const y = p[1];
|
|
556
|
+
const z = p[2];
|
|
557
|
+
const X = m[0] * x + m[4] * y + m[8] * z + m[12];
|
|
558
|
+
const Y$1 = m[1] * x + m[5] * y + m[9] * z + m[13];
|
|
559
|
+
const Z = m[2] * x + m[6] * y + m[10] * z + m[14];
|
|
560
|
+
const W = m[3] * x + m[7] * y + m[11] * z + m[15];
|
|
561
|
+
const wInv = Math.abs(W) > 1e-6 ? 1 / W : 1;
|
|
562
|
+
return [
|
|
563
|
+
X * wInv,
|
|
564
|
+
Y$1 * wInv,
|
|
565
|
+
Z * wInv
|
|
566
|
+
];
|
|
567
|
+
},
|
|
568
|
+
projectRectangle(m, width, height) {
|
|
569
|
+
return [
|
|
570
|
+
Matrix4Math.projectPoint(m, [
|
|
571
|
+
0,
|
|
572
|
+
0,
|
|
573
|
+
0
|
|
574
|
+
]),
|
|
575
|
+
Matrix4Math.projectPoint(m, [
|
|
576
|
+
width,
|
|
577
|
+
0,
|
|
578
|
+
0
|
|
579
|
+
]),
|
|
580
|
+
Matrix4Math.projectPoint(m, [
|
|
581
|
+
width,
|
|
582
|
+
height,
|
|
583
|
+
0
|
|
584
|
+
]),
|
|
585
|
+
Matrix4Math.projectPoint(m, [
|
|
586
|
+
0,
|
|
587
|
+
height,
|
|
588
|
+
0
|
|
589
|
+
])
|
|
590
|
+
];
|
|
591
|
+
},
|
|
592
|
+
toFloat32Array(m) {
|
|
593
|
+
return new Float32Array(m);
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
/**
|
|
597
|
+
* WebGPU 3D Lighting & Material Shading engine.
|
|
598
|
+
* Supports Ambient, Directional, Point, and Spot light sources,
|
|
599
|
+
* normal matrix computation for non-uniform surface scaling,
|
|
600
|
+
* and binary uniform buffer packing for WGSL shaders.
|
|
601
|
+
*/
|
|
602
|
+
const MAX_LIGHTS = 8;
|
|
603
|
+
const LIGHT_UNIFORM_SIZE_BYTES = 544;
|
|
604
|
+
/**
|
|
605
|
+
* Parses CSS / hex / rgb color strings, arrays, or color objects into normalized linear [r, g, b] floats in [0, 1].
|
|
606
|
+
*/
|
|
607
|
+
function parseColorToRgb(color) {
|
|
608
|
+
if (!color) return [
|
|
609
|
+
1,
|
|
610
|
+
1,
|
|
611
|
+
1
|
|
612
|
+
];
|
|
613
|
+
if (Array.isArray(color)) {
|
|
614
|
+
const r = color[0] ?? 1;
|
|
615
|
+
const g = color[1] ?? 1;
|
|
616
|
+
const b = color[2] ?? 1;
|
|
617
|
+
return [
|
|
618
|
+
r > 1 ? r / 255 : r,
|
|
619
|
+
g > 1 ? g / 255 : g,
|
|
620
|
+
b > 1 ? b / 255 : b
|
|
621
|
+
];
|
|
622
|
+
}
|
|
623
|
+
if (typeof color === "object" && color !== null) {
|
|
624
|
+
const r = color.r ?? 1;
|
|
625
|
+
const g = color.g ?? 1;
|
|
626
|
+
const b = color.b ?? 1;
|
|
627
|
+
return [
|
|
628
|
+
r > 1 ? r / 255 : r,
|
|
629
|
+
g > 1 ? g / 255 : g,
|
|
630
|
+
b > 1 ? b / 255 : b
|
|
631
|
+
];
|
|
632
|
+
}
|
|
633
|
+
if (typeof color !== "string") return [
|
|
634
|
+
1,
|
|
635
|
+
1,
|
|
636
|
+
1
|
|
637
|
+
];
|
|
638
|
+
const str = color.trim().toLowerCase();
|
|
639
|
+
if (str.startsWith("#")) {
|
|
640
|
+
const hex = str.slice(1);
|
|
641
|
+
if (hex.length === 3) return [
|
|
642
|
+
Number.parseInt(hex[0] + hex[0], 16) / 255,
|
|
643
|
+
Number.parseInt(hex[1] + hex[1], 16) / 255,
|
|
644
|
+
Number.parseInt(hex[2] + hex[2], 16) / 255
|
|
645
|
+
];
|
|
646
|
+
if (hex.length >= 6) return [
|
|
647
|
+
Number.parseInt(hex.slice(0, 2), 16) / 255,
|
|
648
|
+
Number.parseInt(hex.slice(2, 4), 16) / 255,
|
|
649
|
+
Number.parseInt(hex.slice(4, 6), 16) / 255
|
|
650
|
+
];
|
|
651
|
+
}
|
|
652
|
+
const rgbMatch = str.match(/rgba?\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/);
|
|
653
|
+
if (rgbMatch) {
|
|
654
|
+
const r = Number.parseFloat(rgbMatch[1]) / 255;
|
|
655
|
+
const g = Number.parseFloat(rgbMatch[2]) / 255;
|
|
656
|
+
const b = Number.parseFloat(rgbMatch[3]) / 255;
|
|
657
|
+
return [
|
|
658
|
+
Math.max(0, Math.min(1, r)),
|
|
659
|
+
Math.max(0, Math.min(1, g)),
|
|
660
|
+
Math.max(0, Math.min(1, b))
|
|
661
|
+
];
|
|
662
|
+
}
|
|
663
|
+
const hslMatch = str.match(/hsla?\s*\(\s*([\d.]+)\s*,\s*([\d.]+)%?\s*,\s*([\d.]+)%?/);
|
|
664
|
+
if (hslMatch) return hslToRgb(Number.parseFloat(hslMatch[1]) / 360, Number.parseFloat(hslMatch[2]) / 100, Number.parseFloat(hslMatch[3]) / 100);
|
|
665
|
+
return [
|
|
666
|
+
1,
|
|
667
|
+
1,
|
|
668
|
+
1
|
|
669
|
+
];
|
|
670
|
+
}
|
|
671
|
+
function hslToRgb(h, s, l) {
|
|
672
|
+
if (s === 0) return [
|
|
673
|
+
l,
|
|
674
|
+
l,
|
|
675
|
+
l
|
|
676
|
+
];
|
|
677
|
+
const hue2rgb = (p$1, q$1, t) => {
|
|
678
|
+
let tt = t;
|
|
679
|
+
if (tt < 0) tt += 1;
|
|
680
|
+
if (tt > 1) tt -= 1;
|
|
681
|
+
if (tt < 1 / 6) return p$1 + (q$1 - p$1) * 6 * tt;
|
|
682
|
+
if (tt < 1 / 2) return q$1;
|
|
683
|
+
if (tt < 2 / 3) return p$1 + (q$1 - p$1) * (2 / 3 - tt) * 6;
|
|
684
|
+
return p$1;
|
|
685
|
+
};
|
|
686
|
+
const q = l < .5 ? l * (1 + s) : l + s - l * s;
|
|
687
|
+
const p = 2 * l - q;
|
|
688
|
+
return [
|
|
689
|
+
hue2rgb(p, q, h + 1 / 3),
|
|
690
|
+
hue2rgb(p, q, h),
|
|
691
|
+
hue2rgb(p, q, h - 1 / 3)
|
|
692
|
+
];
|
|
693
|
+
}
|
|
694
|
+
const defaultSpringConfig = {
|
|
695
|
+
damping: 10,
|
|
696
|
+
mass: 1,
|
|
697
|
+
stiffness: 100,
|
|
698
|
+
overshootClamping: false
|
|
699
|
+
};
|
|
700
|
+
const advanceCache = {};
|
|
701
|
+
function advance({ animation, now, config }) {
|
|
702
|
+
const { toValue, lastTimestamp, current, velocity } = animation;
|
|
703
|
+
const deltaTime = Math.min(now - lastTimestamp, 64);
|
|
704
|
+
if (config.damping <= 0) throw new Error("Spring damping must be greater than 0, otherwise the spring() animation will never end, causing an infinite loop.");
|
|
705
|
+
if (config.stiffness <= 0) throw new Error("Spring stiffness must be greater than 0.");
|
|
706
|
+
if (config.mass <= 0) throw new Error("Spring mass must be greater than 0.");
|
|
707
|
+
const c = config.damping;
|
|
708
|
+
const m = config.mass;
|
|
709
|
+
const k = config.stiffness;
|
|
710
|
+
const cacheKey = [
|
|
711
|
+
toValue,
|
|
712
|
+
lastTimestamp,
|
|
713
|
+
current,
|
|
714
|
+
velocity,
|
|
715
|
+
c,
|
|
716
|
+
m,
|
|
717
|
+
k,
|
|
718
|
+
now
|
|
719
|
+
].join("-");
|
|
720
|
+
if (advanceCache[cacheKey]) return advanceCache[cacheKey];
|
|
721
|
+
const v0 = -velocity;
|
|
722
|
+
const x0 = toValue - current;
|
|
723
|
+
const zeta = c / (2 * Math.sqrt(k * m));
|
|
724
|
+
const omega0 = Math.sqrt(k / m);
|
|
725
|
+
const omega1 = omega0 * Math.sqrt(1 - zeta ** 2);
|
|
726
|
+
const t = deltaTime / 1e3;
|
|
727
|
+
const sin1 = Math.sin(omega1 * t);
|
|
728
|
+
const cos1 = Math.cos(omega1 * t);
|
|
729
|
+
const underDampedEnvelope = Math.exp(-zeta * omega0 * t);
|
|
730
|
+
const underDampedFrag1 = underDampedEnvelope * (sin1 * ((v0 + zeta * omega0 * x0) / omega1) + x0 * cos1);
|
|
731
|
+
const underDampedPosition = toValue - underDampedFrag1;
|
|
732
|
+
const underDampedVelocity = zeta * omega0 * underDampedFrag1 - underDampedEnvelope * (cos1 * (v0 + zeta * omega0 * x0) - omega1 * x0 * sin1);
|
|
733
|
+
const criticallyDampedEnvelope = Math.exp(-omega0 * t);
|
|
734
|
+
const criticallyDampedPosition = toValue - criticallyDampedEnvelope * (x0 + (v0 + omega0 * x0) * t);
|
|
735
|
+
const criticallyDampedVelocity = criticallyDampedEnvelope * (v0 * (t * omega0 - 1) + t * x0 * omega0 * omega0);
|
|
736
|
+
const animationNode = {
|
|
737
|
+
toValue,
|
|
738
|
+
prevPosition: current,
|
|
739
|
+
lastTimestamp: now,
|
|
740
|
+
current: zeta < 1 ? underDampedPosition : criticallyDampedPosition,
|
|
741
|
+
velocity: zeta < 1 ? underDampedVelocity : criticallyDampedVelocity
|
|
742
|
+
};
|
|
743
|
+
advanceCache[cacheKey] = animationNode;
|
|
744
|
+
return animationNode;
|
|
745
|
+
}
|
|
746
|
+
const calculationCache = {};
|
|
747
|
+
function springCalculation({ frame, fps, config = {} }) {
|
|
748
|
+
const from = 0;
|
|
749
|
+
const to = 1;
|
|
750
|
+
const cacheKey = [
|
|
751
|
+
frame,
|
|
752
|
+
fps,
|
|
753
|
+
config.damping,
|
|
754
|
+
config.mass,
|
|
755
|
+
config.overshootClamping,
|
|
756
|
+
config.stiffness
|
|
757
|
+
].join("-");
|
|
758
|
+
if (calculationCache[cacheKey]) return calculationCache[cacheKey];
|
|
759
|
+
let animation = {
|
|
760
|
+
lastTimestamp: 0,
|
|
761
|
+
current: from,
|
|
762
|
+
toValue: to,
|
|
763
|
+
velocity: 0,
|
|
764
|
+
prevPosition: 0
|
|
765
|
+
};
|
|
766
|
+
const frameClamped = Math.max(0, frame);
|
|
767
|
+
const unevenRest = frameClamped % 1;
|
|
768
|
+
for (let f = 0; f <= Math.floor(frameClamped); f++) {
|
|
769
|
+
if (f === Math.floor(frameClamped)) f += unevenRest;
|
|
770
|
+
const time = f / fps * 1e3;
|
|
771
|
+
animation = advance({
|
|
772
|
+
animation,
|
|
773
|
+
now: time,
|
|
774
|
+
config: {
|
|
775
|
+
...defaultSpringConfig,
|
|
776
|
+
...config
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
calculationCache[cacheKey] = animation;
|
|
781
|
+
return animation;
|
|
782
|
+
}
|
|
783
|
+
const measureCache = /* @__PURE__ */ new Map();
|
|
784
|
+
function measureSpring({ fps, config = {}, threshold = .005 }) {
|
|
785
|
+
if (typeof threshold !== "number") throw new TypeError(`threshold must be a number, got ${threshold}`);
|
|
786
|
+
if (threshold === 0) return Infinity;
|
|
787
|
+
if (threshold === 1) return 0;
|
|
788
|
+
if (Number.isNaN(threshold)) throw new TypeError("Threshold is NaN");
|
|
789
|
+
if (!Number.isFinite(threshold)) throw new TypeError("Threshold is not finite");
|
|
790
|
+
if (threshold < 0) throw new TypeError("Threshold is below 0");
|
|
791
|
+
const cacheKey = [
|
|
792
|
+
fps,
|
|
793
|
+
config.damping,
|
|
794
|
+
config.mass,
|
|
795
|
+
config.overshootClamping,
|
|
796
|
+
config.stiffness,
|
|
797
|
+
threshold
|
|
798
|
+
].join("-");
|
|
799
|
+
if (measureCache.has(cacheKey)) return measureCache.get(cacheKey);
|
|
800
|
+
let frame = 0;
|
|
801
|
+
let finishedFrame = 0;
|
|
802
|
+
const calc = () => {
|
|
803
|
+
return springCalculation({
|
|
804
|
+
fps,
|
|
805
|
+
frame,
|
|
806
|
+
config
|
|
807
|
+
});
|
|
808
|
+
};
|
|
809
|
+
let animation = calc();
|
|
810
|
+
const calcDifference = () => {
|
|
811
|
+
return Math.abs(animation.current - animation.toValue);
|
|
812
|
+
};
|
|
813
|
+
let difference = calcDifference();
|
|
814
|
+
while (difference >= threshold) {
|
|
815
|
+
frame++;
|
|
816
|
+
animation = calc();
|
|
817
|
+
difference = calcDifference();
|
|
818
|
+
}
|
|
819
|
+
finishedFrame = frame;
|
|
820
|
+
for (let i = 0; i < 20; i++) {
|
|
821
|
+
frame++;
|
|
822
|
+
animation = calc();
|
|
823
|
+
difference = calcDifference();
|
|
824
|
+
if (difference >= threshold) {
|
|
825
|
+
i = 0;
|
|
826
|
+
finishedFrame = frame + 1;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
measureCache.set(cacheKey, finishedFrame);
|
|
830
|
+
return finishedFrame;
|
|
831
|
+
}
|
|
832
|
+
function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durationInFrames: passedDurationInFrames, durationRestThreshold, delay = 0, reverse = false }) {
|
|
833
|
+
const needsToCalculateNaturalDuration = reverse || typeof passedDurationInFrames !== "undefined";
|
|
834
|
+
const naturalDuration = needsToCalculateNaturalDuration ? measureSpring({
|
|
835
|
+
fps,
|
|
836
|
+
config,
|
|
837
|
+
threshold: durationRestThreshold
|
|
838
|
+
}) : void 0;
|
|
839
|
+
const naturalDurationGetter = needsToCalculateNaturalDuration ? { get: () => naturalDuration } : { get: () => {
|
|
840
|
+
throw new Error("did not calculate natural duration");
|
|
841
|
+
} };
|
|
842
|
+
const delayProcessed = (reverse ? (passedDurationInFrames ?? naturalDurationGetter.get()) - passedFrame : passedFrame) + (reverse ? delay : -delay);
|
|
843
|
+
const durationProcessed = passedDurationInFrames === void 0 ? delayProcessed : delayProcessed / (passedDurationInFrames / naturalDurationGetter.get());
|
|
844
|
+
if (passedDurationInFrames && delayProcessed > passedDurationInFrames) return to;
|
|
845
|
+
const spr = springCalculation({
|
|
846
|
+
fps,
|
|
847
|
+
frame: durationProcessed,
|
|
848
|
+
config
|
|
849
|
+
});
|
|
850
|
+
const inner = config.overshootClamping ? to >= from ? Math.min(spr.current, to) : Math.max(spr.current, to) : spr.current;
|
|
851
|
+
return from === 0 && to === 1 ? inner : interpolate(inner, [0, 1], [from, to]);
|
|
852
|
+
}
|
|
853
|
+
const cache = /* @__PURE__ */ new Map();
|
|
854
|
+
function getCacheKey(text, style) {
|
|
855
|
+
return JSON.stringify({
|
|
856
|
+
text,
|
|
857
|
+
...style
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Shared text measurer that uses SlugGeometry.measure for all environments.
|
|
862
|
+
*/
|
|
863
|
+
function measureText(text, style) {
|
|
864
|
+
const safeText = text ? String(text) : " ";
|
|
865
|
+
const cacheKey = getCacheKey(safeText, style);
|
|
866
|
+
const cached = cache.get(cacheKey);
|
|
867
|
+
if (cached) return cached;
|
|
868
|
+
const fontSize = style.fontSize ?? 48;
|
|
869
|
+
let fontFamily = style.fontFamily ?? "Inter";
|
|
870
|
+
if (SlugFontCache.isFailed(fontFamily)) fontFamily = "Inter";
|
|
871
|
+
const letterSpacing = style.letterSpacing ?? 0;
|
|
872
|
+
const calculatedLineHeight = style.lineHeight !== void 0 && style.lineHeight < 10 ? style.lineHeight * fontSize : style.lineHeight ?? fontSize * 1.2;
|
|
873
|
+
const slugFont = SlugFontCache.getFont(fontFamily, style.fontWeight, null);
|
|
874
|
+
const padding = style.padding ?? 0;
|
|
875
|
+
if (!slugFont) {
|
|
876
|
+
if (!SlugFontCache.isFailed(fontFamily)) {
|
|
877
|
+
const fontUrl = GetFontAssetUrl(fontFamily);
|
|
878
|
+
SlugFontCache.preloadSlugFont(null, fontFamily, fontUrl).catch(() => {});
|
|
879
|
+
}
|
|
880
|
+
const lines = safeText.split("\n");
|
|
881
|
+
let totalWrappedLines = 0;
|
|
882
|
+
const maxW = style.width !== void 0 ? Math.max(10, style.width - padding * 2) : 0;
|
|
883
|
+
for (const line of lines) if (maxW > 0) {
|
|
884
|
+
const estLineWidth = line.length * fontSize * .55 + letterSpacing * line.length;
|
|
885
|
+
const wrapCount = Math.max(1, Math.ceil(estLineWidth / maxW));
|
|
886
|
+
totalWrappedLines += wrapCount;
|
|
887
|
+
} else totalWrappedLines += 1;
|
|
888
|
+
const result$1 = {
|
|
889
|
+
width: style.width !== void 0 ? style.width : Math.ceil(safeText.length * fontSize * .6 + letterSpacing * safeText.length) + 2 + padding * 2,
|
|
890
|
+
height: style.height !== void 0 ? style.height : Math.ceil(totalWrappedLines * calculatedLineHeight) + 2 + padding * 2
|
|
891
|
+
};
|
|
892
|
+
cache.set(cacheKey, result$1);
|
|
893
|
+
return result$1;
|
|
894
|
+
}
|
|
895
|
+
const measured = SlugGeometry.measure(safeText, slugFont, fontSize, letterSpacing, calculatedLineHeight, style.width !== void 0 ? Math.max(0, style.width - padding * 2) : void 0, style.spans);
|
|
896
|
+
const result = {
|
|
897
|
+
width: style.width !== void 0 && !style.keepNaturalWidth ? style.width : Math.ceil(measured.width) + padding * 2 + 8,
|
|
898
|
+
height: style.height !== void 0 ? style.height : Math.ceil(measured.height) + padding * 2
|
|
899
|
+
};
|
|
900
|
+
cache.set(cacheKey, result);
|
|
901
|
+
return result;
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Async variant of measureText. Preloads the Slug font and yields to the browser.
|
|
905
|
+
*/
|
|
906
|
+
function measureTextAsync(text, style) {
|
|
907
|
+
let fontFamily = style.fontFamily ?? "Inter";
|
|
908
|
+
if (SlugFontCache.isFailed(fontFamily)) fontFamily = "Inter";
|
|
909
|
+
if (SlugFontCache.isFailed(fontFamily)) return Promise.resolve(measureText(text, style));
|
|
910
|
+
const fontUrl = GetFontAssetUrl(fontFamily);
|
|
911
|
+
return SlugFontCache.preloadSlugFont(null, fontFamily, fontUrl).then(() => measureText(text, style)).catch(() => measureText(text, style));
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Preloads a font into the browser or headless environment.
|
|
915
|
+
*/
|
|
916
|
+
async function preloadFont(family, url) {
|
|
917
|
+
if (typeof window !== "undefined" && typeof FontFace !== "undefined") try {
|
|
918
|
+
const loadedFace = await new FontFace(family, `url(${url})`).load();
|
|
919
|
+
document.fonts.add(loadedFace);
|
|
920
|
+
await document.fonts.ready;
|
|
921
|
+
} catch (e) {
|
|
922
|
+
console.warn(`[preloadFont] Failed to load font "${family}" from ${url}:`, e);
|
|
923
|
+
}
|
|
924
|
+
else await registerHeadlessFont(family, url);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
//#endregion
|
|
928
|
+
//#region ../compositions/dist/layer-logic-DBs4NHoi.mjs
|
|
929
|
+
const BASE_URL = getEnv("BASE_URL");
|
|
930
|
+
const CDN_DOMAIN = getEnv("R2_CUSTOM_DOMAIN");
|
|
931
|
+
/**
|
|
932
|
+
* Compute render parameters for the CURRENT node only — does NOT recurse into
|
|
933
|
+
* children. Each node in the VirtualMedia tree is responsible for exactly its
|
|
934
|
+
* own operation; `SingleClipComposition` drives traversal via React recursion.
|
|
935
|
+
*
|
|
936
|
+
* This is the correct function to use inside the renderer.
|
|
937
|
+
*/
|
|
938
|
+
function computeRenderParams(vv) {
|
|
939
|
+
const op = vv.operation;
|
|
940
|
+
const baseMeta = getActiveMediaMetadata(vv);
|
|
941
|
+
const params = {
|
|
942
|
+
sourceUrl: void 0,
|
|
943
|
+
trimStartSec: 0,
|
|
944
|
+
trimEndSec: null,
|
|
945
|
+
speed: 1,
|
|
946
|
+
cropRegion: null,
|
|
947
|
+
flipH: false,
|
|
948
|
+
flipV: false,
|
|
949
|
+
rotation: 0,
|
|
950
|
+
effectiveDurationSec: 0,
|
|
951
|
+
mimeType: resolveMediaMimeType(vv) || null
|
|
952
|
+
};
|
|
953
|
+
switch (op.op) {
|
|
954
|
+
case "text":
|
|
955
|
+
params.sourceUrl = void 0;
|
|
956
|
+
break;
|
|
957
|
+
default:
|
|
958
|
+
params.sourceUrl = resolveMediaSourceUrl(vv);
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
const sourceDurationSec = (baseMeta?.durationMs ?? 0) / 1e3;
|
|
962
|
+
params.effectiveDurationSec = ((params.trimEndSec ?? sourceDurationSec) - params.trimStartSec) / params.speed;
|
|
963
|
+
return params;
|
|
964
|
+
}
|
|
965
|
+
function secondsToFrames(seconds, fps) {
|
|
966
|
+
return Math.round(seconds * fps);
|
|
967
|
+
}
|
|
968
|
+
const isStaticVisualMedia = (type) => type === "Image" || type === "SVG" || type === "Text";
|
|
969
|
+
const resolveLayerDuration = (layerDurationInMS, metaDurationMs, defaultDuration = DEFAULT_DURATION_MS, type) => {
|
|
970
|
+
if (type === "Caption") return metaDurationMs && metaDurationMs > 0 ? metaDurationMs : layerDurationInMS || defaultDuration;
|
|
971
|
+
const isStatic = isStaticVisualMedia(type);
|
|
972
|
+
if (layerDurationInMS && metaDurationMs && !isStatic) return Math.min(layerDurationInMS, metaDurationMs);
|
|
973
|
+
return layerDurationInMS || metaDurationMs || defaultDuration;
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
//#endregion
|
|
977
|
+
//#region ../compositions/dist/index.mjs
|
|
978
|
+
const segmentRangeCache = /* @__PURE__ */ new WeakMap();
|
|
979
|
+
function getCachedSegmentRanges(segments, fps) {
|
|
980
|
+
const cached = segmentRangeCache.get(segments);
|
|
981
|
+
if (cached && cached.fps === fps) return cached.ranges;
|
|
982
|
+
let currentStart = 0;
|
|
983
|
+
const ranges = segments.map((seg) => {
|
|
984
|
+
const durSec = (seg.endSec ?? 0) - seg.startSec;
|
|
985
|
+
const durFrames = Math.max(1, Math.round(durSec * fps));
|
|
986
|
+
const start = currentStart;
|
|
987
|
+
currentStart += durFrames;
|
|
988
|
+
return {
|
|
989
|
+
seg,
|
|
990
|
+
start,
|
|
991
|
+
duration: durFrames
|
|
992
|
+
};
|
|
993
|
+
});
|
|
994
|
+
segmentRangeCache.set(segments, {
|
|
995
|
+
fps,
|
|
996
|
+
ranges
|
|
997
|
+
});
|
|
998
|
+
return ranges;
|
|
999
|
+
}
|
|
1000
|
+
const frameCtxPool = [];
|
|
1001
|
+
function acquireFrameContext() {
|
|
1002
|
+
return frameCtxPool.pop() ?? {};
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Effect operations carry every config field as a signal. Hand node renderers
|
|
1006
|
+
* the plain value for this frame (nested objects/arrays included), keeping only
|
|
1007
|
+
* GPU-bound signals intact since those are consumed as textures.
|
|
1008
|
+
*/
|
|
1009
|
+
function resolveSignalOperation(virtualMedia, frameCtx) {
|
|
1010
|
+
const op = virtualMedia.operation;
|
|
1011
|
+
const resolved = { ...op };
|
|
1012
|
+
for (const [key, sig] of Object.entries(op.signals)) if (isSignal(sig) && !sig.gpuBinding) resolved[key] = sig.get(frameCtx);
|
|
1013
|
+
return {
|
|
1014
|
+
...virtualMedia,
|
|
1015
|
+
operation: resolved
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
async function drawCompositionTree(ctx, encoder, targetView, targetTexture, targetWidth, targetHeight, virtualMedia, props, inheritedSeekOffset = 0, inheritedClockOffset = 0) {
|
|
1019
|
+
const fps = props.fps ?? 24;
|
|
1020
|
+
const op = virtualMedia.operation;
|
|
1021
|
+
if (!op) return;
|
|
1022
|
+
const isCompositor = op.op === "Compositor";
|
|
1023
|
+
const frame = props.frame ?? 0;
|
|
1024
|
+
const segments = op.timeline?.segments || [];
|
|
1025
|
+
const localFrame = frame - (op.startFrame ?? op.timeline?.startFrame ?? 0);
|
|
1026
|
+
const isTimelineProvider = op.timeline !== void 0 || op.startFrame !== void 0 || op.op === "compose";
|
|
1027
|
+
const resolvedDurationMs = isTimelineProvider ? getActiveMediaMetadata(virtualMedia)?.durationMs ?? props.durationMs ?? void 0 : props.durationMs ?? getActiveMediaMetadata(virtualMedia)?.durationMs ?? void 0;
|
|
1028
|
+
if (!(op.op === "source" || op.op === "text" || op.op === "caption")) updateClockSignals(frame, fps, resolvedDurationMs);
|
|
1029
|
+
const frameCtx = acquireFrameContext();
|
|
1030
|
+
frameCtx.frame = frame;
|
|
1031
|
+
frameCtx.fps = fps;
|
|
1032
|
+
frameCtx.time = fps > 0 ? frame / fps : 0;
|
|
1033
|
+
frameCtx.duration = (resolvedDurationMs ?? 0) / 1e3;
|
|
1034
|
+
frameCtx.durationMs = resolvedDurationMs ?? 0;
|
|
1035
|
+
frameCtx.progress = resolvedDurationMs && resolvedDurationMs > 0 ? Math.max(0, Math.min(1, frame / fps * 1e3 / resolvedDurationMs)) : 0;
|
|
1036
|
+
frameCtx.deltaTime = fps > 0 ? 1 / fps : 0;
|
|
1037
|
+
const resolvedElapsedMs = isTimelineProvider ? (localFrame !== void 0 && fps !== void 0 ? localFrame / fps * 1e3 : void 0) ?? props.elapsedMs : props.elapsedMs ?? (localFrame !== void 0 && fps !== void 0 ? localFrame / fps * 1e3 : void 0);
|
|
1038
|
+
const effectiveLocalFrame = localFrame + Math.round(inheritedSeekOffset * fps);
|
|
1039
|
+
let activeSeg = null;
|
|
1040
|
+
let windowStartFrame = 0;
|
|
1041
|
+
if (segments.length > 0) {
|
|
1042
|
+
const active = getCachedSegmentRanges(segments, fps).find(({ start, duration }) => effectiveLocalFrame >= start && effectiveLocalFrame < start + duration);
|
|
1043
|
+
if (active) {
|
|
1044
|
+
activeSeg = active.seg;
|
|
1045
|
+
windowStartFrame = active.start;
|
|
1046
|
+
} else return;
|
|
1047
|
+
}
|
|
1048
|
+
const segmentLocalFrame = localFrame - windowStartFrame;
|
|
1049
|
+
const accumulatedSeekOffsetSec = inheritedSeekOffset + (activeSeg ? activeSeg.startSec - windowStartFrame / fps : 0);
|
|
1050
|
+
const accumulatedClockOffsetSec = inheritedClockOffset + windowStartFrame / fps;
|
|
1051
|
+
if (typeof op.onRequestFrame === "function") op.onRequestFrame(frameCtx);
|
|
1052
|
+
else if (op.effect && typeof op.effect.notifyFrame === "function") op.effect.notifyFrame(frameCtx);
|
|
1053
|
+
const CustomRenderer = webgpuRegistry.get(op.op);
|
|
1054
|
+
if (CustomRenderer) {
|
|
1055
|
+
if (op.signals) virtualMedia = resolveSignalOperation(virtualMedia, frameCtx);
|
|
1056
|
+
const inputs = op?.inputs;
|
|
1057
|
+
if (inputs) {
|
|
1058
|
+
for (const entry of Object.values(inputs)) if (entry?.connectionValid && entry?.outputItem?.type === "LUT") {
|
|
1059
|
+
const lutVirtualMedia = entry.outputItem.data;
|
|
1060
|
+
if (lutVirtualMedia && typeof lutVirtualMedia === "object" && lutVirtualMedia.operation) {
|
|
1061
|
+
const lutW = lutVirtualMedia.metadata?.width ?? targetWidth;
|
|
1062
|
+
const lutH = lutVirtualMedia.metadata?.height ?? targetHeight;
|
|
1063
|
+
const dummyTex = ctx.renderer.getTemporaryTexture(lutW, lutH);
|
|
1064
|
+
await drawCompositionTree(ctx, encoder, dummyTex.createView(), dummyTex, lutW, lutH, lutVirtualMedia, {
|
|
1065
|
+
...props,
|
|
1066
|
+
virtualMedia: lutVirtualMedia
|
|
1067
|
+
}, accumulatedSeekOffsetSec, accumulatedClockOffsetSec);
|
|
1068
|
+
}
|
|
1069
|
+
} else if (entry?.connectionValid && entry?.outputItem?.type === "Signal") {
|
|
1070
|
+
const sigData = entry.outputItem.data;
|
|
1071
|
+
if (sigData && typeof sigData === "object") await signalRegistry.ensureAudioSourcesExtracted(ctx.device, sigData.signalConfig ?? sigData, fps, props.renderId);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
const pass = ctx.renderer.beginFrame(encoder, targetView, {
|
|
1075
|
+
r: 0,
|
|
1076
|
+
g: 0,
|
|
1077
|
+
b: 0,
|
|
1078
|
+
a: 0
|
|
1079
|
+
}, targetWidth, targetHeight, "load");
|
|
1080
|
+
let passEnded = false;
|
|
1081
|
+
const originalEnd = pass.end.bind(pass);
|
|
1082
|
+
pass.end = () => {
|
|
1083
|
+
if (!passEnded) {
|
|
1084
|
+
originalEnd();
|
|
1085
|
+
passEnded = true;
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
const renderArgs = {
|
|
1089
|
+
ctx,
|
|
1090
|
+
encoder,
|
|
1091
|
+
pass,
|
|
1092
|
+
targetView,
|
|
1093
|
+
targetTexture,
|
|
1094
|
+
targetWidth,
|
|
1095
|
+
targetHeight,
|
|
1096
|
+
props: {
|
|
1097
|
+
...props,
|
|
1098
|
+
virtualMedia,
|
|
1099
|
+
inheritedSeekOffset: accumulatedSeekOffsetSec,
|
|
1100
|
+
inheritedClockOffset: accumulatedClockOffsetSec,
|
|
1101
|
+
durationMs: resolvedDurationMs,
|
|
1102
|
+
elapsedMs: resolvedElapsedMs
|
|
1103
|
+
},
|
|
1104
|
+
drawChild: async (child, overrides, targetViewOverride, targetTextureOverride, targetWidthOverride, targetHeightOverride) => {
|
|
1105
|
+
await drawCompositionTree(ctx, encoder, targetViewOverride ?? targetView, targetTextureOverride ?? targetTexture, targetWidthOverride ?? targetWidth, targetHeightOverride ?? targetHeight, child, {
|
|
1106
|
+
...props,
|
|
1107
|
+
durationMs: resolvedDurationMs,
|
|
1108
|
+
elapsedMs: resolvedElapsedMs,
|
|
1109
|
+
virtualMedia: child,
|
|
1110
|
+
...overrides,
|
|
1111
|
+
excludeTextures: [
|
|
1112
|
+
...props.excludeTextures || [],
|
|
1113
|
+
...overrides?.excludeTextures || [],
|
|
1114
|
+
targetTextureOverride ?? targetTexture
|
|
1115
|
+
]
|
|
1116
|
+
}, isCompositor ? 0 : accumulatedSeekOffsetSec, accumulatedClockOffsetSec);
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
await CustomRenderer(renderArgs);
|
|
1120
|
+
renderArgs.pass.end();
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
if (op.op === "LUT") return;
|
|
1124
|
+
if (op.op === "Signal" || op.op === "SignalMath" || op.dataType === "Signal") {
|
|
1125
|
+
const pass = ctx.renderer.beginFrame(encoder, targetView, {
|
|
1126
|
+
r: 0,
|
|
1127
|
+
g: 0,
|
|
1128
|
+
b: 0,
|
|
1129
|
+
a: 0
|
|
1130
|
+
}, targetWidth, targetHeight, "load");
|
|
1131
|
+
await drawSignalNode(ctx, encoder, pass, {
|
|
1132
|
+
nodeId: op.nodeId || op.signalConfig?.nodeId || props.renderId,
|
|
1133
|
+
func: op.func,
|
|
1134
|
+
amplitude: Number(op.amplitude ?? 1),
|
|
1135
|
+
frequency: Number(op.frequency ?? 1),
|
|
1136
|
+
phase: Number(op.phase ?? 0),
|
|
1137
|
+
offset: Number(op.offset ?? 0),
|
|
1138
|
+
signalConfig: {
|
|
1139
|
+
...op.signalConfig,
|
|
1140
|
+
...op
|
|
1141
|
+
},
|
|
1142
|
+
frame,
|
|
1143
|
+
fps,
|
|
1144
|
+
elapsedMs: resolvedElapsedMs,
|
|
1145
|
+
durationMs: resolvedDurationMs ?? 0,
|
|
1146
|
+
width: targetWidth,
|
|
1147
|
+
height: targetHeight,
|
|
1148
|
+
drawChild: async (child, childProps, childView, childTex, childW, childH) => {
|
|
1149
|
+
await drawCompositionTree(ctx, encoder, childView, childTex, childW, childH, child, {
|
|
1150
|
+
...props,
|
|
1151
|
+
durationMs: resolvedDurationMs,
|
|
1152
|
+
elapsedMs: resolvedElapsedMs,
|
|
1153
|
+
...childProps,
|
|
1154
|
+
excludeTextures: [
|
|
1155
|
+
...props.excludeTextures || [],
|
|
1156
|
+
...childProps?.excludeTextures || [],
|
|
1157
|
+
childTex
|
|
1158
|
+
]
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
});
|
|
1162
|
+
pass.end();
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
if (op.op === "source" || op.op === "text" || op.op === "caption") {
|
|
1166
|
+
const pass = ctx.renderer.beginFrame(encoder, targetView, {
|
|
1167
|
+
r: 0,
|
|
1168
|
+
g: 0,
|
|
1169
|
+
b: 0,
|
|
1170
|
+
a: 0
|
|
1171
|
+
}, targetWidth, targetHeight, "load");
|
|
1172
|
+
if (op.op === "source") {
|
|
1173
|
+
const mediaType = getMediaType(virtualMedia);
|
|
1174
|
+
const params = computeRenderParams(virtualMedia);
|
|
1175
|
+
if (params.sourceUrl) {
|
|
1176
|
+
const containerWidth = props.containerWidth ?? ctx.surface.width;
|
|
1177
|
+
const containerHeight = props.containerHeight ?? ctx.surface.height;
|
|
1178
|
+
if (mediaType === "Image") await drawImageNode(ctx, pass, {
|
|
1179
|
+
src: params.sourceUrl,
|
|
1180
|
+
dstRect: {
|
|
1181
|
+
x: 0,
|
|
1182
|
+
y: 0,
|
|
1183
|
+
width: containerWidth,
|
|
1184
|
+
height: containerHeight
|
|
1185
|
+
},
|
|
1186
|
+
opacity: Number(op.opacity ?? 1) * Number(props.opacity ?? 1),
|
|
1187
|
+
isHeadless: props.isHeadless
|
|
1188
|
+
});
|
|
1189
|
+
else if (mediaType === "SVG") await drawSvgNode(ctx, pass, {
|
|
1190
|
+
src: params.sourceUrl,
|
|
1191
|
+
dstRect: {
|
|
1192
|
+
x: 0,
|
|
1193
|
+
y: 0,
|
|
1194
|
+
width: containerWidth,
|
|
1195
|
+
height: containerHeight
|
|
1196
|
+
},
|
|
1197
|
+
opacity: Number(op.opacity ?? 1),
|
|
1198
|
+
isHeadless: props.isHeadless
|
|
1199
|
+
});
|
|
1200
|
+
else if (mediaType === "Lottie") await drawLottieNode(ctx, pass, {
|
|
1201
|
+
src: params.sourceUrl,
|
|
1202
|
+
dstRect: {
|
|
1203
|
+
x: 0,
|
|
1204
|
+
y: 0,
|
|
1205
|
+
width: containerWidth,
|
|
1206
|
+
height: containerHeight
|
|
1207
|
+
},
|
|
1208
|
+
frame: segmentLocalFrame + Math.round(accumulatedSeekOffsetSec * fps),
|
|
1209
|
+
fps,
|
|
1210
|
+
opacity: Number(op.opacity ?? 1) * Number(props.opacity ?? 1),
|
|
1211
|
+
isHeadless: props.isHeadless
|
|
1212
|
+
});
|
|
1213
|
+
else if (mediaType === "GIF") await drawGifNode(ctx, pass, {
|
|
1214
|
+
src: params.sourceUrl,
|
|
1215
|
+
dstRect: {
|
|
1216
|
+
x: 0,
|
|
1217
|
+
y: 0,
|
|
1218
|
+
width: containerWidth,
|
|
1219
|
+
height: containerHeight
|
|
1220
|
+
},
|
|
1221
|
+
frame: segmentLocalFrame + Math.round(accumulatedSeekOffsetSec * fps),
|
|
1222
|
+
fps,
|
|
1223
|
+
opacity: Number(op.opacity ?? 1) * Number(props.opacity ?? 1),
|
|
1224
|
+
isHeadless: props.isHeadless
|
|
1225
|
+
});
|
|
1226
|
+
else if (mediaType === "Text") {
|
|
1227
|
+
const opText = { ...op };
|
|
1228
|
+
drawParagraphNode(ctx, pass, {
|
|
1229
|
+
text: opText.text || "",
|
|
1230
|
+
dstRect: {
|
|
1231
|
+
x: Number(opText.x ?? 0),
|
|
1232
|
+
y: Number(opText.y ?? 0),
|
|
1233
|
+
width: Number(opText.width ?? containerWidth),
|
|
1234
|
+
height: Number(opText.height ?? containerHeight)
|
|
1235
|
+
},
|
|
1236
|
+
fontFamily: opText.fontFamily,
|
|
1237
|
+
fontSize: Number(opText.fontSize ?? 48),
|
|
1238
|
+
color: opText.fill ?? opText.color ?? "white",
|
|
1239
|
+
width: opText.width ? Number(opText.width) : void 0,
|
|
1240
|
+
height: opText.height ? Number(opText.height) : void 0,
|
|
1241
|
+
lineHeight: Number(opText.lineHeight ?? 1.2),
|
|
1242
|
+
align: opText.align,
|
|
1243
|
+
verticalAlign: opText.verticalAlign,
|
|
1244
|
+
fontWeight: opText.fontWeight,
|
|
1245
|
+
fontStyle: opText.fontStyle,
|
|
1246
|
+
letterSpacing: opText.letterSpacing,
|
|
1247
|
+
shadows: opText.shadows,
|
|
1248
|
+
textBackgroundColor: opText.textBackgroundColor,
|
|
1249
|
+
borderRadius: opText.borderRadius != null ? Number(opText.borderRadius) : void 0,
|
|
1250
|
+
padding: opText.padding != null ? Number(opText.padding) : void 0,
|
|
1251
|
+
stroke: opText.stroke,
|
|
1252
|
+
strokeWidth: opText.strokeWidth ?? opText.strokeThickness ? Number(opText.strokeWidth ?? opText.strokeThickness) : void 0,
|
|
1253
|
+
strokeAlign: opText.strokeAlign,
|
|
1254
|
+
opacity: Number(opText.opacity ?? 1) * Number(props.opacity ?? 1),
|
|
1255
|
+
isHeadless: props.isHeadless,
|
|
1256
|
+
animation: opText.animation ?? opText.textAnimation,
|
|
1257
|
+
animators: opText.animators,
|
|
1258
|
+
pathOptions: opText.pathOptions,
|
|
1259
|
+
typewriter: opText.typewriter,
|
|
1260
|
+
marquee: opText.marquee,
|
|
1261
|
+
textProgress: opText.textProgress != null ? Number(opText.textProgress) : void 0,
|
|
1262
|
+
signals: props.signals ?? opText.signals,
|
|
1263
|
+
firstMargin: opText.firstMargin != null ? Number(opText.firstMargin) : void 0,
|
|
1264
|
+
lastMargin: opText.lastMargin != null ? Number(opText.lastMargin) : void 0,
|
|
1265
|
+
baselineShift: opText.baselineShift != null ? Number(opText.baselineShift) : void 0,
|
|
1266
|
+
frame: localFrame,
|
|
1267
|
+
fps,
|
|
1268
|
+
durationMs: resolvedDurationMs,
|
|
1269
|
+
elapsedMs: resolvedElapsedMs,
|
|
1270
|
+
isVideoMode: props.isVideoMode
|
|
1271
|
+
});
|
|
1272
|
+
} else if (mediaType === "Video") {
|
|
1273
|
+
const finalPlaybackRate = Math.max(.01, (Number(props.playbackRateOverride) || 1) * (Number(params.speed) || 1));
|
|
1274
|
+
const effectiveTrimSec = Math.max(0, (Number(props.trimStartOverride) || 0) + (Number(params.trimStartSec) || 0) + accumulatedSeekOffsetSec);
|
|
1275
|
+
const rawTimestampSec = segmentLocalFrame / fps * finalPlaybackRate + effectiveTrimSec;
|
|
1276
|
+
const timestampSec = Math.max(0, Number.isFinite(rawTimestampSec) ? rawTimestampSec : 0);
|
|
1277
|
+
await drawVideoNode(ctx, pass, {
|
|
1278
|
+
nodeId: props.renderId,
|
|
1279
|
+
frameKey: `${props.renderId ?? "video"}-${params.sourceUrl}-${Math.round(timestampSec * fps)}`,
|
|
1280
|
+
sourceUrl: params.sourceUrl,
|
|
1281
|
+
timestampSec,
|
|
1282
|
+
dstRect: {
|
|
1283
|
+
x: 0,
|
|
1284
|
+
y: 0,
|
|
1285
|
+
width: containerWidth,
|
|
1286
|
+
height: containerHeight
|
|
1287
|
+
},
|
|
1288
|
+
opacity: Number(op.opacity ?? 1) * Number(props.opacity ?? 1),
|
|
1289
|
+
isHeadless: props.isHeadless,
|
|
1290
|
+
isPlaying: props.isPlaying,
|
|
1291
|
+
forceWait: props.forceWait
|
|
1292
|
+
});
|
|
1293
|
+
} else if (mediaType === "Caption") {
|
|
1294
|
+
const opCap = {
|
|
1295
|
+
...op,
|
|
1296
|
+
...props
|
|
1297
|
+
};
|
|
1298
|
+
await drawCaptionNode(ctx, pass, {
|
|
1299
|
+
renderId: props.renderId,
|
|
1300
|
+
src: params.sourceUrl,
|
|
1301
|
+
dstRect: {
|
|
1302
|
+
x: 0,
|
|
1303
|
+
y: 0,
|
|
1304
|
+
width: containerWidth,
|
|
1305
|
+
height: containerHeight
|
|
1306
|
+
},
|
|
1307
|
+
frame: localFrame,
|
|
1308
|
+
fps,
|
|
1309
|
+
fontFamily: opCap.fontFamily,
|
|
1310
|
+
fontSize: Number(opCap.fontSize ?? 48),
|
|
1311
|
+
color: opCap.fill ?? opCap.color ?? "white",
|
|
1312
|
+
lineHeight: Number(opCap.lineHeight ?? 1.2),
|
|
1313
|
+
align: opCap.align === "start" ? "left" : opCap.align === "end" ? "right" : opCap.align ?? "center",
|
|
1314
|
+
textAlignVertical: opCap.verticalAlign ?? opCap.textAlignVertical,
|
|
1315
|
+
fontWeight: opCap.fontWeight,
|
|
1316
|
+
fontStyle: opCap.fontStyle,
|
|
1317
|
+
letterSpacing: opCap.letterSpacing,
|
|
1318
|
+
shadows: opCap.shadows,
|
|
1319
|
+
textBackgroundColor: opCap.background ?? opCap.textBackgroundColor,
|
|
1320
|
+
borderRadius: (opCap.borderRadius ?? opCap.strokeRadius) != null ? Number(opCap.borderRadius ?? opCap.strokeRadius) : void 0,
|
|
1321
|
+
strokeRadius: (opCap.strokeRadius ?? opCap.borderRadius) != null ? Number(opCap.strokeRadius ?? opCap.borderRadius) : void 0,
|
|
1322
|
+
stroke: opCap.stroke,
|
|
1323
|
+
strokeWidth: (opCap.strokeWidth ?? opCap.strokeThickness) != null ? Number(opCap.strokeWidth ?? opCap.strokeThickness) : void 0,
|
|
1324
|
+
maxWidth: opCap.maxWidth,
|
|
1325
|
+
padding: opCap.padding != null ? Number(opCap.padding) : void 0,
|
|
1326
|
+
opacity: Number(opCap.opacity ?? 1) * Number(props.opacity ?? 1),
|
|
1327
|
+
isHeadless: props.isHeadless,
|
|
1328
|
+
isVideoMode: props.isVideoMode
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
} else if (op.op === "text") {
|
|
1333
|
+
const opText = { ...op };
|
|
1334
|
+
const containerWidth = props.containerWidth ?? ctx.surface.width;
|
|
1335
|
+
const containerHeight = props.containerHeight ?? ctx.surface.height;
|
|
1336
|
+
drawParagraphNode(ctx, pass, {
|
|
1337
|
+
renderId: props.renderId,
|
|
1338
|
+
text: opText.text || "",
|
|
1339
|
+
dstRect: {
|
|
1340
|
+
x: Number(opText.x ?? 0),
|
|
1341
|
+
y: Number(opText.y ?? 0),
|
|
1342
|
+
width: Number(opText.width ?? containerWidth),
|
|
1343
|
+
height: Number(opText.height ?? containerHeight)
|
|
1344
|
+
},
|
|
1345
|
+
spans: opText.spans,
|
|
1346
|
+
fontFamily: opText.fontFamily,
|
|
1347
|
+
fontSize: Number(opText.fontSize ?? 48),
|
|
1348
|
+
color: opText.fill ?? opText.color ?? "white",
|
|
1349
|
+
width: opText.width ? Number(opText.width) : void 0,
|
|
1350
|
+
height: opText.height ? Number(opText.height) : void 0,
|
|
1351
|
+
lineHeight: Number(opText.lineHeight ?? 1.2),
|
|
1352
|
+
align: opText.align,
|
|
1353
|
+
verticalAlign: opText.verticalAlign,
|
|
1354
|
+
fontWeight: opText.fontWeight,
|
|
1355
|
+
fontStyle: opText.fontStyle,
|
|
1356
|
+
letterSpacing: opText.letterSpacing,
|
|
1357
|
+
shadows: opText.shadows,
|
|
1358
|
+
textBackgroundColor: opText.textBackgroundColor,
|
|
1359
|
+
borderRadius: (opText.borderRadius ?? opText.strokeRadius) != null ? Number(opText.borderRadius ?? opText.strokeRadius) : void 0,
|
|
1360
|
+
strokeRadius: (opText.strokeRadius ?? opText.borderRadius) != null ? Number(opText.strokeRadius ?? opText.borderRadius) : void 0,
|
|
1361
|
+
padding: opText.padding != null ? Number(opText.padding) : void 0,
|
|
1362
|
+
stroke: opText.stroke,
|
|
1363
|
+
strokeWidth: opText.strokeWidth ?? opText.strokeThickness ? Number(opText.strokeWidth ?? opText.strokeThickness) : void 0,
|
|
1364
|
+
strokeAlign: opText.strokeAlign,
|
|
1365
|
+
opacity: Number(opText.opacity ?? 1) * Number(props.opacity ?? 1),
|
|
1366
|
+
isHeadless: props.isHeadless,
|
|
1367
|
+
animation: opText.animation ?? opText.textAnimation,
|
|
1368
|
+
animators: opText.animators,
|
|
1369
|
+
pathOptions: opText.pathOptions,
|
|
1370
|
+
typewriter: opText.typewriter,
|
|
1371
|
+
marquee: opText.marquee,
|
|
1372
|
+
signals: props.signals ?? opText.signals,
|
|
1373
|
+
firstMargin: opText.firstMargin != null ? Number(opText.firstMargin) : void 0,
|
|
1374
|
+
lastMargin: opText.lastMargin != null ? Number(opText.lastMargin) : void 0,
|
|
1375
|
+
baselineShift: opText.baselineShift != null ? Number(opText.baselineShift) : void 0,
|
|
1376
|
+
frame: localFrame,
|
|
1377
|
+
fps,
|
|
1378
|
+
durationMs: resolvedDurationMs,
|
|
1379
|
+
elapsedMs: resolvedElapsedMs,
|
|
1380
|
+
isVideoMode: props.isVideoMode
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
pass.end();
|
|
1384
|
+
}
|
|
1385
|
+
if (virtualMedia.children && virtualMedia.children.length > 0) for (let i = 0; i < virtualMedia.children.length; i++) {
|
|
1386
|
+
const child = virtualMedia.children[i];
|
|
1387
|
+
if (child) await drawCompositionTree(ctx, encoder, targetView, targetTexture, targetWidth, targetHeight, child, {
|
|
1388
|
+
...props,
|
|
1389
|
+
durationMs: resolvedDurationMs,
|
|
1390
|
+
elapsedMs: resolvedElapsedMs,
|
|
1391
|
+
virtualMedia: child,
|
|
1392
|
+
renderId: `${props.renderId}-c${i}`
|
|
1393
|
+
}, isCompositor ? 0 : accumulatedSeekOffsetSec, accumulatedClockOffsetSec);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
const DEFAULT_STATE = {
|
|
1397
|
+
frame: 0,
|
|
1398
|
+
fps: 30,
|
|
1399
|
+
isPlaying: false
|
|
1400
|
+
};
|
|
1401
|
+
var CompositionStateStore = class {
|
|
1402
|
+
states = /* @__PURE__ */ new Map();
|
|
1403
|
+
listeners = /* @__PURE__ */ new Map();
|
|
1404
|
+
setState(key, frame, fps, isPlaying) {
|
|
1405
|
+
const current = this.states.get(key);
|
|
1406
|
+
const resolvedPlaying = isPlaying !== void 0 ? isPlaying : current?.isPlaying ?? false;
|
|
1407
|
+
if (current?.frame === frame && current?.fps === fps && current?.isPlaying === resolvedPlaying) return;
|
|
1408
|
+
this.states.set(key, {
|
|
1409
|
+
frame,
|
|
1410
|
+
fps,
|
|
1411
|
+
isPlaying: resolvedPlaying
|
|
1412
|
+
});
|
|
1413
|
+
this.notify(key);
|
|
1414
|
+
}
|
|
1415
|
+
getState(key) {
|
|
1416
|
+
if (this.states.has(key)) return this.states.get(key);
|
|
1417
|
+
for (const [storeKey, value] of this.states.entries()) if (key.startsWith(storeKey)) return value;
|
|
1418
|
+
return DEFAULT_STATE;
|
|
1419
|
+
}
|
|
1420
|
+
subscribe(key, listener) {
|
|
1421
|
+
if (!this.listeners.has(key)) this.listeners.set(key, /* @__PURE__ */ new Set());
|
|
1422
|
+
this.listeners.get(key).add(listener);
|
|
1423
|
+
return () => {
|
|
1424
|
+
const set = this.listeners.get(key);
|
|
1425
|
+
set?.delete(listener);
|
|
1426
|
+
if (set?.size === 0) {
|
|
1427
|
+
this.listeners.delete(key);
|
|
1428
|
+
this.states.delete(key);
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
clearKey(key) {
|
|
1433
|
+
this.states.delete(key);
|
|
1434
|
+
}
|
|
1435
|
+
notify(key) {
|
|
1436
|
+
for (const [listenerKey, set] of this.listeners.entries()) if (listenerKey === key || listenerKey.startsWith(key)) set.forEach((l) => l());
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
const compositionStateStore = new CompositionStateStore();
|
|
1440
|
+
/**
|
|
1441
|
+
* normalizeTimeline recurses through the virtual media tree and "absorbs"
|
|
1442
|
+
* generic timeline-shifting operations into standard properties
|
|
1443
|
+
* of their children.
|
|
1444
|
+
*/
|
|
1445
|
+
function normalizeTimeline(vv, fps, context = { timeOffsetSec: 0 }) {
|
|
1446
|
+
if (!vv) return vv;
|
|
1447
|
+
const { operation, metadata = {}, children = [] } = vv;
|
|
1448
|
+
const { timeOffsetSec, durationLimitMs } = context;
|
|
1449
|
+
if (!operation) return {
|
|
1450
|
+
...vv,
|
|
1451
|
+
children: (children || []).map((child) => normalizeTimeline(child, fps, context))
|
|
1452
|
+
};
|
|
1453
|
+
const timeline = operation.timeline;
|
|
1454
|
+
const segments = timeline?.segments || [];
|
|
1455
|
+
let totalDurationMs = getActiveMediaMetadata(vv)?.durationMs ?? 0;
|
|
1456
|
+
if (segments.length > 0) {
|
|
1457
|
+
const totalSegmentsFrames = segments.reduce((acc, seg) => {
|
|
1458
|
+
const durSec = seg.endSec != null ? seg.endSec - seg.startSec : 0;
|
|
1459
|
+
return acc + Math.max(1, Math.round(durSec * fps));
|
|
1460
|
+
}, 0);
|
|
1461
|
+
if (totalSegmentsFrames > 0) totalDurationMs = totalSegmentsFrames / fps * 1e3;
|
|
1462
|
+
}
|
|
1463
|
+
const newOperation = { ...operation };
|
|
1464
|
+
const rawStartFrame = timeline?.startFrame ?? newOperation.startFrame;
|
|
1465
|
+
if (typeof rawStartFrame === "number") newOperation.startFrame = rawStartFrame - secondsToFrames(timeOffsetSec, fps);
|
|
1466
|
+
const newMetadata = {
|
|
1467
|
+
...metadata,
|
|
1468
|
+
durationMs: totalDurationMs
|
|
1469
|
+
};
|
|
1470
|
+
const childContext = typeof rawStartFrame === "number" || newOperation.op === "compose" ? {
|
|
1471
|
+
timeOffsetSec: 0,
|
|
1472
|
+
durationLimitMs: void 0
|
|
1473
|
+
} : {
|
|
1474
|
+
timeOffsetSec,
|
|
1475
|
+
durationLimitMs
|
|
1476
|
+
};
|
|
1477
|
+
return {
|
|
1478
|
+
metadata: newMetadata,
|
|
1479
|
+
operation: newOperation,
|
|
1480
|
+
children: (children || []).map((child) => normalizeTimeline(child, fps, childContext))
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
const verbose = typeof process !== "undefined" && /^(debug|trace)$/i.test(process.env?.LOG_LEVEL ?? "");
|
|
1484
|
+
let mediaLogger = {
|
|
1485
|
+
debug: (msg, ...args) => {
|
|
1486
|
+
if (!verbose) return;
|
|
1487
|
+
if (typeof msg === "object" && msg !== null) console.info("[AudioExtractor]", msg, ...args);
|
|
1488
|
+
else console.info(`[AudioExtractor] ${msg}`, ...args);
|
|
1489
|
+
},
|
|
1490
|
+
warn: (msg, ...args) => {
|
|
1491
|
+
if (typeof msg === "object" && msg !== null) console.warn("[AudioExtractor]", msg, ...args);
|
|
1492
|
+
else console.warn(`[AudioExtractor] ${msg}`, ...args);
|
|
1493
|
+
},
|
|
1494
|
+
error: (msg, ...args) => {
|
|
1495
|
+
if (typeof msg === "object" && msg !== null) console.error("[AudioExtractor]", msg, ...args);
|
|
1496
|
+
else console.error(`[AudioExtractor] ${msg}`, ...args);
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
if (typeof window === "undefined" || typeof process !== "undefined" && process.versions?.node) import(
|
|
1500
|
+
/* webpackIgnore: true */
|
|
1501
|
+
/* @vite-ignore */
|
|
1502
|
+
"@framefields/server-utils"
|
|
1503
|
+
).then((m) => {
|
|
1504
|
+
if (m.mediaLogger) mediaLogger = m.mediaLogger;
|
|
1505
|
+
}).catch(() => {});
|
|
1506
|
+
const yieldToMain = () => {
|
|
1507
|
+
if (typeof window === "undefined") return Promise.resolve();
|
|
1508
|
+
const sched = globalThis.scheduler;
|
|
1509
|
+
return typeof sched?.yield === "function" ? sched.yield() : new Promise((resolve) => setTimeout(resolve, 0));
|
|
1510
|
+
};
|
|
1511
|
+
const waitForDelayRender = async (timeoutMs = 3e4) => {
|
|
1512
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1513
|
+
const start = Date.now();
|
|
1514
|
+
return new Promise((resolve) => {
|
|
1515
|
+
const check = () => {
|
|
1516
|
+
const browserHandles = typeof window !== "undefined" && window.renderer_delayRenderHandles ? window.renderer_delayRenderHandles : [];
|
|
1517
|
+
const globalDelays = typeof globalThis !== "undefined" ? globalThis.__GATEWAI_DELAYS__ : null;
|
|
1518
|
+
const hasBrowserDelays = browserHandles.length > 0;
|
|
1519
|
+
const hasGlobalDelays = globalDelays instanceof Set && globalDelays.size > 0;
|
|
1520
|
+
if (!hasBrowserDelays && !hasGlobalDelays) {
|
|
1521
|
+
resolve();
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
if (Date.now() - start > timeoutMs) {
|
|
1525
|
+
mediaLogger.warn(`[AudioExtractor] waitForDelayRender timed out waiting for handles: ${JSON.stringify({
|
|
1526
|
+
browserHandles,
|
|
1527
|
+
globalDelays: globalDelays ? Array.from(globalDelays) : []
|
|
1528
|
+
})}`);
|
|
1529
|
+
resolve();
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1532
|
+
setTimeout(check, 50);
|
|
1533
|
+
};
|
|
1534
|
+
check();
|
|
1535
|
+
});
|
|
1536
|
+
};
|
|
1537
|
+
/**
|
|
1538
|
+
* Decodes all audio samples from a given source URL into raw Float32 mono/stereo channel buffers.
|
|
1539
|
+
*/
|
|
1540
|
+
async function decodeAudioSource(url) {
|
|
1541
|
+
mediaLogger.debug(`[AudioExtractor] decodeAudioSource started for url: ${url}`);
|
|
1542
|
+
try {
|
|
1543
|
+
if (typeof window !== "undefined" && typeof window.document !== "undefined" && !(typeof process !== "undefined" && process.versions && process.versions.node)) {
|
|
1544
|
+
mediaLogger.debug(`[AudioExtractor] Browser detected. Fetching arrayBuffer for ${url}...`);
|
|
1545
|
+
const AudioContextClass = window.AudioContext || window.webkitAudioContext;
|
|
1546
|
+
if (!AudioContextClass) throw new Error("AudioContext is not supported in this browser");
|
|
1547
|
+
const audioCtx = new AudioContextClass();
|
|
1548
|
+
try {
|
|
1549
|
+
const response = await fetch(url);
|
|
1550
|
+
mediaLogger.debug(`[AudioExtractor] Fetch response status for ${url}: ${response.status} (${response.statusText})`);
|
|
1551
|
+
if (!response.ok) throw new Error(`Failed to fetch audio source: ${response.statusText}`);
|
|
1552
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
1553
|
+
mediaLogger.debug(`[AudioExtractor] Fetched ${arrayBuffer.byteLength} bytes. Decoding audio data...`);
|
|
1554
|
+
const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
|
|
1555
|
+
mediaLogger.debug(`[AudioExtractor] Decoded successfully: ${audioBuffer.numberOfChannels} channels, sampleRate: ${audioBuffer.sampleRate}, duration: ${audioBuffer.duration}s`);
|
|
1556
|
+
const channels = [];
|
|
1557
|
+
for (let c = 0; c < audioBuffer.numberOfChannels; c++) channels.push(new Float32Array(audioBuffer.getChannelData(c)));
|
|
1558
|
+
return {
|
|
1559
|
+
channels,
|
|
1560
|
+
sampleRate: audioBuffer.sampleRate
|
|
1561
|
+
};
|
|
1562
|
+
} finally {
|
|
1563
|
+
audioCtx.close();
|
|
1564
|
+
mediaLogger.debug(`[AudioExtractor] AudioContext closed for ${url}`);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
let inputAcquired = false;
|
|
1568
|
+
try {
|
|
1569
|
+
mediaLogger.debug(`[AudioExtractor] Server / Node.js detected. Acquiring from inputStore for ${url}...`);
|
|
1570
|
+
const input = await inputStore.acquire(url);
|
|
1571
|
+
inputAcquired = true;
|
|
1572
|
+
mediaLogger.debug(`[AudioExtractor] inputStore acquired. Retrieving primary audio track...`);
|
|
1573
|
+
const track = await input.getPrimaryAudioTrack();
|
|
1574
|
+
if (!track) {
|
|
1575
|
+
mediaLogger.warn(`[AudioExtractor] No primary audio track found in input for ${url}`);
|
|
1576
|
+
return null;
|
|
1577
|
+
}
|
|
1578
|
+
const generator = new AudioSampleSink(track).samples(0);
|
|
1579
|
+
const decodedPlanes = [];
|
|
1580
|
+
let totalFrames = 0;
|
|
1581
|
+
let sampleRate = 48e3;
|
|
1582
|
+
let numChannels = 1;
|
|
1583
|
+
mediaLogger.debug(`[AudioExtractor] Starting mediabunny generator loop for ${url}...`);
|
|
1584
|
+
for await (const sample of generator) {
|
|
1585
|
+
sampleRate = sample.sampleRate;
|
|
1586
|
+
numChannels = sample.numberOfChannels;
|
|
1587
|
+
const sampleFrames = sample.numberOfFrames;
|
|
1588
|
+
if (decodedPlanes.length === 0) for (let c = 0; c < numChannels; c++) decodedPlanes.push([]);
|
|
1589
|
+
for (let c = 0; c < numChannels; c++) {
|
|
1590
|
+
let planeBuffer;
|
|
1591
|
+
try {
|
|
1592
|
+
const allocSize = sample.allocationSize({
|
|
1593
|
+
planeIndex: c,
|
|
1594
|
+
format: "f32-planar"
|
|
1595
|
+
});
|
|
1596
|
+
planeBuffer = new Float32Array(allocSize / 4);
|
|
1597
|
+
sample.copyTo(planeBuffer, {
|
|
1598
|
+
planeIndex: c,
|
|
1599
|
+
format: "f32-planar"
|
|
1600
|
+
});
|
|
1601
|
+
} catch {
|
|
1602
|
+
const allocSize = sample.allocationSize({ planeIndex: c });
|
|
1603
|
+
if (sample.format === "s16" || sample.format === "s16-planar") {
|
|
1604
|
+
const int16Buffer = new Int16Array(allocSize / 2);
|
|
1605
|
+
sample.copyTo(int16Buffer, { planeIndex: c });
|
|
1606
|
+
planeBuffer = new Float32Array(int16Buffer.length);
|
|
1607
|
+
for (let i = 0; i < int16Buffer.length; i++) planeBuffer[i] = (int16Buffer[i] ?? 0) / 32768;
|
|
1608
|
+
} else if (sample.format === "s32" || sample.format === "s32-planar") {
|
|
1609
|
+
const int32Buffer = new Int32Array(allocSize / 4);
|
|
1610
|
+
sample.copyTo(int32Buffer, { planeIndex: c });
|
|
1611
|
+
planeBuffer = new Float32Array(int32Buffer.length);
|
|
1612
|
+
for (let i = 0; i < int32Buffer.length; i++) planeBuffer[i] = (int32Buffer[i] ?? 0) / 2147483648;
|
|
1613
|
+
} else if (sample.format === "u8" || sample.format === "u8-planar") {
|
|
1614
|
+
const u8Buffer = new Uint8Array(allocSize);
|
|
1615
|
+
sample.copyTo(u8Buffer, { planeIndex: c });
|
|
1616
|
+
planeBuffer = new Float32Array(u8Buffer.length);
|
|
1617
|
+
for (let i = 0; i < u8Buffer.length; i++) planeBuffer[i] = ((u8Buffer[i] ?? 128) - 128) / 128;
|
|
1618
|
+
} else {
|
|
1619
|
+
planeBuffer = new Float32Array(allocSize / 4);
|
|
1620
|
+
sample.copyTo(planeBuffer, { planeIndex: c });
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
decodedPlanes[c].push(planeBuffer);
|
|
1624
|
+
}
|
|
1625
|
+
totalFrames += sampleFrames;
|
|
1626
|
+
sample.close();
|
|
1627
|
+
}
|
|
1628
|
+
mediaLogger.debug(`[AudioExtractor] Generator loop finished. Decoded total frames: ${totalFrames}`);
|
|
1629
|
+
if (totalFrames === 0 || decodedPlanes.length === 0) return null;
|
|
1630
|
+
return {
|
|
1631
|
+
channels: decodedPlanes.map((planes) => {
|
|
1632
|
+
const merged = new Float32Array(totalFrames);
|
|
1633
|
+
let offset = 0;
|
|
1634
|
+
for (const plane of planes) {
|
|
1635
|
+
merged.set(plane, offset);
|
|
1636
|
+
offset += plane.length;
|
|
1637
|
+
}
|
|
1638
|
+
return merged;
|
|
1639
|
+
}),
|
|
1640
|
+
sampleRate
|
|
1641
|
+
};
|
|
1642
|
+
} catch (err) {
|
|
1643
|
+
if (typeof process !== "undefined" && process.versions?.node) try {
|
|
1644
|
+
const { execSync } = await import("node:child_process");
|
|
1645
|
+
const stdout = execSync(`ffmpeg -v error -i "${url}" -f f32le -ar 48000 -ac 2 pipe:1`, { maxBuffer: 100 * 1024 * 1024 });
|
|
1646
|
+
const totalSamples = stdout.byteLength / 4;
|
|
1647
|
+
const numFrames = totalSamples / 2;
|
|
1648
|
+
const interleaved = new Float32Array(stdout.buffer, stdout.byteOffset, totalSamples);
|
|
1649
|
+
const left = new Float32Array(numFrames);
|
|
1650
|
+
const right = new Float32Array(numFrames);
|
|
1651
|
+
for (let i = 0; i < numFrames; i++) {
|
|
1652
|
+
left[i] = interleaved[i * 2];
|
|
1653
|
+
right[i] = interleaved[i * 2 + 1];
|
|
1654
|
+
}
|
|
1655
|
+
return {
|
|
1656
|
+
channels: [left, right],
|
|
1657
|
+
sampleRate: 48e3
|
|
1658
|
+
};
|
|
1659
|
+
} catch (ffmpegErr) {
|
|
1660
|
+
mediaLogger.warn({ ffmpegErr }, `[AudioExtractor] ffmpeg fallback decode failed for ${url}`);
|
|
1661
|
+
}
|
|
1662
|
+
mediaLogger.error({ err }, `[AudioExtractor] Failed to decode source ${url}`);
|
|
1663
|
+
return null;
|
|
1664
|
+
} finally {
|
|
1665
|
+
if (inputAcquired) inputStore.release(url);
|
|
1666
|
+
}
|
|
1667
|
+
} catch (err) {
|
|
1668
|
+
mediaLogger.error({ err }, `[AudioExtractor] Failed to decode source ${url}`);
|
|
1669
|
+
return null;
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
/**
|
|
1673
|
+
* Resamples a PCM buffer using linear interpolation to target sample rate & speed.
|
|
1674
|
+
*/
|
|
1675
|
+
async function resampleAndStretchPCM(inputChannel, sourceSampleRate, targetSampleRate, speed, outputLength, trimOffsetSamples) {
|
|
1676
|
+
const output = new Float32Array(outputLength);
|
|
1677
|
+
const factor = sourceSampleRate / targetSampleRate * speed;
|
|
1678
|
+
const YIELD_INTERVAL = 1e5;
|
|
1679
|
+
for (let i = 0; i < outputLength; i++) {
|
|
1680
|
+
if (i > 0 && i % YIELD_INTERVAL === 0) await yieldToMain();
|
|
1681
|
+
const srcIndex = trimOffsetSamples + i * factor;
|
|
1682
|
+
const indexFloor = Math.floor(srcIndex);
|
|
1683
|
+
const indexCeil = Math.ceil(srcIndex);
|
|
1684
|
+
if (indexFloor < 0) {
|
|
1685
|
+
output[i] = 0;
|
|
1686
|
+
continue;
|
|
1687
|
+
}
|
|
1688
|
+
if (indexFloor >= inputChannel.length) break;
|
|
1689
|
+
const weight = srcIndex - indexFloor;
|
|
1690
|
+
const sampleFloor = inputChannel[indexFloor] ?? 0;
|
|
1691
|
+
const val = sampleFloor + weight * ((indexCeil >= 0 && indexCeil < inputChannel.length ? inputChannel[indexCeil] ?? sampleFloor : sampleFloor) - sampleFloor);
|
|
1692
|
+
output[i] = Number.isFinite(val) ? val : 0;
|
|
1693
|
+
}
|
|
1694
|
+
return output;
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Recursively parses the VirtualMediaData tree and mixes all active audio tracks
|
|
1698
|
+
* into a single unified stereo PCM stream (Float32Array channels).
|
|
1699
|
+
*/
|
|
1700
|
+
async function mixAudioTracks(virtualMedia, fps, targetSampleRate = 48e3, device, renderId) {
|
|
1701
|
+
mediaLogger.debug(`[AudioExtractor] mixAudioTracks started. FPS: ${fps}, targetSampleRate: ${targetSampleRate}`);
|
|
1702
|
+
await waitForDelayRender();
|
|
1703
|
+
shaderStore.registerSignalsFromComposition(renderId, virtualMedia);
|
|
1704
|
+
const durationMs = getActiveMediaMetadata(virtualMedia)?.durationMs || 1e3;
|
|
1705
|
+
const totalDurationSec = durationMs / 1e3;
|
|
1706
|
+
const totalTargetSamples = Math.ceil(totalDurationSec * targetSampleRate);
|
|
1707
|
+
mediaLogger.debug(`[AudioExtractor] Composition total duration: ${durationMs}ms (${totalDurationSec}s). Total mixed samples to allocate: ${totalTargetSamples}`);
|
|
1708
|
+
const outputLeft = new Float32Array(totalTargetSamples);
|
|
1709
|
+
const outputRight = new Float32Array(totalTargetSamples);
|
|
1710
|
+
const mixedChannels = [outputLeft, outputRight];
|
|
1711
|
+
const decodedCache = /* @__PURE__ */ new Map();
|
|
1712
|
+
async function traverse(node, inheritedSeekSec, inheritedClockFrames, inheritedVolume, inheritedSpeed, inheritedDurationFrames) {
|
|
1713
|
+
if (!node) return null;
|
|
1714
|
+
const op = node.operation;
|
|
1715
|
+
if (!op) {
|
|
1716
|
+
const durationMs$1 = getActiveMediaMetadata(node)?.durationMs ?? 0;
|
|
1717
|
+
const durationFrames = Math.round(durationMs$1 / 1e3 * fps);
|
|
1718
|
+
const actualDurationFrames = inheritedDurationFrames !== null ? durationFrames > 0 ? Math.min(inheritedDurationFrames, durationFrames) : inheritedDurationFrames : durationFrames;
|
|
1719
|
+
const localSamplesCount$1 = Math.ceil(actualDurationFrames / fps * targetSampleRate);
|
|
1720
|
+
if (localSamplesCount$1 <= 0) return null;
|
|
1721
|
+
const localChannels$1 = [new Float32Array(localSamplesCount$1), new Float32Array(localSamplesCount$1)];
|
|
1722
|
+
for (const child of node.children) {
|
|
1723
|
+
const childChannels = await traverse(child, inheritedSeekSec, inheritedClockFrames, inheritedVolume, inheritedSpeed, actualDurationFrames);
|
|
1724
|
+
if (childChannels) {
|
|
1725
|
+
const childOp = child.operation;
|
|
1726
|
+
const childStartFrame = childOp?.startFrame ?? childOp?.timeline?.startFrame ?? 0;
|
|
1727
|
+
const childStartSample = Math.round(childStartFrame / fps * targetSampleRate);
|
|
1728
|
+
for (let c = 0; c < 2; c++) {
|
|
1729
|
+
const dest = localChannels$1[c];
|
|
1730
|
+
const src = childChannels[c];
|
|
1731
|
+
const len = Math.min(src.length, dest.length - childStartSample);
|
|
1732
|
+
for (let i = 0; i < len; i++) if (childStartSample + i >= 0) dest[childStartSample + i] += src[i];
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
return localChannels$1;
|
|
1737
|
+
}
|
|
1738
|
+
const volume = inheritedVolume * (op.volume ?? 1) * (op.opacity === 0 ? 0 : 1) * (op.muted ? 0 : 1);
|
|
1739
|
+
const speedMultiplier = inheritedSpeed;
|
|
1740
|
+
const localClockFrames = inheritedClockFrames + (op.startFrame ?? op.timeline?.startFrame ?? 0);
|
|
1741
|
+
const segments = op.timeline?.segments || [];
|
|
1742
|
+
const nodeDurationMs = getActiveMediaMetadata(node)?.durationMs ?? 0;
|
|
1743
|
+
const nodeDurationFrames = Math.round(nodeDurationMs / 1e3 * fps);
|
|
1744
|
+
const nodeActualDurationFrames = inheritedDurationFrames !== null ? nodeDurationFrames > 0 ? Math.min(inheritedDurationFrames, nodeDurationFrames) : inheritedDurationFrames : nodeDurationFrames;
|
|
1745
|
+
const localSamplesCount = Math.ceil(nodeActualDurationFrames / fps * targetSampleRate);
|
|
1746
|
+
if (localSamplesCount <= 0) return null;
|
|
1747
|
+
const localLeft = new Float32Array(localSamplesCount);
|
|
1748
|
+
const localRight = new Float32Array(localSamplesCount);
|
|
1749
|
+
const localChannels = [localLeft, localRight];
|
|
1750
|
+
const processSegment = async (seg, windowStartFrameOffset) => {
|
|
1751
|
+
const totalSeekSec = inheritedSeekSec + (seg ? seg.startSec : 0);
|
|
1752
|
+
const totalClockFrames = localClockFrames + windowStartFrameOffset;
|
|
1753
|
+
let segDurationFrames = 0;
|
|
1754
|
+
if (seg) segDurationFrames = Math.max(1, Math.round(((seg.endSec ?? 0) - seg.startSec) * fps));
|
|
1755
|
+
else segDurationFrames = nodeDurationFrames;
|
|
1756
|
+
const actualDurationFrames = inheritedDurationFrames !== null ? Math.min(inheritedDurationFrames, segDurationFrames) : segDurationFrames;
|
|
1757
|
+
const segmentStartSample = Math.round(windowStartFrameOffset / fps * targetSampleRate);
|
|
1758
|
+
if (op.op === "source") {
|
|
1759
|
+
const mediaType = getMediaType(node);
|
|
1760
|
+
const params = computeRenderParams(node);
|
|
1761
|
+
if (params.sourceUrl && (mediaType === "Audio" || mediaType === "Video") && volume > 0) {
|
|
1762
|
+
const finalSpeed = Math.max(.5, speedMultiplier * (Number(params.speed) || 1));
|
|
1763
|
+
const effectiveTrimSec = Math.max(0, (Number(params.trimStartSec) || 0) + totalSeekSec);
|
|
1764
|
+
let decoded = decodedCache.get(params.sourceUrl);
|
|
1765
|
+
if (decoded === void 0) {
|
|
1766
|
+
decoded = await decodeAudioSource(params.sourceUrl);
|
|
1767
|
+
decodedCache.set(params.sourceUrl, decoded);
|
|
1768
|
+
}
|
|
1769
|
+
if (decoded) {
|
|
1770
|
+
const clipDurationSec = actualDurationFrames / fps;
|
|
1771
|
+
const clipSamplesCount = Math.min(localSamplesCount - segmentStartSample, Math.ceil(clipDurationSec * targetSampleRate));
|
|
1772
|
+
if (clipSamplesCount > 0 && segmentStartSample < localSamplesCount) {
|
|
1773
|
+
const trimOffsetSamples = Math.round(effectiveTrimSec * decoded.sampleRate);
|
|
1774
|
+
const srcLeft = decoded.channels[0];
|
|
1775
|
+
const srcRight = decoded.channels.length > 1 ? decoded.channels[1] : decoded.channels[0];
|
|
1776
|
+
const stretchedLeft = await resampleAndStretchPCM(srcLeft, decoded.sampleRate, targetSampleRate, finalSpeed, clipSamplesCount, trimOffsetSamples);
|
|
1777
|
+
const stretchedRight = await resampleAndStretchPCM(srcRight, decoded.sampleRate, targetSampleRate, finalSpeed, clipSamplesCount, trimOffsetSamples);
|
|
1778
|
+
for (let i = 0; i < clipSamplesCount; i++) {
|
|
1779
|
+
const outIndex = segmentStartSample + i;
|
|
1780
|
+
localLeft[outIndex] += stretchedLeft[i] * volume;
|
|
1781
|
+
localRight[outIndex] += stretchedRight[i] * volume;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
await yieldToMain();
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
if (node.children) for (const child of node.children) {
|
|
1789
|
+
const childChannels = await traverse(child, totalSeekSec, totalClockFrames, volume, speedMultiplier, actualDurationFrames);
|
|
1790
|
+
if (childChannels) {
|
|
1791
|
+
const childOp = child.operation;
|
|
1792
|
+
const childStartFrame = childOp?.startFrame ?? childOp?.timeline?.startFrame ?? 0;
|
|
1793
|
+
const destStartSample = segmentStartSample + Math.round(childStartFrame / fps * targetSampleRate);
|
|
1794
|
+
for (let c = 0; c < 2; c++) {
|
|
1795
|
+
const dest = localChannels[c];
|
|
1796
|
+
const src = childChannels[c];
|
|
1797
|
+
const len = Math.min(src.length, dest.length - destStartSample);
|
|
1798
|
+
for (let i = 0; i < len; i++) if (destStartSample + i >= 0) dest[destStartSample + i] += src[i];
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
const pluginProcessor = audioRegistry.get(op.op);
|
|
1803
|
+
if (pluginProcessor) try {
|
|
1804
|
+
const clipDurationSec = actualDurationFrames / fps;
|
|
1805
|
+
const clipSamplesCount = Math.min(localSamplesCount - segmentStartSample, Math.ceil(clipDurationSec * targetSampleRate));
|
|
1806
|
+
if (clipSamplesCount > 0 && segmentStartSample < localSamplesCount && segmentStartSample >= 0) await pluginProcessor(localChannels.map((ch) => ch.subarray(segmentStartSample, segmentStartSample + clipSamplesCount)), targetSampleRate, node, {
|
|
1807
|
+
device,
|
|
1808
|
+
frame: totalClockFrames,
|
|
1809
|
+
fps,
|
|
1810
|
+
renderId,
|
|
1811
|
+
elapsedMs: (totalClockFrames / fps + totalSeekSec) * 1e3,
|
|
1812
|
+
durationMs: getActiveMediaMetadata(node)?.durationMs ?? void 0
|
|
1813
|
+
});
|
|
1814
|
+
} catch (pluginErr) {
|
|
1815
|
+
mediaLogger.error({ err: pluginErr }, `[AudioExtractor] Custom plugin for operation '${op.op}' failed`);
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
if (segments.length > 0) {
|
|
1819
|
+
let currentStart = 0;
|
|
1820
|
+
for (const seg of segments) {
|
|
1821
|
+
const durSec = (seg.endSec ?? 0) - seg.startSec;
|
|
1822
|
+
const durFrames = Math.max(1, Math.round(durSec * fps));
|
|
1823
|
+
await processSegment(seg, currentStart);
|
|
1824
|
+
currentStart += durFrames;
|
|
1825
|
+
}
|
|
1826
|
+
} else await processSegment(null, 0);
|
|
1827
|
+
return localChannels;
|
|
1828
|
+
}
|
|
1829
|
+
const rootChannels = await traverse(normalizeTimeline(virtualMedia, fps), 0, 0, 1, 1, null);
|
|
1830
|
+
if (rootChannels) for (let c = 0; c < 2; c++) {
|
|
1831
|
+
const dest = mixedChannels[c];
|
|
1832
|
+
const src = rootChannels[c];
|
|
1833
|
+
const len = Math.min(src.length, dest.length);
|
|
1834
|
+
for (let i = 0; i < len; i++) dest[i] = src[i];
|
|
1835
|
+
}
|
|
1836
|
+
decodedCache.clear();
|
|
1837
|
+
let mixPeak = 0;
|
|
1838
|
+
for (let i = 0; i < totalTargetSamples; i++) {
|
|
1839
|
+
const l = Math.abs(outputLeft[i] ?? 0);
|
|
1840
|
+
const r = Math.abs(outputRight[i] ?? 0);
|
|
1841
|
+
if (l > mixPeak) mixPeak = l;
|
|
1842
|
+
if (r > mixPeak) mixPeak = r;
|
|
1843
|
+
}
|
|
1844
|
+
const autoGain = mixPeak > .95 ? .92 / mixPeak : 1;
|
|
1845
|
+
for (let i = 0; i < totalTargetSamples; i++) {
|
|
1846
|
+
const l = (outputLeft[i] ?? 0) * autoGain;
|
|
1847
|
+
const r = (outputRight[i] ?? 0) * autoGain;
|
|
1848
|
+
outputLeft[i] = Number.isFinite(l) ? Math.tanh(l) : 0;
|
|
1849
|
+
outputRight[i] = Number.isFinite(r) ? Math.tanh(r) : 0;
|
|
1850
|
+
}
|
|
1851
|
+
return {
|
|
1852
|
+
channels: mixedChannels,
|
|
1853
|
+
sampleRate: targetSampleRate
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
//#endregion
|
|
1858
|
+
export { springCalculation as S, measureTextAsync as _, resolveLayerDuration as a, requiresIsolation as b, MAX_LIGHTS as c, bezier as d, computeStrokeRect as f, measureText as g, measureSpring as h, mixAudioTracks as i, Matrix4Math as l, mapBlendModeToSkia as m, decodeAudioSource as n, Easing as o, interpolate as p, drawCompositionTree as r, LIGHT_UNIFORM_SIZE_BYTES as s, compositionStateStore as t, Vector3Math as u, parseColorToRgb as v, spring as x, preloadFont as y };
|
|
1859
|
+
//# sourceMappingURL=dist-1iUYuPct.mjs.map
|