@ignix-social/editor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/NOTICE +54 -0
- package/README.md +23 -0
- package/bin/ignix-editor.mjs +8 -0
- package/package.json +53 -0
- package/patches/index.mjs +53 -0
- package/scripts/build-ffmpeg-macos.sh +35 -0
- package/scripts/build-whisper-macos.sh +21 -0
- package/scripts/vendor.mjs +41 -0
- package/skills/ignix-editor/SKILL.md +132 -0
- package/src/audio.mjs +31 -0
- package/src/binaries.json +46 -0
- package/src/binaries.mjs +83 -0
- package/src/cli.mjs +254 -0
- package/src/prepare.mjs +74 -0
- package/src/runtime/ignix-frame.js +92 -0
- package/src/transcribe.mjs +71 -0
- package/src/validate.mjs +71 -0
- package/templates/blank/index.html +41 -0
- package/vendor/hyperframes/README.md +181 -0
- package/vendor/hyperframes/UPSTREAM.json +12 -0
- package/vendor/hyperframes/bin/hyperframes-localize-fonts.mjs +12 -0
- package/vendor/hyperframes/bin/hyperframes.mjs +11 -0
- package/vendor/hyperframes/dist/add-LR3ZR2A5.js +79 -0
- package/vendor/hyperframes/dist/agentPromptGenerator-VIIPZCJ3.js +143 -0
- package/vendor/hyperframes/dist/animatedGifPrep-P2T6YM7Z.js +34 -0
- package/vendor/hyperframes/dist/asset-BE2DOV72.js +26 -0
- package/vendor/hyperframes/dist/assetCataloger-VBLPHX24.js +340 -0
- package/vendor/hyperframes/dist/auth-RCQB2ZT7.js +60 -0
- package/vendor/hyperframes/dist/autoUpdate-RJAX3DAZ.js +268 -0
- package/vendor/hyperframes/dist/backgroundChecks-H2LCUIMJ.js +61 -0
- package/vendor/hyperframes/dist/backgroundChecksWorker.js +26 -0
- package/vendor/hyperframes/dist/batchRender-FT7AP7XH.js +355 -0
- package/vendor/hyperframes/dist/beat-analyzer.global.js +338 -0
- package/vendor/hyperframes/dist/beats-Y2EOP72P.js +309 -0
- package/vendor/hyperframes/dist/benchmark-MZ7GY3JW.js +231 -0
- package/vendor/hyperframes/dist/browser-HUTAMRQE.js +237 -0
- package/vendor/hyperframes/dist/bundleWithLocalizedFonts-5QOPOB5D.js +52 -0
- package/vendor/hyperframes/dist/capture-RLZA6EMR.js +4079 -0
- package/vendor/hyperframes/dist/capture-SZZ4IYJK.js +290 -0
- package/vendor/hyperframes/dist/captureFile-LYOJOUIE.js +15 -0
- package/vendor/hyperframes/dist/captureTimeout-PA4FYWT5.js +27 -0
- package/vendor/hyperframes/dist/catalog-KYU55EWR.js +1001 -0
- package/vendor/hyperframes/dist/check-TCG4PXLR.js +1697 -0
- package/vendor/hyperframes/dist/checkBrowser-RPMO4OW5.js +1032 -0
- package/vendor/hyperframes/dist/chunk-2EAXUCCE.js +88 -0
- package/vendor/hyperframes/dist/chunk-2EGFTPWD.js +1077 -0
- package/vendor/hyperframes/dist/chunk-2PSPARWP.js +6058 -0
- package/vendor/hyperframes/dist/chunk-2YN64IN5.js +5747 -0
- package/vendor/hyperframes/dist/chunk-3GXQPCJC.js +682 -0
- package/vendor/hyperframes/dist/chunk-3ZP5DXE7.js +15 -0
- package/vendor/hyperframes/dist/chunk-4NWOGZZS.js +1990 -0
- package/vendor/hyperframes/dist/chunk-4PFZPP2N.js +587 -0
- package/vendor/hyperframes/dist/chunk-4THIAPBL.js +128 -0
- package/vendor/hyperframes/dist/chunk-4YYJOFKS.js +28 -0
- package/vendor/hyperframes/dist/chunk-54HJ63Q2.js +29 -0
- package/vendor/hyperframes/dist/chunk-5ETJX6WM.js +89 -0
- package/vendor/hyperframes/dist/chunk-5IAKAQA7.js +389 -0
- package/vendor/hyperframes/dist/chunk-5Z63TBTX.js +37 -0
- package/vendor/hyperframes/dist/chunk-6BEFEWFB.js +25 -0
- package/vendor/hyperframes/dist/chunk-6CSYCFQV.js +68 -0
- package/vendor/hyperframes/dist/chunk-6CTIGJY7.js +154 -0
- package/vendor/hyperframes/dist/chunk-7HG4BFIN.js +93 -0
- package/vendor/hyperframes/dist/chunk-7JZ4FXP2.js +118 -0
- package/vendor/hyperframes/dist/chunk-A2Z4Z4VL.js +2961 -0
- package/vendor/hyperframes/dist/chunk-AMKC3AXA.js +25 -0
- package/vendor/hyperframes/dist/chunk-AVUUN2XD.js +4847 -0
- package/vendor/hyperframes/dist/chunk-AWDFDFI3.js +46 -0
- package/vendor/hyperframes/dist/chunk-AWNBM3MZ.js +94 -0
- package/vendor/hyperframes/dist/chunk-BXCMXMJQ.js +73 -0
- package/vendor/hyperframes/dist/chunk-BZ56MTDX.js +6 -0
- package/vendor/hyperframes/dist/chunk-CFKU7HTK.js +171 -0
- package/vendor/hyperframes/dist/chunk-CWPVM2QV.js +308 -0
- package/vendor/hyperframes/dist/chunk-DPVXBVLL.js +31292 -0
- package/vendor/hyperframes/dist/chunk-DQBY7FRR.js +397 -0
- package/vendor/hyperframes/dist/chunk-E6RPWJVC.js +213 -0
- package/vendor/hyperframes/dist/chunk-EISRN4E6.js +294 -0
- package/vendor/hyperframes/dist/chunk-EOVYQ3IG.js +143 -0
- package/vendor/hyperframes/dist/chunk-F3WZGU7C.js +479 -0
- package/vendor/hyperframes/dist/chunk-FCSIGXXP.js +366 -0
- package/vendor/hyperframes/dist/chunk-FI4I7CME.js +56 -0
- package/vendor/hyperframes/dist/chunk-FLWXXDNS.js +15 -0
- package/vendor/hyperframes/dist/chunk-GK4AIFIH.js +11171 -0
- package/vendor/hyperframes/dist/chunk-GMECXFAN.js +57 -0
- package/vendor/hyperframes/dist/chunk-GULOKZLI.js +155 -0
- package/vendor/hyperframes/dist/chunk-H4YZZ2VQ.js +68 -0
- package/vendor/hyperframes/dist/chunk-H6QMKUYA.js +477 -0
- package/vendor/hyperframes/dist/chunk-HBBJFK6I.js +273 -0
- package/vendor/hyperframes/dist/chunk-HRUGC23L.js +212 -0
- package/vendor/hyperframes/dist/chunk-HVW7ABXD.js +19 -0
- package/vendor/hyperframes/dist/chunk-HW6OYASV.js +344 -0
- package/vendor/hyperframes/dist/chunk-HWKCIWQT.js +3578 -0
- package/vendor/hyperframes/dist/chunk-I465DBM6.js +1214 -0
- package/vendor/hyperframes/dist/chunk-IGLEPPTN.js +24 -0
- package/vendor/hyperframes/dist/chunk-IGNAAHS3.js +433 -0
- package/vendor/hyperframes/dist/chunk-IHFUKJOR.js +85 -0
- package/vendor/hyperframes/dist/chunk-IQ3OUQ5Z.js +213 -0
- package/vendor/hyperframes/dist/chunk-ISN5GRYI.js +20 -0
- package/vendor/hyperframes/dist/chunk-IUZFXWSV.js +446 -0
- package/vendor/hyperframes/dist/chunk-JH556Q42.js +647 -0
- package/vendor/hyperframes/dist/chunk-JTHMTOMQ.js +601 -0
- package/vendor/hyperframes/dist/chunk-K2EQN4VU.js +405 -0
- package/vendor/hyperframes/dist/chunk-K2FTXJYH.js +16044 -0
- package/vendor/hyperframes/dist/chunk-K4WIOZFP.js +32 -0
- package/vendor/hyperframes/dist/chunk-K4WKGXRC.js +18 -0
- package/vendor/hyperframes/dist/chunk-KBJUXVOJ.js +172 -0
- package/vendor/hyperframes/dist/chunk-KC5XXX3X.js +590 -0
- package/vendor/hyperframes/dist/chunk-KNU5COPB.js +29 -0
- package/vendor/hyperframes/dist/chunk-KZI44OPA.js +185 -0
- package/vendor/hyperframes/dist/chunk-L3YOGIPG.js +48 -0
- package/vendor/hyperframes/dist/chunk-LAOCA3MQ.js +189 -0
- package/vendor/hyperframes/dist/chunk-LCSMOLGX.js +312 -0
- package/vendor/hyperframes/dist/chunk-LFGJWOVA.js +61 -0
- package/vendor/hyperframes/dist/chunk-LHSR3M4M.js +498 -0
- package/vendor/hyperframes/dist/chunk-LYNI3FOL.js +123 -0
- package/vendor/hyperframes/dist/chunk-M2WBOQ2Q.js +54 -0
- package/vendor/hyperframes/dist/chunk-MRF4AMKD.js +104 -0
- package/vendor/hyperframes/dist/chunk-MWB3ZIFM.js +852 -0
- package/vendor/hyperframes/dist/chunk-NGKM64BP.js +39 -0
- package/vendor/hyperframes/dist/chunk-NXMYHJAL.js +43 -0
- package/vendor/hyperframes/dist/chunk-OAF4XJOW.js +192 -0
- package/vendor/hyperframes/dist/chunk-OFQWTKPW.js +117 -0
- package/vendor/hyperframes/dist/chunk-P6LJ4Y32.js +4662 -0
- package/vendor/hyperframes/dist/chunk-PBN6GBJE.js +108 -0
- package/vendor/hyperframes/dist/chunk-PDAMK4Q5.js +28 -0
- package/vendor/hyperframes/dist/chunk-PFCFR3KZ.js +20 -0
- package/vendor/hyperframes/dist/chunk-PJ3HDUCY.js +108 -0
- package/vendor/hyperframes/dist/chunk-PMRBLBUP.js +152 -0
- package/vendor/hyperframes/dist/chunk-PPQUYWTW.js +240 -0
- package/vendor/hyperframes/dist/chunk-Q5X2B5WT.js +29 -0
- package/vendor/hyperframes/dist/chunk-Q7IU7MOR.js +351 -0
- package/vendor/hyperframes/dist/chunk-QC4FJVLM.js +371 -0
- package/vendor/hyperframes/dist/chunk-QNYYOUU3.js +1318 -0
- package/vendor/hyperframes/dist/chunk-RDNNAKEP.js +161 -0
- package/vendor/hyperframes/dist/chunk-RMHUQGRK.js +657 -0
- package/vendor/hyperframes/dist/chunk-RQVDTPGD.js +6 -0
- package/vendor/hyperframes/dist/chunk-RVCWIIZ7.js +68 -0
- package/vendor/hyperframes/dist/chunk-S3D6GE5W.js +72 -0
- package/vendor/hyperframes/dist/chunk-S3S4TGEH.js +424 -0
- package/vendor/hyperframes/dist/chunk-S7NPLFWV.js +11395 -0
- package/vendor/hyperframes/dist/chunk-SHB5VDMH.js +51 -0
- package/vendor/hyperframes/dist/chunk-TCLGPL65.js +860 -0
- package/vendor/hyperframes/dist/chunk-THXFSPLV.js +40 -0
- package/vendor/hyperframes/dist/chunk-TJSTGSAW.js +354 -0
- package/vendor/hyperframes/dist/chunk-TQFG7HTI.js +1024 -0
- package/vendor/hyperframes/dist/chunk-TVCRUG2S.js +265 -0
- package/vendor/hyperframes/dist/chunk-TWWSYAKJ.js +24 -0
- package/vendor/hyperframes/dist/chunk-U7CZBDMV.js +27 -0
- package/vendor/hyperframes/dist/chunk-UEZXMWG3.js +139 -0
- package/vendor/hyperframes/dist/chunk-UYEZTK4U.js +61 -0
- package/vendor/hyperframes/dist/chunk-VC76R6W2.js +27 -0
- package/vendor/hyperframes/dist/chunk-VFCKXTBB.js +159 -0
- package/vendor/hyperframes/dist/chunk-VWG7OQKU.js +22 -0
- package/vendor/hyperframes/dist/chunk-VXVRPIJA.js +105 -0
- package/vendor/hyperframes/dist/chunk-WBLXWOYK.js +15 -0
- package/vendor/hyperframes/dist/chunk-WERLJGIC.js +20 -0
- package/vendor/hyperframes/dist/chunk-WMQNIQDJ.js +2057 -0
- package/vendor/hyperframes/dist/chunk-WPHMNO44.js +4528 -0
- package/vendor/hyperframes/dist/chunk-X5HWXQPU.js +113 -0
- package/vendor/hyperframes/dist/chunk-X7MTZ4T2.js +6 -0
- package/vendor/hyperframes/dist/chunk-XH4DSOS5.js +59 -0
- package/vendor/hyperframes/dist/chunk-XS4EJSKU.js +23 -0
- package/vendor/hyperframes/dist/chunk-XT5P4QMO.js +181 -0
- package/vendor/hyperframes/dist/chunk-XT7X6QCP.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUHOIDKG.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUXGIA7H.js +485 -0
- package/vendor/hyperframes/dist/chunk-XZABUQTX.js +113 -0
- package/vendor/hyperframes/dist/chunk-Y6W4DVPS.js +356 -0
- package/vendor/hyperframes/dist/chunk-YEIFI443.js +44 -0
- package/vendor/hyperframes/dist/chunk-YQZNILVH.js +375 -0
- package/vendor/hyperframes/dist/chunk-Z27A7NUB.js +65 -0
- package/vendor/hyperframes/dist/chunk-Z6B37SNM.js +3081 -0
- package/vendor/hyperframes/dist/chunk-ZJUKFZ2P.js +10954 -0
- package/vendor/hyperframes/dist/chunk-ZKDMAOFU.js +32 -0
- package/vendor/hyperframes/dist/chunk-ZMXUQLI2.js +17219 -0
- package/vendor/hyperframes/dist/chunk-ZTZ7NCJT.js +58 -0
- package/vendor/hyperframes/dist/chunk-ZTZA4UWZ.js +108 -0
- package/vendor/hyperframes/dist/clean-W57E5YQ3.js +293 -0
- package/vendor/hyperframes/dist/cli.js +495 -0
- package/vendor/hyperframes/dist/cloud-FFTJGZ24.js +70 -0
- package/vendor/hyperframes/dist/cloudrun-AJUTHUEA.js +763 -0
- package/vendor/hyperframes/dist/colors-HKWSZCGK.js +15 -0
- package/vendor/hyperframes/dist/commands/contrast-audit.browser.js +459 -0
- package/vendor/hyperframes/dist/commands/layout-audit.browser.js +2102 -0
- package/vendor/hyperframes/dist/commands/motion-sample.browser.js +74 -0
- package/vendor/hyperframes/dist/commands/motion-signature.browser.js +374 -0
- package/vendor/hyperframes/dist/compare-AYCTT55F.js +421 -0
- package/vendor/hyperframes/dist/compiler-QO36EXLS.js +121 -0
- package/vendor/hyperframes/dist/component-VFFR2O7T.js +176 -0
- package/vendor/hyperframes/dist/compositions-QTVN3U2A.js +228 -0
- package/vendor/hyperframes/dist/contactSheet-27SRU7A4.js +22 -0
- package/vendor/hyperframes/dist/delete-ZAKYCB7I.js +114 -0
- package/vendor/hyperframes/dist/deploy-MX76RZ36.js +101 -0
- package/vendor/hyperframes/dist/destroy-H2TZBYHH.js +42 -0
- package/vendor/hyperframes/dist/deterministicFonts-HAEMV4TM.js +50 -0
- package/vendor/hyperframes/dist/dist-EWXJGN63.js +129 -0
- package/vendor/hyperframes/dist/dist-FNNGCKFS.js +29 -0
- package/vendor/hyperframes/dist/dist-S3PJNPXQ.js +392 -0
- package/vendor/hyperframes/dist/docker/Dockerfile.render +65 -0
- package/vendor/hyperframes/dist/docs/compositions.md +67 -0
- package/vendor/hyperframes/dist/docs/data-attributes.md +27 -0
- package/vendor/hyperframes/dist/docs/examples.md +19 -0
- package/vendor/hyperframes/dist/docs/gsap.md +26 -0
- package/vendor/hyperframes/dist/docs/rendering.md +35 -0
- package/vendor/hyperframes/dist/docs/troubleshooting.md +29 -0
- package/vendor/hyperframes/dist/docs-QAPJEGLS.js +131 -0
- package/vendor/hyperframes/dist/doctor-AI7C3FON.js +67 -0
- package/vendor/hyperframes/dist/dom-IROKGVJI.js +14 -0
- package/vendor/hyperframes/dist/dotEnv-AECLXQSO.js +14 -0
- package/vendor/hyperframes/dist/events-7LALYNKZ.js +92 -0
- package/vendor/hyperframes/dist/events-FQY3HGKZ.js +88 -0
- package/vendor/hyperframes/dist/feedback-WCMDMSTK.js +472 -0
- package/vendor/hyperframes/dist/ffmpeg-QIUFEFTY.js +35 -0
- package/vendor/hyperframes/dist/figma-64WY462P.js +63 -0
- package/vendor/hyperframes/dist/fontData.generated-NXAOI4GH.js +13 -0
- package/vendor/hyperframes/dist/fontLocalizeCli.js +132 -0
- package/vendor/hyperframes/dist/get-FPOMJMZB.js +103 -0
- package/vendor/hyperframes/dist/gpuPolicy-2ZUZE5D6.js +38 -0
- package/vendor/hyperframes/dist/grade-compare-E2CKPST4.js +647 -0
- package/vendor/hyperframes/dist/gsapParser-DIYYX6JT.js +2846 -0
- package/vendor/hyperframes/dist/gsapParserAcorn-E3GEIRZB.js +28 -0
- package/vendor/hyperframes/dist/help-YRQIDDML.js +197 -0
- package/vendor/hyperframes/dist/history-PP5NDRV3.js +571 -0
- package/vendor/hyperframes/dist/hyperframe-runtime.js +1081 -0
- package/vendor/hyperframes/dist/hyperframe.manifest.json +22 -0
- package/vendor/hyperframes/dist/hyperframe.runtime.iife.js +1081 -0
- package/vendor/hyperframes/dist/hyperframes-player.global.js +474 -0
- package/vendor/hyperframes/dist/hyperframes-slideshow.global.js +149 -0
- package/vendor/hyperframes/dist/info-SEX3B7JL.js +153 -0
- package/vendor/hyperframes/dist/init-U3AKHO5B.js +1147 -0
- package/vendor/hyperframes/dist/inspect-Q3K6EDEK.js +97 -0
- package/vendor/hyperframes/dist/installer-K6O5WF44.js +37 -0
- package/vendor/hyperframes/dist/keyframes-DC64JCI3.js +2602 -0
- package/vendor/hyperframes/dist/lambda-D7UMN4DJ.js +451 -0
- package/vendor/hyperframes/dist/layout-XSPPDHOO.js +86 -0
- package/vendor/hyperframes/dist/lib-TPG2ZMAX.js +128 -0
- package/vendor/hyperframes/dist/lint-7DQZE7L3.js +164 -0
- package/vendor/hyperframes/dist/lintProject-OHBBM3DJ.js +27 -0
- package/vendor/hyperframes/dist/list-4K5MVDQX.js +162 -0
- package/vendor/hyperframes/dist/login-NTX4OWXL.js +377 -0
- package/vendor/hyperframes/dist/logout-Q654A3SI.js +100 -0
- package/vendor/hyperframes/dist/manager-67P2XFXQ.js +34 -0
- package/vendor/hyperframes/dist/manager-CT3D67CG.js +38 -0
- package/vendor/hyperframes/dist/manager-GFN75DM4.js +30 -0
- package/vendor/hyperframes/dist/media-treatment-5FYAOPNL.js +972 -0
- package/vendor/hyperframes/dist/media-use-4XXGABIL.js +113 -0
- package/vendor/hyperframes/dist/models-C4E4IWJD.js +137 -0
- package/vendor/hyperframes/dist/motionShot-S4MIGMT5.js +614 -0
- package/vendor/hyperframes/dist/normalize-O76AC4HE.js +333 -0
- package/vendor/hyperframes/dist/normalize-audio-CSFTXLXD.js +276 -0
- package/vendor/hyperframes/dist/open-2ZD6BHZG.js +115 -0
- package/vendor/hyperframes/dist/pipeline-TNGWUZQC.js +54 -0
- package/vendor/hyperframes/dist/play-CTMUXX6E.js +349 -0
- package/vendor/hyperframes/dist/policies-FSDZVS2E.js +292 -0
- package/vendor/hyperframes/dist/preflight-SMNV6RW2.js +45 -0
- package/vendor/hyperframes/dist/present-WQVHV5CR.js +350 -0
- package/vendor/hyperframes/dist/preview-JOJXTH75.js +1820 -0
- package/vendor/hyperframes/dist/producer-ECLEN5RP.js +13 -0
- package/vendor/hyperframes/dist/progress-FBIEEB7Y.js +73 -0
- package/vendor/hyperframes/dist/projectConfig-HYJMJ5BY.js +56 -0
- package/vendor/hyperframes/dist/publication-HQ5Y3KBM.js +29 -0
- package/vendor/hyperframes/dist/publish-VHDYQASC.js +430 -0
- package/vendor/hyperframes/dist/refresh-K24ETHMA.js +53 -0
- package/vendor/hyperframes/dist/remove-background-W2YX2NVH.js +253 -0
- package/vendor/hyperframes/dist/render-AO5VX3YI.js +177 -0
- package/vendor/hyperframes/dist/render-LNO62LEL.js +2367 -0
- package/vendor/hyperframes/dist/render-TTQI7TGN.js +796 -0
- package/vendor/hyperframes/dist/render-batch-YH7CTWNY.js +284 -0
- package/vendor/hyperframes/dist/renderCancellation-JPIHE47X.js +35 -0
- package/vendor/hyperframes/dist/renderSetupWorker.js +79 -0
- package/vendor/hyperframes/dist/resolver-IZ647GBZ.js +38 -0
- package/vendor/hyperframes/dist/runtimeVersion.js +18 -0
- package/vendor/hyperframes/dist/screenshotCapture-ECBTLCU6.js +179 -0
- package/vendor/hyperframes/dist/shaderTransitionWorker.js +44 -0
- package/vendor/hyperframes/dist/sherpa-KKLNW6U2.js +314 -0
- package/vendor/hyperframes/dist/sherpaWorker.js +77 -0
- package/vendor/hyperframes/dist/sites-TNVKZS73.js +52 -0
- package/vendor/hyperframes/dist/skill-ZHVLH7KX.js +15 -0
- package/vendor/hyperframes/dist/skills/hyperframes/SKILL.md +152 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-contract.md +108 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-format.md +72 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/capability-menu.md +47 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/frame-worker-core.md +80 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/intent-interview.md +73 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/pitch-round.md +40 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/plugin-installation.md +43 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/production-loop.md +26 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/review-loop.md +37 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/route-briefs.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/embedded-captions.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/faceless-explainer.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/general-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/motion-graphics.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/music-to-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/pr-to-video.md +28 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/product-launch-video.md +13 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +9 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/slideshow.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/talking-head-recut.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/script-format.md +52 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/skill-lifecycle.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/storyboard-format.md +99 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/subagent-dispatch.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/workflow-catalog.md +10 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/SKILL.md +189 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/beats.md +19 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloud.md +163 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloudrun.md +62 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/compare-and-batch.md +105 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/doctor-browser.md +57 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/init-and-scaffold.md +74 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lambda.md +185 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +132 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/preview-render.md +193 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +134 -0
- package/vendor/hyperframes/dist/skills/media-use/SKILL.md +100 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/CREDITS.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/chime.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click-soft.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/error.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-3.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/key-press.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/manifest.json +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/notification.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/ping.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/pop.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/riser.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/sparkle.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/typing.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-cinematic.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-short.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/bgm.md +76 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/authoring.md +163 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/motion.md +87 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/transcript-handling.md +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/remove-background.md +143 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/requirements.md +29 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/sfx.md +42 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/transcribe.md +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts-to-captions.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts.md +260 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.mjs +311 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.test.mjs +159 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +131 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.test.mjs +38 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.mjs +98 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.test.mjs +233 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.mjs +257 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.test.mjs +74 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.mjs +14 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.test.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.test.mjs +185 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.mjs +114 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.test.mjs +205 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.mjs +77 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.mjs +389 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.spawn.test.mjs +158 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.test.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lyria-recipe.py +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.mjs +175 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.test.mjs +108 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/README.md +28 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/index.json +57 -0
- package/vendor/hyperframes/dist/skills/media-use/references/audio.md +20 -0
- package/vendor/hyperframes/dist/skills/media-use/references/grading.md +160 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatment-recipes.md +929 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatments.md +202 -0
- package/vendor/hyperframes/dist/skills/media-use/references/memory.md +37 -0
- package/vendor/hyperframes/dist/skills/media-use/references/meta.md +61 -0
- package/vendor/hyperframes/dist/skills/media-use/references/operations.md +327 -0
- package/vendor/hyperframes/dist/skills/media-use/references/resolve.md +150 -0
- package/vendor/hyperframes/dist/skills/media-use/references/setup-providers.md +80 -0
- package/vendor/hyperframes/dist/skills/media-use/references/telemetry-dashboard.md +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/audio-duck.mjs +113 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/compatibility.test.mjs +96 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.mjs +328 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.test.mjs +176 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/eval.mjs +369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.test.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bgm-provider.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/brand-provider.mjs +59 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +119 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +139 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cache.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.mjs +91 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.test.mjs +155 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.mjs +161 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.test.mjs +34 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.d.mts +3 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.test.mjs +79 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/coverage.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.mjs +181 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.test.mjs +80 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.mjs +198 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.test.mjs +125 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.mjs +184 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.test.mjs +162 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.test.mjs +153 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.test.mjs +102 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ff-binaries.mjs +37 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.test.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.mjs +265 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.test.mjs +285 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.mjs +191 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.test.mjs +301 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.test.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +435 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/image-provider.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/index-gen.mjs +63 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-media-search.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.mjs +318 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.test.mjs +220 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.mjs +78 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.mjs +244 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.test.mjs +298 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +316 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.mjs +271 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +199 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.d.mts +19 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.mjs +279 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.test.mjs +397 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/match.mjs +47 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.test.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.test.mjs +61 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.d.mts +9 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.mjs +107 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.test.mjs +174 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.test.mjs +89 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.mjs +31 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.test.mjs +50 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.mjs +27 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.test.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.mjs +180 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.test.mjs +189 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.test.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/providers.mjs +5 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.test.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.mjs +212 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.test.mjs +262 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.mjs +24 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.test.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/sfx-provider.mjs +23 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.mjs +132 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.test.mjs +157 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.mjs +117 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.test.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/svg-sanitize.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.mjs +210 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.test.mjs +437 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/test-home.test.mjs +10 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.test.mjs +33 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.test.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.test.mjs +54 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.test.mjs +46 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/words.mjs +18 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/prefs.mjs +70 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/recipe.mjs +103 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve.mjs +1369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.mjs +194 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.test.mjs +112 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.mjs +270 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills-MJ2J4GEM.js +808 -0
- package/vendor/hyperframes/dist/skillsUpdateCheck-TKTYQN5R.js +26 -0
- package/vendor/hyperframes/dist/slideshow-EJ4IMY6P.js +24 -0
- package/vendor/hyperframes/dist/snapshot-KIVDUUMN.js +875 -0
- package/vendor/hyperframes/dist/src-6YQBJGWR.js +202 -0
- package/vendor/hyperframes/dist/src-PVYUYV3M.js +471 -0
- package/vendor/hyperframes/dist/state-KAXGHF77.js +26 -0
- package/vendor/hyperframes/dist/staticProjectServer-7EU666GS.js +49 -0
- package/vendor/hyperframes/dist/status-YM52BQ6S.js +311 -0
- package/vendor/hyperframes/dist/studio/assets/hyperframes-player-Cp8e_Zst.js +473 -0
- package/vendor/hyperframes/dist/studio/assets/index-BX3KHhGX.js +71 -0
- package/vendor/hyperframes/dist/studio/assets/index-CASEBNy2.js +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-D11atkBt.css +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-DMTt9nTf.js +531 -0
- package/vendor/hyperframes/dist/studio/assets/index-oE1pOdAy.js +399 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js +948 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js +938 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js +190 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js +1441 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js +10 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js +1103 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js.map +1 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js +47 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js.map +1 -0
- package/vendor/hyperframes/dist/studio/favicon.svg +14 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/audio.svg +7 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/captions.svg +5 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/composition.svg +12 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/image.svg +18 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/music.svg +10 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/text.svg +3 -0
- package/vendor/hyperframes/dist/studio/index.css +165 -0
- package/vendor/hyperframes/dist/studio/index.css.map +1 -0
- package/vendor/hyperframes/dist/studio/index.d.ts +4296 -0
- package/vendor/hyperframes/dist/studio/index.html +23 -0
- package/vendor/hyperframes/dist/studio/index.js +99693 -0
- package/vendor/hyperframes/dist/studio/index.js.map +1 -0
- package/vendor/hyperframes/dist/studio/player.d.ts +30 -0
- package/vendor/hyperframes/dist/studio/player.js +10 -0
- package/vendor/hyperframes/dist/studio/player.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.d.ts +39 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js +50 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles.css +1 -0
- package/vendor/hyperframes/dist/studio/ui.d.ts +296 -0
- package/vendor/hyperframes/dist/studio/ui.js +66 -0
- package/vendor/hyperframes/dist/studio/ui.js.map +1 -0
- package/vendor/hyperframes/dist/studio-api-PNQZRPX5.js +136 -0
- package/vendor/hyperframes/dist/studioSelectionClient-IUUPKUHZ.js +25 -0
- package/vendor/hyperframes/dist/studioServer-UWRBPIOJ.js +1457 -0
- package/vendor/hyperframes/dist/synthesize-K62TIZWI.js +182 -0
- package/vendor/hyperframes/dist/system-EZYZNUFD.js +44 -0
- package/vendor/hyperframes/dist/telemetry-2YC4SGQU.js +144 -0
- package/vendor/hyperframes/dist/telemetry-QMYM4WME.js +95 -0
- package/vendor/hyperframes/dist/templates/_shared/AGENTS.md +107 -0
- package/vendor/hyperframes/dist/templates/_shared/CLAUDE.md +107 -0
- package/vendor/hyperframes/dist/templates/blank/index.html +55 -0
- package/vendor/hyperframes/dist/templates/from-file/index.html +75 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/captions.html +154 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/graphics.html +162 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/intro.html +87 -0
- package/vendor/hyperframes/dist/templates/warm-grain/index.html +264 -0
- package/vendor/hyperframes/dist/templates/warm-grain/registry-item.json +34 -0
- package/vendor/hyperframes/dist/timeline-77Z3BBQM.js +1377 -0
- package/vendor/hyperframes/dist/tokens-OBGTYE4Z.js +92 -0
- package/vendor/hyperframes/dist/transcribe-7NVFHCGA.js +387 -0
- package/vendor/hyperframes/dist/transcribe-BNSJRR4M.js +62 -0
- package/vendor/hyperframes/dist/tts-P3LIPIL5.js +234 -0
- package/vendor/hyperframes/dist/updateCheck-UDWIJ4ZQ.js +39 -0
- package/vendor/hyperframes/dist/upgrade-CT3CPO3E.js +231 -0
- package/vendor/hyperframes/dist/urlDownloader-H6WRI2UE.js +39 -0
- package/vendor/hyperframes/dist/usage-EC3KFUIJ.js +2139 -0
- package/vendor/hyperframes/dist/validate-65QDZJWZ.js +70 -0
- package/vendor/hyperframes/dist/video-FGSGKRSV.js +261 -0
- package/vendor/hyperframes/dist/workspaceBuildCheck-TOLGAI4T.js +133 -0
- package/vendor/hyperframes/package.json +80 -0
|
@@ -0,0 +1,2367 @@
|
|
|
1
|
+
import { createRequire as __hf_createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath as __hf_fileURLToPath } from "node:url";
|
|
3
|
+
import { dirname as __hf_dirname } from "node:path";
|
|
4
|
+
var require = __hf_createRequire(import.meta.url);
|
|
5
|
+
var __filename = __hf_fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __hf_dirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
maybePromptRenderFeedback
|
|
9
|
+
} from "./chunk-4THIAPBL.js";
|
|
10
|
+
import {
|
|
11
|
+
reportVariableIssues,
|
|
12
|
+
resolveVariablesArg,
|
|
13
|
+
validateVariablesAgainstProject
|
|
14
|
+
} from "./chunk-6CTIGJY7.js";
|
|
15
|
+
import {
|
|
16
|
+
loadProducer
|
|
17
|
+
} from "./chunk-3ZP5DXE7.js";
|
|
18
|
+
import {
|
|
19
|
+
renderJobObservabilityTelemetryPayload
|
|
20
|
+
} from "./chunk-VXVRPIJA.js";
|
|
21
|
+
import {
|
|
22
|
+
hasExplicitCompositionArg,
|
|
23
|
+
parseGifLoopArg,
|
|
24
|
+
parseHlsSegmentSecondsArg,
|
|
25
|
+
resolveBrowserTimeoutMsArg,
|
|
26
|
+
resolveCompositionEntryArg,
|
|
27
|
+
resolveDefaultFpsArg,
|
|
28
|
+
windowsChromeCrashRemediation
|
|
29
|
+
} from "./chunk-HRUGC23L.js";
|
|
30
|
+
import "./chunk-YEIFI443.js";
|
|
31
|
+
import {
|
|
32
|
+
resolveProject
|
|
33
|
+
} from "./chunk-S3D6GE5W.js";
|
|
34
|
+
import {
|
|
35
|
+
formatLintStartupMessage
|
|
36
|
+
} from "./chunk-6CSYCFQV.js";
|
|
37
|
+
import {
|
|
38
|
+
desktopHint
|
|
39
|
+
} from "./chunk-GULOKZLI.js";
|
|
40
|
+
import {
|
|
41
|
+
errorBox,
|
|
42
|
+
formatBytes,
|
|
43
|
+
formatRenderPipelineDetail,
|
|
44
|
+
formatRenderSummaryDetail,
|
|
45
|
+
formatScreenshotFallbackHint,
|
|
46
|
+
resolvePrintedCaptureMode
|
|
47
|
+
} from "./chunk-IHFUKJOR.js";
|
|
48
|
+
import {
|
|
49
|
+
runEnvironmentChecks
|
|
50
|
+
} from "./chunk-FCSIGXXP.js";
|
|
51
|
+
import "./chunk-PFCFR3KZ.js";
|
|
52
|
+
import {
|
|
53
|
+
createRenderCancellationScope
|
|
54
|
+
} from "./chunk-7JZ4FXP2.js";
|
|
55
|
+
import {
|
|
56
|
+
loadProjectConfig,
|
|
57
|
+
readProjectConfigWithStatus,
|
|
58
|
+
seedProjectAuthoringSkill
|
|
59
|
+
} from "./chunk-CFKU7HTK.js";
|
|
60
|
+
import "./chunk-XT7X6QCP.js";
|
|
61
|
+
import "./chunk-4YYJOFKS.js";
|
|
62
|
+
import {
|
|
63
|
+
normalizeSkillSlug
|
|
64
|
+
} from "./chunk-HVW7ABXD.js";
|
|
65
|
+
import "./chunk-LYNI3FOL.js";
|
|
66
|
+
import "./chunk-CWPVM2QV.js";
|
|
67
|
+
import "./chunk-A2Z4Z4VL.js";
|
|
68
|
+
import "./chunk-AWDFDFI3.js";
|
|
69
|
+
import "./chunk-P6LJ4Y32.js";
|
|
70
|
+
import "./chunk-GMECXFAN.js";
|
|
71
|
+
import {
|
|
72
|
+
H264EncoderUnavailableError,
|
|
73
|
+
chromeLaunchRemediation,
|
|
74
|
+
detectH264EncoderModeForRender,
|
|
75
|
+
findFFmpeg,
|
|
76
|
+
findFFprobe,
|
|
77
|
+
getFFmpegInstallHint
|
|
78
|
+
} from "./chunk-TVCRUG2S.js";
|
|
79
|
+
import {
|
|
80
|
+
trackRenderComplete,
|
|
81
|
+
trackRenderError,
|
|
82
|
+
trackRenderObservation,
|
|
83
|
+
trackRenderPreflightRejected
|
|
84
|
+
} from "./chunk-JTHMTOMQ.js";
|
|
85
|
+
import "./chunk-EISRN4E6.js";
|
|
86
|
+
import "./chunk-VWG7OQKU.js";
|
|
87
|
+
import {
|
|
88
|
+
c
|
|
89
|
+
} from "./chunk-ZTZA4UWZ.js";
|
|
90
|
+
import {
|
|
91
|
+
bytesToMb
|
|
92
|
+
} from "./chunk-IUZFXWSV.js";
|
|
93
|
+
import "./chunk-AMKC3AXA.js";
|
|
94
|
+
import {
|
|
95
|
+
markRenderSucceeded,
|
|
96
|
+
runPostRenderStep,
|
|
97
|
+
runPostRenderStepAsync
|
|
98
|
+
} from "./chunk-L3YOGIPG.js";
|
|
99
|
+
import {
|
|
100
|
+
defineCommand
|
|
101
|
+
} from "./chunk-S3S4TGEH.js";
|
|
102
|
+
import "./chunk-54HJ63Q2.js";
|
|
103
|
+
import {
|
|
104
|
+
failCommand,
|
|
105
|
+
failUsage,
|
|
106
|
+
requestCliExit,
|
|
107
|
+
setCommandExitCode
|
|
108
|
+
} from "./chunk-PBN6GBJE.js";
|
|
109
|
+
import {
|
|
110
|
+
EXTRACT_CACHE_DIR_DISABLED_ALIASES,
|
|
111
|
+
MAX_VP9_CPU_USED,
|
|
112
|
+
MIN_VP9_CPU_USED,
|
|
113
|
+
isVideoFrameFormat
|
|
114
|
+
} from "./chunk-K2FTXJYH.js";
|
|
115
|
+
import {
|
|
116
|
+
formatRenderOutputTimestamp,
|
|
117
|
+
fpsToFfmpegArg,
|
|
118
|
+
fpsToNumber,
|
|
119
|
+
parseFps
|
|
120
|
+
} from "./chunk-2YN64IN5.js";
|
|
121
|
+
import {
|
|
122
|
+
checkOutputResolutionCompatibility,
|
|
123
|
+
isAspectAgnosticResolutionAlias,
|
|
124
|
+
normalizeResolutionFlag,
|
|
125
|
+
suggestMatchingPreset
|
|
126
|
+
} from "./chunk-AVUUN2XD.js";
|
|
127
|
+
import "./chunk-DPVXBVLL.js";
|
|
128
|
+
import "./chunk-Z6B37SNM.js";
|
|
129
|
+
import "./chunk-HWKCIWQT.js";
|
|
130
|
+
import "./chunk-VC76R6W2.js";
|
|
131
|
+
import "./chunk-OFQWTKPW.js";
|
|
132
|
+
import {
|
|
133
|
+
hasDefinitiveEntryMismatch
|
|
134
|
+
} from "./chunk-Q5X2B5WT.js";
|
|
135
|
+
import "./chunk-4PFZPP2N.js";
|
|
136
|
+
import {
|
|
137
|
+
killOrphanedProcessesForRender
|
|
138
|
+
} from "./chunk-LAOCA3MQ.js";
|
|
139
|
+
import {
|
|
140
|
+
runRenderSetupWorker
|
|
141
|
+
} from "./chunk-LCSMOLGX.js";
|
|
142
|
+
import "./chunk-TWWSYAKJ.js";
|
|
143
|
+
import {
|
|
144
|
+
collectSubCompositionSrcs,
|
|
145
|
+
lintProject,
|
|
146
|
+
shouldBlockRender
|
|
147
|
+
} from "./chunk-ZJUKFZ2P.js";
|
|
148
|
+
import "./chunk-HBBJFK6I.js";
|
|
149
|
+
import "./chunk-PJ3HDUCY.js";
|
|
150
|
+
import "./chunk-TQFG7HTI.js";
|
|
151
|
+
import "./chunk-GK4AIFIH.js";
|
|
152
|
+
import "./chunk-2PSPARWP.js";
|
|
153
|
+
import "./chunk-K4WIOZFP.js";
|
|
154
|
+
import {
|
|
155
|
+
readConfigFresh,
|
|
156
|
+
recordRecentRender,
|
|
157
|
+
writeConfig,
|
|
158
|
+
writeConfigWithResult
|
|
159
|
+
} from "./chunk-XUXGIA7H.js";
|
|
160
|
+
import "./chunk-WERLJGIC.js";
|
|
161
|
+
import {
|
|
162
|
+
isDevMode
|
|
163
|
+
} from "./chunk-ISN5GRYI.js";
|
|
164
|
+
import {
|
|
165
|
+
VERSION
|
|
166
|
+
} from "./chunk-FLWXXDNS.js";
|
|
167
|
+
import {
|
|
168
|
+
normalizeErrorMessage
|
|
169
|
+
} from "./chunk-KNU5COPB.js";
|
|
170
|
+
import "./chunk-3GXQPCJC.js";
|
|
171
|
+
import "./chunk-RQVDTPGD.js";
|
|
172
|
+
import "./chunk-PMRBLBUP.js";
|
|
173
|
+
import "./chunk-M2WBOQ2Q.js";
|
|
174
|
+
|
|
175
|
+
// src/commands/render.ts
|
|
176
|
+
import { mkdtempSync, readdirSync, readFileSync as readFileSync4, statSync as statSync2, writeFileSync, rmSync } from "fs";
|
|
177
|
+
|
|
178
|
+
// src/commands/render/plan.ts
|
|
179
|
+
import { statSync } from "fs";
|
|
180
|
+
import { dirname, join, resolve as resolve2 } from "path";
|
|
181
|
+
|
|
182
|
+
// src/utils/catalogUsage.ts
|
|
183
|
+
import { readFileSync } from "fs";
|
|
184
|
+
import { isAbsolute, relative, resolve } from "path";
|
|
185
|
+
var EMPTY = Object.freeze({
|
|
186
|
+
installed: [],
|
|
187
|
+
usedBlocks: [],
|
|
188
|
+
manifestUnreadable: false
|
|
189
|
+
});
|
|
190
|
+
var UNREADABLE = Object.freeze({
|
|
191
|
+
installed: [],
|
|
192
|
+
usedBlocks: [],
|
|
193
|
+
manifestUnreadable: true
|
|
194
|
+
});
|
|
195
|
+
var MAX_VISITED_FILES = 250;
|
|
196
|
+
var MAX_HTML_BYTES = 20 * 1024 * 1024;
|
|
197
|
+
var REGISTRY_ITEM_NAME = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
198
|
+
function reachableCompositions(projectDir, entryPath) {
|
|
199
|
+
const seen = /* @__PURE__ */ new Set();
|
|
200
|
+
const queue = [resolve(entryPath)];
|
|
201
|
+
while (queue.length > 0 && seen.size < MAX_VISITED_FILES) {
|
|
202
|
+
const current = queue.shift();
|
|
203
|
+
if (seen.has(current)) continue;
|
|
204
|
+
seen.add(current);
|
|
205
|
+
let html;
|
|
206
|
+
try {
|
|
207
|
+
html = readFileSync(current, "utf-8");
|
|
208
|
+
} catch {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (html.length > MAX_HTML_BYTES) continue;
|
|
212
|
+
for (const src of collectSubCompositionSrcs(html)) {
|
|
213
|
+
queue.push(resolve(projectDir, src));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return seen;
|
|
217
|
+
}
|
|
218
|
+
function isReached(projectDir, target, reachable) {
|
|
219
|
+
if (isAbsolute(target)) return false;
|
|
220
|
+
const abs = resolve(projectDir, target);
|
|
221
|
+
if (relative(projectDir, abs).startsWith("..")) return false;
|
|
222
|
+
return reachable.has(abs);
|
|
223
|
+
}
|
|
224
|
+
function reportableNames(names) {
|
|
225
|
+
return [...new Set(names.filter((name) => REGISTRY_ITEM_NAME.test(name)))].sort();
|
|
226
|
+
}
|
|
227
|
+
function summarizeCatalogUsage(projectDir, entryPath) {
|
|
228
|
+
const { status, config } = readProjectConfigWithStatus(projectDir);
|
|
229
|
+
if (status === "unreadable") return UNREADABLE;
|
|
230
|
+
const items = config?.registryItems ?? [];
|
|
231
|
+
if (items.length === 0) return EMPTY;
|
|
232
|
+
const installed = reportableNames(items.map((item) => item.name));
|
|
233
|
+
if (installed.length === 0) return EMPTY;
|
|
234
|
+
const reachable = reachableCompositions(projectDir, entryPath);
|
|
235
|
+
const usedBlocks = reportableNames(
|
|
236
|
+
items.filter(
|
|
237
|
+
(item) => item.type === "hyperframes:block" && isReached(projectDir, item.target, reachable)
|
|
238
|
+
).map((item) => item.name)
|
|
239
|
+
);
|
|
240
|
+
return { installed, usedBlocks, manifestUnreadable: false };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/commands/render/plan.ts
|
|
244
|
+
var QUALITY_ALIASES = {
|
|
245
|
+
draft: { quality: "draft" },
|
|
246
|
+
standard: { quality: "standard" },
|
|
247
|
+
high: { quality: "high" },
|
|
248
|
+
looks: { quality: "standard", crf: 16 },
|
|
249
|
+
delivery: { quality: "high" }
|
|
250
|
+
};
|
|
251
|
+
var RENDER_FORMATS = ["mp4", "webm", "mov", "png-sequence", "gif", "hls"];
|
|
252
|
+
var VALID_FORMAT = new Set(RENDER_FORMATS);
|
|
253
|
+
var RENDER_FORMAT_LABEL = "mp4, webm, mov, png-sequence, gif, or hls";
|
|
254
|
+
var DEFAULT_HLS_SEGMENT_SECONDS = 4;
|
|
255
|
+
var FORMAT_EXT = {
|
|
256
|
+
mp4: ".mp4",
|
|
257
|
+
webm: ".webm",
|
|
258
|
+
mov: ".mov",
|
|
259
|
+
"png-sequence": "",
|
|
260
|
+
gif: ".gif",
|
|
261
|
+
// Directory output, like png-sequence: playlists and .ts segments go inside.
|
|
262
|
+
hls: ""
|
|
263
|
+
};
|
|
264
|
+
function formatFpsParseError(input, reason) {
|
|
265
|
+
switch (reason) {
|
|
266
|
+
case "empty":
|
|
267
|
+
return "Frame rate must not be empty.";
|
|
268
|
+
case "not-a-number":
|
|
269
|
+
return `Got "${input}". Frame rate must be an integer (e.g. 30) or a rational (e.g. 30000/1001 for NTSC).`;
|
|
270
|
+
case "non-positive":
|
|
271
|
+
return `Got "${input}". Frame rate must be greater than zero.`;
|
|
272
|
+
case "out-of-range":
|
|
273
|
+
return `Got "${input}". Frame rate must be in the range 1\u2013240.`;
|
|
274
|
+
case "invalid-fraction":
|
|
275
|
+
return `Got "${input}". Rational frame rates must be two positive integers separated by '/' (e.g. 30000/1001).`;
|
|
276
|
+
case "ambiguous-decimal":
|
|
277
|
+
return `Got "${input}". Decimal frame rates are ambiguous \u2014 use the exact rational form instead (e.g. 30000/1001 for 29.97).`;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function parseRenderFormat(input) {
|
|
281
|
+
if (!VALID_FORMAT.has(input)) return void 0;
|
|
282
|
+
return RENDER_FORMATS.find((format) => format === input);
|
|
283
|
+
}
|
|
284
|
+
function positiveInteger(raw, title, message, min = 1) {
|
|
285
|
+
const parsed = Number(raw);
|
|
286
|
+
if (!Number.isInteger(parsed) || parsed < min) {
|
|
287
|
+
errorBox(title, message);
|
|
288
|
+
failUsage();
|
|
289
|
+
}
|
|
290
|
+
return parsed;
|
|
291
|
+
}
|
|
292
|
+
var HF_ENV_OVERRIDE_RE = /^(HF|HYPERFRAMES)_/;
|
|
293
|
+
var MAX_REPORTED_ENV_OVERRIDES = 20;
|
|
294
|
+
var CLI_INTERNAL_HF_ENV_KEYS = /* @__PURE__ */ new Set(["HF_SHADER_WORKER_ENTRY"]);
|
|
295
|
+
function resolveHfEnvOverrides() {
|
|
296
|
+
return Object.keys(process.env).filter((name) => HF_ENV_OVERRIDE_RE.test(name) && !CLI_INTERNAL_HF_ENV_KEYS.has(name)).sort().slice(0, MAX_REPORTED_ENV_OVERRIDES);
|
|
297
|
+
}
|
|
298
|
+
function createRenderPlan(args, now = /* @__PURE__ */ new Date()) {
|
|
299
|
+
const hfEnvOverrides = resolveHfEnvOverrides();
|
|
300
|
+
const hasExplicitComposition = hasExplicitCompositionArg(args.composition);
|
|
301
|
+
const project = resolveProject(args.dir, { requireIndex: !hasExplicitComposition });
|
|
302
|
+
const entryFile = resolveCompositionEntryArg(args.composition, project.dir, statSync);
|
|
303
|
+
const renderTarget = entryFile ? resolve2(project.dir, entryFile) : project.indexPath;
|
|
304
|
+
const fpsArg = resolveDefaultFpsArg(args.fps, project.dir, project.indexPath, entryFile);
|
|
305
|
+
const fpsParse = parseFps(fpsArg ?? "30");
|
|
306
|
+
if (!fpsParse.ok) {
|
|
307
|
+
errorBox("Invalid fps", formatFpsParseError(fpsArg ?? "30", fpsParse.reason));
|
|
308
|
+
failUsage();
|
|
309
|
+
}
|
|
310
|
+
let fps = fpsParse.value;
|
|
311
|
+
const qualityRaw = args.quality ?? "looks";
|
|
312
|
+
if (!(qualityRaw in QUALITY_ALIASES)) {
|
|
313
|
+
errorBox(
|
|
314
|
+
"Invalid quality",
|
|
315
|
+
`Got "${qualityRaw}". Must be draft, looks, delivery, standard, or high.`
|
|
316
|
+
);
|
|
317
|
+
failUsage();
|
|
318
|
+
}
|
|
319
|
+
const qualityAlias = QUALITY_ALIASES[qualityRaw];
|
|
320
|
+
const quality = qualityAlias.quality;
|
|
321
|
+
const flagSkill = normalizeSkillSlug(args.skill);
|
|
322
|
+
const projectConfigSkill = loadProjectConfig(project.dir).authoringSkill;
|
|
323
|
+
const authoringSkill = flagSkill ?? projectConfigSkill;
|
|
324
|
+
const invalidAuthoringSkill = typeof args.skill === "string" && args.skill.trim() !== "" && !flagSkill ? args.skill : void 0;
|
|
325
|
+
const authoringSkillSource = flagSkill ? "flag" : projectConfigSkill ? "project-config" : void 0;
|
|
326
|
+
const catalogUsage = summarizeCatalogUsage(project.dir, renderTarget);
|
|
327
|
+
const formatRaw = args.format ?? "mp4";
|
|
328
|
+
const format = parseRenderFormat(formatRaw);
|
|
329
|
+
if (!format) {
|
|
330
|
+
errorBox("Invalid format", `Got "${formatRaw}". Must be ${RENDER_FORMAT_LABEL}.`);
|
|
331
|
+
failUsage();
|
|
332
|
+
}
|
|
333
|
+
let gifFpsCapped = false;
|
|
334
|
+
if (format === "gif" && fpsToNumber(fps) > 30) {
|
|
335
|
+
fps = { num: 30, den: 1 };
|
|
336
|
+
gifFpsCapped = true;
|
|
337
|
+
}
|
|
338
|
+
const gifLoopParse = parseGifLoopArg(args["gif-loop"]);
|
|
339
|
+
if (!gifLoopParse.ok) {
|
|
340
|
+
errorBox("Invalid gif-loop", gifLoopParse.message);
|
|
341
|
+
failUsage();
|
|
342
|
+
}
|
|
343
|
+
const gifLoop = gifLoopParse.value ?? (format === "gif" ? 0 : void 0);
|
|
344
|
+
const hlsSegmentParse = parseHlsSegmentSecondsArg(args["hls-segment-seconds"]);
|
|
345
|
+
if (!hlsSegmentParse.ok) {
|
|
346
|
+
errorBox("Invalid hls-segment-seconds", hlsSegmentParse.message);
|
|
347
|
+
failUsage();
|
|
348
|
+
}
|
|
349
|
+
const hlsSegmentSeconds = format === "hls" ? hlsSegmentParse.value ?? DEFAULT_HLS_SEGMENT_SECONDS : void 0;
|
|
350
|
+
const videoFrameFormatRaw = args["video-frame-format"] ?? "auto";
|
|
351
|
+
if (!isVideoFrameFormat(videoFrameFormatRaw)) {
|
|
352
|
+
errorBox(
|
|
353
|
+
"Invalid video-frame-format",
|
|
354
|
+
`Got "${videoFrameFormatRaw}". Must be auto, jpg, or png.`
|
|
355
|
+
);
|
|
356
|
+
failUsage();
|
|
357
|
+
}
|
|
358
|
+
let outputResolution;
|
|
359
|
+
let outputResolutionAspectAgnostic = false;
|
|
360
|
+
if (args.resolution !== void 0) {
|
|
361
|
+
outputResolution = normalizeResolutionFlag(args.resolution);
|
|
362
|
+
if (!outputResolution) {
|
|
363
|
+
errorBox(
|
|
364
|
+
"Invalid resolution",
|
|
365
|
+
`Got "${args.resolution}". Must be one of: landscape, portrait, landscape-4k, portrait-4k, square, square-4k (or aliases 1080p, 4k, uhd, 1080p-square, square-1080p, 4k-square).`
|
|
366
|
+
);
|
|
367
|
+
failUsage();
|
|
368
|
+
}
|
|
369
|
+
outputResolutionAspectAgnostic = isAspectAgnosticResolutionAlias(args.resolution);
|
|
370
|
+
if (args.hdr) {
|
|
371
|
+
errorBox(
|
|
372
|
+
"Conflicting flags",
|
|
373
|
+
"--resolution cannot be combined with --hdr. The HDR pipeline composites at composition dimensions and does not yet support supersampling.",
|
|
374
|
+
"Render in two passes: HDR at composition resolution, then upscale separately with ffmpeg."
|
|
375
|
+
);
|
|
376
|
+
failUsage();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (args.hdr && args.sdr) {
|
|
380
|
+
errorBox("Conflicting flags", "--hdr and --sdr are mutually exclusive.");
|
|
381
|
+
failUsage();
|
|
382
|
+
}
|
|
383
|
+
if (format === "hls" && args.hdr) {
|
|
384
|
+
errorBox(
|
|
385
|
+
"Unsupported HLS output",
|
|
386
|
+
"--hdr cannot be combined with --format hls. HLS output is SDR only (H.264 + AAC in MPEG-TS); HDR10 would need fMP4 segments and HEVC.",
|
|
387
|
+
"Render HDR to MP4, or drop --hdr."
|
|
388
|
+
);
|
|
389
|
+
failUsage();
|
|
390
|
+
}
|
|
391
|
+
if (format === "hls" && args.gpu) {
|
|
392
|
+
errorBox(
|
|
393
|
+
"Unsupported HLS output",
|
|
394
|
+
"--gpu cannot be combined with --format hls. Fixed-length segments require the software encoder's forced-keyframe lock, which GPU encoders ignore.",
|
|
395
|
+
"Re-run without --gpu."
|
|
396
|
+
);
|
|
397
|
+
failUsage();
|
|
398
|
+
}
|
|
399
|
+
const workers = args.workers != null && args.workers !== "auto" ? positiveInteger(
|
|
400
|
+
args.workers,
|
|
401
|
+
"Invalid workers",
|
|
402
|
+
`Got "${args.workers}". Must be a positive number or "auto".`
|
|
403
|
+
) : void 0;
|
|
404
|
+
const protocolTimeout = args["protocol-timeout"] != null ? positiveInteger(
|
|
405
|
+
args["protocol-timeout"],
|
|
406
|
+
"Invalid protocol-timeout",
|
|
407
|
+
`Got "${args["protocol-timeout"]}". Must be a number >= 1000 (ms).`,
|
|
408
|
+
1e3
|
|
409
|
+
) : void 0;
|
|
410
|
+
const playerReadyTimeout = args["player-ready-timeout"] != null ? positiveInteger(
|
|
411
|
+
args["player-ready-timeout"],
|
|
412
|
+
"Invalid player-ready-timeout",
|
|
413
|
+
`Got "${args["player-ready-timeout"]}". Must be a number >= 1000 (ms).`,
|
|
414
|
+
1e3
|
|
415
|
+
) : void 0;
|
|
416
|
+
const environment = {};
|
|
417
|
+
if (args["page-side-compositing"] === false) environment.HF_PAGE_SIDE_COMPOSITING = "false";
|
|
418
|
+
if (args["low-memory-mode"] != null) {
|
|
419
|
+
environment.PRODUCER_LOW_MEMORY_MODE = args["low-memory-mode"] ? "true" : "false";
|
|
420
|
+
}
|
|
421
|
+
if (args["experimental-fast-capture"] != null) {
|
|
422
|
+
environment.PRODUCER_EXPERIMENTAL_FAST_CAPTURE = args["experimental-fast-capture"] ? "true" : "false";
|
|
423
|
+
}
|
|
424
|
+
if (typeof args["frames-cache-dir"] === "string" && args["frames-cache-dir"].trim() !== "") {
|
|
425
|
+
const raw = args["frames-cache-dir"].trim();
|
|
426
|
+
const normalized = raw.toLowerCase();
|
|
427
|
+
const isDisableAlias = EXTRACT_CACHE_DIR_DISABLED_ALIASES.includes(normalized);
|
|
428
|
+
environment.HYPERFRAMES_EXTRACT_CACHE_DIR = isDisableAlias ? raw : resolve2(raw);
|
|
429
|
+
}
|
|
430
|
+
if (args["max-concurrent-renders"] != null) {
|
|
431
|
+
const parsed = positiveInteger(
|
|
432
|
+
args["max-concurrent-renders"],
|
|
433
|
+
"Invalid max-concurrent-renders",
|
|
434
|
+
`Got "${args["max-concurrent-renders"]}". Must be a number between 1 and 10.`
|
|
435
|
+
);
|
|
436
|
+
if (parsed > 10) {
|
|
437
|
+
errorBox(
|
|
438
|
+
"Invalid max-concurrent-renders",
|
|
439
|
+
`Got "${args["max-concurrent-renders"]}". Must be a number between 1 and 10.`
|
|
440
|
+
);
|
|
441
|
+
failUsage();
|
|
442
|
+
}
|
|
443
|
+
environment.PRODUCER_MAX_CONCURRENT_RENDERS = String(parsed);
|
|
444
|
+
}
|
|
445
|
+
const batchPath = typeof args.batch === "string" && args.batch.trim() !== "" ? args.batch.trim() : void 0;
|
|
446
|
+
if (batchPath && (args.variables != null || args["variables-file"] != null)) {
|
|
447
|
+
errorBox(
|
|
448
|
+
"Conflicting variables flags",
|
|
449
|
+
"Use either --batch or --variables/--variables-file, not both."
|
|
450
|
+
);
|
|
451
|
+
failUsage();
|
|
452
|
+
}
|
|
453
|
+
if (!batchPath && args["batch-concurrency"] != null) {
|
|
454
|
+
errorBox("Invalid batch-concurrency", "--batch-concurrency requires --batch.");
|
|
455
|
+
failUsage();
|
|
456
|
+
}
|
|
457
|
+
if (!batchPath && args["batch-fail-fast"]) {
|
|
458
|
+
errorBox("Invalid batch-fail-fast", "--batch-fail-fast requires --batch.");
|
|
459
|
+
failUsage();
|
|
460
|
+
}
|
|
461
|
+
const batchConcurrency = args["batch-concurrency"] != null ? positiveInteger(
|
|
462
|
+
args["batch-concurrency"],
|
|
463
|
+
"Invalid batch-concurrency",
|
|
464
|
+
`Got "${args["batch-concurrency"]}". Must be a positive integer.`
|
|
465
|
+
) : 1;
|
|
466
|
+
const rendersDir = resolve2("renders");
|
|
467
|
+
const ext = FORMAT_EXT[format];
|
|
468
|
+
const timestamp = formatRenderOutputTimestamp(now);
|
|
469
|
+
const batchOutputTemplate = args.output ? args.output : join(rendersDir, `${project.name}_${timestamp}_{index}${ext}`);
|
|
470
|
+
const outputPath = args.output ? resolve2(args.output) : join(rendersDir, `${project.name}_${timestamp}${ext}`);
|
|
471
|
+
const useDocker = args.docker ?? false;
|
|
472
|
+
const useGpu = args.gpu ?? false;
|
|
473
|
+
const browserGpuMode = resolveBrowserGpuForCli(useDocker, args["browser-gpu"]);
|
|
474
|
+
if (useDocker && args["browser-gpu"] === true) {
|
|
475
|
+
errorBox(
|
|
476
|
+
"Browser GPU is local-only",
|
|
477
|
+
"--browser-gpu uses the host Chrome GPU backend. Docker mode keeps browser rendering deterministic and does not expose a cross-platform Chrome GPU backend.",
|
|
478
|
+
"Run without --docker, or use --gpu for Docker GPU encoding where your Docker host supports GPU passthrough."
|
|
479
|
+
);
|
|
480
|
+
failUsage();
|
|
481
|
+
}
|
|
482
|
+
const videoBitrate = args["video-bitrate"]?.trim();
|
|
483
|
+
if (args.crf != null && videoBitrate) {
|
|
484
|
+
errorBox("Conflicting encoder settings", "Use either --crf or --video-bitrate, not both.");
|
|
485
|
+
failUsage();
|
|
486
|
+
}
|
|
487
|
+
const crf = args.crf != null ? positiveInteger(
|
|
488
|
+
args.crf,
|
|
489
|
+
"Invalid crf",
|
|
490
|
+
`Got "${args.crf}". Must be a non-negative integer.`,
|
|
491
|
+
0
|
|
492
|
+
) : format === "mov" || args["video-bitrate"] ? void 0 : "crf" in qualityAlias ? qualityAlias.crf : void 0;
|
|
493
|
+
let vp9CpuUsed;
|
|
494
|
+
if (args["vp9-cpu-used"] != null) {
|
|
495
|
+
const parsed = Number(args["vp9-cpu-used"]);
|
|
496
|
+
if (!Number.isInteger(parsed) || parsed < MIN_VP9_CPU_USED || parsed > MAX_VP9_CPU_USED) {
|
|
497
|
+
errorBox(
|
|
498
|
+
"Invalid vp9-cpu-used",
|
|
499
|
+
`Got "${args["vp9-cpu-used"]}". Must be an integer between ${MIN_VP9_CPU_USED} and ${MAX_VP9_CPU_USED}.`
|
|
500
|
+
);
|
|
501
|
+
failUsage();
|
|
502
|
+
}
|
|
503
|
+
vp9CpuUsed = parsed;
|
|
504
|
+
}
|
|
505
|
+
if (args["video-bitrate"] != null && !videoBitrate) {
|
|
506
|
+
errorBox(
|
|
507
|
+
"Invalid video-bitrate",
|
|
508
|
+
`Got "${args["video-bitrate"]}". Must be a non-empty bitrate such as "10M".`
|
|
509
|
+
);
|
|
510
|
+
failUsage();
|
|
511
|
+
}
|
|
512
|
+
if (format === "mov" && (crf !== void 0 || videoBitrate !== void 0)) {
|
|
513
|
+
const flag = crf !== void 0 ? "--crf" : "--video-bitrate";
|
|
514
|
+
errorBox(
|
|
515
|
+
"Unsupported ProRes rate control",
|
|
516
|
+
`${flag} does not apply to MOV. MOV uses a fixed alpha-preserving ProRes 4444 profile.`,
|
|
517
|
+
`Remove ${flag}, or choose MP4/WebM when you need CRF or target-bitrate control.`
|
|
518
|
+
);
|
|
519
|
+
failUsage();
|
|
520
|
+
}
|
|
521
|
+
const quiet = args.quiet ?? false;
|
|
522
|
+
const batchJson = args.json ?? false;
|
|
523
|
+
return Object.freeze({
|
|
524
|
+
project,
|
|
525
|
+
entryFile,
|
|
526
|
+
renderTarget,
|
|
527
|
+
fps,
|
|
528
|
+
quality,
|
|
529
|
+
authoringSkill,
|
|
530
|
+
invalidAuthoringSkill,
|
|
531
|
+
authoringSkillSource,
|
|
532
|
+
catalogUsage,
|
|
533
|
+
format,
|
|
534
|
+
gifLoop,
|
|
535
|
+
gifFpsCapped,
|
|
536
|
+
hlsSegmentSeconds,
|
|
537
|
+
videoFrameFormat: videoFrameFormatRaw,
|
|
538
|
+
outputResolution,
|
|
539
|
+
outputResolutionAspectAgnostic,
|
|
540
|
+
outputResolutionRaw: args.resolution,
|
|
541
|
+
workers,
|
|
542
|
+
protocolTimeout,
|
|
543
|
+
playerReadyTimeout,
|
|
544
|
+
pageNavigationTimeoutMs: resolveBrowserTimeoutMsArg(args["browser-timeout"]),
|
|
545
|
+
batchPath,
|
|
546
|
+
batchConcurrency,
|
|
547
|
+
batchFailFast: args["batch-fail-fast"] ?? false,
|
|
548
|
+
batchOutputTemplate,
|
|
549
|
+
outputPath,
|
|
550
|
+
useDocker,
|
|
551
|
+
useGpu,
|
|
552
|
+
browserGpuMode,
|
|
553
|
+
quiet,
|
|
554
|
+
lintVerbose: args["lint-verbose"] ?? false,
|
|
555
|
+
debug: args.debug ?? false,
|
|
556
|
+
resumeSegments: args.resume ?? false,
|
|
557
|
+
keepSegments: args["keep-segments"] ?? false,
|
|
558
|
+
bestEffort: args["best-effort"] ?? true,
|
|
559
|
+
batchJson,
|
|
560
|
+
effectiveQuiet: quiet || batchPath != null && batchJson,
|
|
561
|
+
strictAll: args["strict-all"] ?? false,
|
|
562
|
+
strictErrors: (args.strict ?? false) || (args["strict-all"] ?? false),
|
|
563
|
+
crf,
|
|
564
|
+
vp9CpuUsed,
|
|
565
|
+
videoBitrate,
|
|
566
|
+
hdrMode: args.sdr ? "force-sdr" : args.hdr ? "force-hdr" : "auto",
|
|
567
|
+
pageSideCompositing: args["page-side-compositing"] !== false,
|
|
568
|
+
experimentalFastCapture: args["experimental-fast-capture"] === true,
|
|
569
|
+
variablesArg: args.variables,
|
|
570
|
+
variablesFileArg: args["variables-file"],
|
|
571
|
+
strictVariables: args["strict-variables"] ?? false,
|
|
572
|
+
environment: Object.freeze(environment),
|
|
573
|
+
hfEnvOverrides
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
function applyRenderEnvironment(plan) {
|
|
577
|
+
for (const [key, value] of Object.entries(plan.environment)) process.env[key] = value;
|
|
578
|
+
}
|
|
579
|
+
function renderOutputDirectory(plan) {
|
|
580
|
+
return dirname(plan.outputPath);
|
|
581
|
+
}
|
|
582
|
+
function resolveBrowserGpuForCli(useDocker, browserGpuArg, envMode = process.env.PRODUCER_BROWSER_GPU_MODE) {
|
|
583
|
+
if (useDocker) return "software";
|
|
584
|
+
if (browserGpuArg === true) return "hardware";
|
|
585
|
+
if (browserGpuArg === false) return "software";
|
|
586
|
+
if (envMode === "hardware" || envMode === "software" || envMode === "auto") return envMode;
|
|
587
|
+
return "auto";
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// src/commands/render/present.ts
|
|
591
|
+
import { cpus } from "os";
|
|
592
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
593
|
+
async function presentRenderPlan(plan) {
|
|
594
|
+
await presentRenderWarnings(plan);
|
|
595
|
+
if (plan.effectiveQuiet || plan.batchPath) return;
|
|
596
|
+
presentRenderSummary(plan);
|
|
597
|
+
}
|
|
598
|
+
async function presentRenderWarnings(plan) {
|
|
599
|
+
if (plan.invalidAuthoringSkill) {
|
|
600
|
+
process.stderr.write(
|
|
601
|
+
`hyperframes: ignoring --skill="${plan.invalidAuthoringSkill}" \u2014 not a valid slug (lowercase letters/digits/hyphens, max 64); this render will be unattributed.
|
|
602
|
+
`
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
if (!plan.effectiveQuiet && plan.gifFpsCapped) {
|
|
606
|
+
console.log(c.warn(" GIF output is capped at 30fps. Use --fps 15 for smaller files."));
|
|
607
|
+
}
|
|
608
|
+
if (!plan.effectiveQuiet) await warnForSlideshow(plan);
|
|
609
|
+
}
|
|
610
|
+
function presentRenderSummary(plan) {
|
|
611
|
+
const workerLabel = plan.workers != null ? `${plan.workers} workers` : `auto workers (${cpus().length} cores detected)`;
|
|
612
|
+
const nameLabel = plan.entryFile ? `${plan.project.name}/${plan.entryFile}` : plan.project.name;
|
|
613
|
+
console.log("");
|
|
614
|
+
console.log(
|
|
615
|
+
c.accent("\u25C6") + " Rendering " + c.accent(nameLabel) + c.dim(" \u2192 " + plan.outputPath)
|
|
616
|
+
);
|
|
617
|
+
console.log(
|
|
618
|
+
c.dim(` ${fpsToFfmpegArg(plan.fps)}fps \xB7 ${plan.quality} \xB7 ${workerLabel}`)
|
|
619
|
+
);
|
|
620
|
+
if (plan.outputResolution) {
|
|
621
|
+
console.log(c.dim(" Output resolution: " + plan.outputResolution));
|
|
622
|
+
}
|
|
623
|
+
if (plan.format === "hls") {
|
|
624
|
+
console.log(c.dim(` HLS: ${plan.hlsSegmentSeconds}s segments in a playlist directory`));
|
|
625
|
+
}
|
|
626
|
+
const gpuModes = formatGpuModes(plan);
|
|
627
|
+
if (gpuModes) console.log(c.dim(" GPU: " + gpuModes));
|
|
628
|
+
console.log("");
|
|
629
|
+
}
|
|
630
|
+
function formatGpuModes(plan) {
|
|
631
|
+
const modes = [];
|
|
632
|
+
if (plan.useGpu) modes.push("encoder GPU");
|
|
633
|
+
if (plan.browserGpuMode === "hardware") modes.push("browser GPU (forced)");
|
|
634
|
+
else if (plan.browserGpuMode === "auto") modes.push("browser GPU (auto-detect)");
|
|
635
|
+
return modes.length > 0 ? modes.join(" + ") : void 0;
|
|
636
|
+
}
|
|
637
|
+
async function warnForSlideshow(plan) {
|
|
638
|
+
try {
|
|
639
|
+
const { slideshowIslandRegex } = await import("./slideshow-EJ4IMY6P.js");
|
|
640
|
+
if (!slideshowIslandRegex("i").test(readFileSync2(plan.renderTarget, "utf8"))) return;
|
|
641
|
+
console.log(
|
|
642
|
+
c.warn("\u26A0") + " This composition carries a slideshow island \u2014 `render` captures only the first scene, so the MP4 will be truncated to slide 1. Use " + c.accent("hyperframes present") + " for the deck; a linear main-line MP4 export is not yet available."
|
|
643
|
+
);
|
|
644
|
+
console.log("");
|
|
645
|
+
} catch {
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// src/commands/render/execute.ts
|
|
650
|
+
import { mkdirSync, readFileSync as readFileSync3 } from "fs";
|
|
651
|
+
function renderLintContinuationHint(strictErrors) {
|
|
652
|
+
return strictErrors ? " Continuing render despite lint warnings. Use --strict-all to block warnings." : " Continuing render despite lint issues. Use --strict to block errors.";
|
|
653
|
+
}
|
|
654
|
+
function renderLintShouldAbort(strictErrors, strictAll, lintResult, definitiveEntryMismatch) {
|
|
655
|
+
return definitiveEntryMismatch || shouldBlockRender(strictErrors, strictAll, lintResult.totalErrors, lintResult.totalWarnings);
|
|
656
|
+
}
|
|
657
|
+
async function executeRenderPlan(plan, dependencies, cancellation) {
|
|
658
|
+
assertRenderActive(cancellation);
|
|
659
|
+
applyRenderEnvironment(plan);
|
|
660
|
+
if (!plan.batchPath) mkdirSync(renderOutputDirectory(plan), { recursive: true });
|
|
661
|
+
let batchModule;
|
|
662
|
+
let preparedBatch;
|
|
663
|
+
if (plan.batchPath) {
|
|
664
|
+
batchModule = await import("./batchRender-FT7AP7XH.js");
|
|
665
|
+
try {
|
|
666
|
+
preparedBatch = batchModule.prepareBatchRender({
|
|
667
|
+
batchPath: plan.batchPath,
|
|
668
|
+
outputTemplate: plan.batchOutputTemplate,
|
|
669
|
+
indexPath: plan.renderTarget,
|
|
670
|
+
strictVariables: plan.strictVariables,
|
|
671
|
+
quiet: plan.quiet || plan.batchJson,
|
|
672
|
+
json: plan.batchJson
|
|
673
|
+
});
|
|
674
|
+
} catch (error) {
|
|
675
|
+
batchModule.exitBatchRenderInputError(error);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
const browserPath = plan.useDocker ? void 0 : await ensureRenderBrowser(plan, cancellation?.signal);
|
|
679
|
+
assertRenderActive(cancellation);
|
|
680
|
+
await runRenderLint(plan, lintProject, cancellation?.signal);
|
|
681
|
+
assertRenderActive(cancellation);
|
|
682
|
+
await runResolutionPreflight(plan, dependencies.checkResolution);
|
|
683
|
+
assertRenderActive(cancellation);
|
|
684
|
+
if (plan.batchPath && batchModule && preparedBatch) {
|
|
685
|
+
await executeBatchRender(
|
|
686
|
+
plan,
|
|
687
|
+
browserPath,
|
|
688
|
+
batchModule,
|
|
689
|
+
preparedBatch,
|
|
690
|
+
dependencies,
|
|
691
|
+
cancellation
|
|
692
|
+
);
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
const variables = resolveVariablesArg(plan.variablesArg, plan.variablesFileArg);
|
|
696
|
+
if (variables && Object.keys(variables).length > 0) {
|
|
697
|
+
const issues = validateVariablesAgainstProject(plan.renderTarget, variables);
|
|
698
|
+
reportVariableIssues(issues, { strict: plan.strictVariables, quiet: plan.quiet });
|
|
699
|
+
}
|
|
700
|
+
const options = renderOptionsFromPlan(plan, browserPath, variables);
|
|
701
|
+
const execute = plan.useDocker ? dependencies.renderDocker : dependencies.renderLocal;
|
|
702
|
+
await execute(plan.project.dir, plan.outputPath, options, cancellation);
|
|
703
|
+
}
|
|
704
|
+
function renderOptionsFromPlan(plan, browserPath, variables) {
|
|
705
|
+
const options = {
|
|
706
|
+
fps: plan.fps,
|
|
707
|
+
quality: plan.quality,
|
|
708
|
+
authoringSkill: plan.authoringSkill,
|
|
709
|
+
authoringSkillSource: plan.authoringSkillSource,
|
|
710
|
+
authoringSkillInvalid: plan.invalidAuthoringSkill,
|
|
711
|
+
hfEnvOverrides: plan.hfEnvOverrides,
|
|
712
|
+
catalogUsage: plan.catalogUsage,
|
|
713
|
+
format: plan.format,
|
|
714
|
+
gifLoop: plan.gifLoop,
|
|
715
|
+
gifFpsCapped: plan.gifFpsCapped,
|
|
716
|
+
hlsSegmentSeconds: plan.hlsSegmentSeconds,
|
|
717
|
+
workers: plan.workers,
|
|
718
|
+
gpu: plan.useGpu,
|
|
719
|
+
browserGpuMode: plan.browserGpuMode,
|
|
720
|
+
hdrMode: plan.hdrMode,
|
|
721
|
+
crf: plan.crf,
|
|
722
|
+
vp9CpuUsed: plan.vp9CpuUsed,
|
|
723
|
+
videoBitrate: plan.videoBitrate,
|
|
724
|
+
videoFrameFormat: plan.videoFrameFormat,
|
|
725
|
+
quiet: plan.quiet,
|
|
726
|
+
browserPath,
|
|
727
|
+
debug: plan.debug,
|
|
728
|
+
resumeSegments: plan.resumeSegments,
|
|
729
|
+
keepSegments: plan.keepSegments,
|
|
730
|
+
bestEffort: plan.bestEffort,
|
|
731
|
+
variables,
|
|
732
|
+
entryFile: plan.entryFile,
|
|
733
|
+
outputResolution: plan.outputResolution,
|
|
734
|
+
outputResolutionAspectAgnostic: plan.outputResolutionAspectAgnostic,
|
|
735
|
+
outputResolutionRaw: plan.outputResolutionRaw,
|
|
736
|
+
pageNavigationTimeoutMs: plan.pageNavigationTimeoutMs,
|
|
737
|
+
protocolTimeout: plan.protocolTimeout,
|
|
738
|
+
playerReadyTimeout: plan.playerReadyTimeout,
|
|
739
|
+
exitAfterComplete: true,
|
|
740
|
+
manageDeParallelRouterBreaker: true
|
|
741
|
+
};
|
|
742
|
+
if (plan.useDocker) {
|
|
743
|
+
options.pageSideCompositing = plan.pageSideCompositing;
|
|
744
|
+
options.experimentalFastCapture = plan.experimentalFastCapture;
|
|
745
|
+
}
|
|
746
|
+
return options;
|
|
747
|
+
}
|
|
748
|
+
function assertRenderActive(cancellation) {
|
|
749
|
+
cancellation?.checkAncestors();
|
|
750
|
+
cancellation?.signal.throwIfAborted();
|
|
751
|
+
}
|
|
752
|
+
async function ensureRenderBrowser(plan, signal) {
|
|
753
|
+
const { ensureBrowser } = await import("./manager-CT3D67CG.js");
|
|
754
|
+
let browserSpinner;
|
|
755
|
+
try {
|
|
756
|
+
if (plan.effectiveQuiet) {
|
|
757
|
+
return (await ensureBrowser({ preferManagedChrome: true, signal })).executablePath;
|
|
758
|
+
}
|
|
759
|
+
const clack = await import("./dist-EWXJGN63.js");
|
|
760
|
+
browserSpinner = clack.spinner();
|
|
761
|
+
browserSpinner.start("Checking browser...");
|
|
762
|
+
const info = await ensureBrowser({
|
|
763
|
+
preferManagedChrome: true,
|
|
764
|
+
signal,
|
|
765
|
+
onProgress: (downloaded, total) => {
|
|
766
|
+
if (total <= 0) return;
|
|
767
|
+
const pct = Math.floor(downloaded / total * 100);
|
|
768
|
+
browserSpinner?.message(
|
|
769
|
+
`Downloading Chrome... ${c.progress(pct + "%")} ${c.dim("(" + formatBytes(downloaded) + " / " + formatBytes(total) + ")")}`
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
browserSpinner.stop(c.dim(`Browser: ${info.source}`));
|
|
774
|
+
return info.executablePath;
|
|
775
|
+
} catch (error) {
|
|
776
|
+
browserSpinner?.stop(c.error("Browser not available"));
|
|
777
|
+
if (signal?.aborted) signal.throwIfAborted();
|
|
778
|
+
errorBox(
|
|
779
|
+
"Chrome not found",
|
|
780
|
+
normalizeErrorMessage(error),
|
|
781
|
+
"Run: npx hyperframes browser ensure"
|
|
782
|
+
);
|
|
783
|
+
failCommand();
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
async function runRenderLint(plan, runLint = lintProject, signal) {
|
|
787
|
+
const explicitEntry = plan.entryFile ? plan.renderTarget : void 0;
|
|
788
|
+
const lintResult = signal && runLint === lintProject ? await runRenderLintInOwnedProcess(plan.project.dir, explicitEntry, signal) : await runLint(plan.project.dir, explicitEntry);
|
|
789
|
+
if (lintResult.totalErrors === 0 && lintResult.totalWarnings === 0) return;
|
|
790
|
+
const definitiveEntryMismatch = hasDefinitiveEntryMismatch(lintResult);
|
|
791
|
+
const willAbort = renderLintShouldAbort(
|
|
792
|
+
plan.strictErrors,
|
|
793
|
+
plan.strictAll,
|
|
794
|
+
lintResult,
|
|
795
|
+
definitiveEntryMismatch
|
|
796
|
+
);
|
|
797
|
+
presentRenderLintFindings(lintResult, plan.effectiveQuiet, plan.lintVerbose || willAbort);
|
|
798
|
+
if (willAbort) {
|
|
799
|
+
presentRenderLintAbort(plan, definitiveEntryMismatch);
|
|
800
|
+
failCommand();
|
|
801
|
+
}
|
|
802
|
+
presentRenderLintContinuation(plan);
|
|
803
|
+
}
|
|
804
|
+
async function runRenderLintInOwnedProcess(projectDir, entryFile, signal) {
|
|
805
|
+
return runRenderSetupWorker(
|
|
806
|
+
"lint",
|
|
807
|
+
{ projectDir, entryFile },
|
|
808
|
+
{
|
|
809
|
+
signal,
|
|
810
|
+
maxBufferBytes: 8 * 1024 * 1024
|
|
811
|
+
}
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
function presentRenderLintFindings(lintResult, quiet, lintVerbose) {
|
|
815
|
+
if (quiet) return;
|
|
816
|
+
console.log("");
|
|
817
|
+
for (const line of formatLintStartupMessage(
|
|
818
|
+
lintResult,
|
|
819
|
+
lintVerbose ? { kind: "verbose", options: { errorsFirst: true } } : { kind: "summary" }
|
|
820
|
+
))
|
|
821
|
+
console.log(line);
|
|
822
|
+
}
|
|
823
|
+
function presentRenderLintAbort(plan, definitiveEntryMismatch) {
|
|
824
|
+
if (plan.effectiveQuiet) return;
|
|
825
|
+
console.log("");
|
|
826
|
+
console.log(
|
|
827
|
+
c.error(
|
|
828
|
+
definitiveEntryMismatch ? " Aborting render because the default index.html entry is blank." : ` Aborting render due to lint issues (${plan.strictAll ? "--strict-all" : "--strict"} mode).`
|
|
829
|
+
)
|
|
830
|
+
);
|
|
831
|
+
console.log("");
|
|
832
|
+
}
|
|
833
|
+
function presentRenderLintContinuation(plan) {
|
|
834
|
+
if (plan.effectiveQuiet) return;
|
|
835
|
+
console.log(c.dim(renderLintContinuationHint(plan.strictErrors)));
|
|
836
|
+
console.log("");
|
|
837
|
+
}
|
|
838
|
+
async function runResolutionPreflight(plan, checkResolution) {
|
|
839
|
+
if (!plan.outputResolution) return;
|
|
840
|
+
let issue;
|
|
841
|
+
try {
|
|
842
|
+
issue = await checkResolution(readFileSync3(plan.renderTarget, "utf8"), plan.outputResolution, {
|
|
843
|
+
alphaRequested: plan.format === "webm" || plan.format === "mov" || plan.format === "png-sequence",
|
|
844
|
+
hdrRequested: plan.hdrMode === "force-hdr",
|
|
845
|
+
aspectAgnostic: plan.outputResolutionAspectAgnostic
|
|
846
|
+
});
|
|
847
|
+
} catch {
|
|
848
|
+
}
|
|
849
|
+
if (!issue) return;
|
|
850
|
+
trackRenderPreflightRejected({ kind: issue.kind });
|
|
851
|
+
errorBox("Output resolution incompatible", issue.message);
|
|
852
|
+
failCommand();
|
|
853
|
+
}
|
|
854
|
+
function batchRowRenderOptions(plan, browserPath) {
|
|
855
|
+
const batchQuiet = plan.quiet || plan.batchJson;
|
|
856
|
+
return {
|
|
857
|
+
fps: plan.fps,
|
|
858
|
+
quality: plan.quality,
|
|
859
|
+
authoringSkill: plan.authoringSkill,
|
|
860
|
+
authoringSkillSource: plan.authoringSkillSource,
|
|
861
|
+
authoringSkillInvalid: plan.invalidAuthoringSkill,
|
|
862
|
+
hfEnvOverrides: plan.hfEnvOverrides,
|
|
863
|
+
catalogUsage: plan.catalogUsage,
|
|
864
|
+
format: plan.format,
|
|
865
|
+
gifLoop: plan.gifLoop,
|
|
866
|
+
gifFpsCapped: plan.gifFpsCapped,
|
|
867
|
+
hlsSegmentSeconds: plan.hlsSegmentSeconds,
|
|
868
|
+
workers: plan.workers,
|
|
869
|
+
gpu: plan.useGpu,
|
|
870
|
+
browserGpuMode: plan.browserGpuMode,
|
|
871
|
+
hdrMode: plan.hdrMode,
|
|
872
|
+
crf: plan.crf,
|
|
873
|
+
vp9CpuUsed: plan.vp9CpuUsed,
|
|
874
|
+
videoBitrate: plan.videoBitrate,
|
|
875
|
+
videoFrameFormat: plan.videoFrameFormat,
|
|
876
|
+
quiet: batchQuiet,
|
|
877
|
+
browserPath,
|
|
878
|
+
entryFile: plan.entryFile,
|
|
879
|
+
outputResolution: plan.outputResolution,
|
|
880
|
+
outputResolutionAspectAgnostic: plan.outputResolutionAspectAgnostic,
|
|
881
|
+
outputResolutionRaw: plan.outputResolutionRaw,
|
|
882
|
+
pageNavigationTimeoutMs: plan.pageNavigationTimeoutMs,
|
|
883
|
+
protocolTimeout: plan.protocolTimeout,
|
|
884
|
+
playerReadyTimeout: plan.playerReadyTimeout,
|
|
885
|
+
debug: plan.debug,
|
|
886
|
+
resumeSegments: plan.resumeSegments,
|
|
887
|
+
keepSegments: plan.keepSegments,
|
|
888
|
+
bestEffort: plan.bestEffort,
|
|
889
|
+
exitAfterComplete: false,
|
|
890
|
+
throwOnError: true,
|
|
891
|
+
skipFeedback: true,
|
|
892
|
+
desktopHint: false,
|
|
893
|
+
manageDeParallelRouterBreaker: plan.batchConcurrency <= 1
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
async function executeBatchRender(plan, browserPath, batchModule, preparedBatch, dependencies, cancellation) {
|
|
897
|
+
const batchQuiet = plan.quiet || plan.batchJson;
|
|
898
|
+
const renderOptionsBase = batchRowRenderOptions(plan, browserPath);
|
|
899
|
+
const manifest = await batchModule.runBatchRender({
|
|
900
|
+
prepared: preparedBatch,
|
|
901
|
+
concurrency: plan.batchConcurrency,
|
|
902
|
+
failFast: plan.batchFailFast,
|
|
903
|
+
quiet: batchQuiet,
|
|
904
|
+
json: plan.batchJson,
|
|
905
|
+
renderOne: (row) => {
|
|
906
|
+
assertRenderActive(cancellation);
|
|
907
|
+
const options = { ...renderOptionsBase, variables: row.variables };
|
|
908
|
+
if (plan.useDocker) options.pageSideCompositing = plan.pageSideCompositing;
|
|
909
|
+
const execute = plan.useDocker ? dependencies.renderDocker : dependencies.renderLocal;
|
|
910
|
+
return execute(plan.project.dir, row.outputPath, options, cancellation);
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
if (manifest.failed > 0) setCommandExitCode(1);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// src/commands/render.ts
|
|
917
|
+
import { freemem, tmpdir } from "os";
|
|
918
|
+
import { resolve as resolve3, dirname as dirname2, join as join2, basename } from "path";
|
|
919
|
+
import { execFileSync as execFileSync2, spawn } from "child_process";
|
|
920
|
+
|
|
921
|
+
// src/utils/webmAlphaCheck.ts
|
|
922
|
+
import { execFileSync } from "child_process";
|
|
923
|
+
function webmAlphaAdvisory(format, probe) {
|
|
924
|
+
if (format !== "webm") return void 0;
|
|
925
|
+
if (!probe.probed) return void 0;
|
|
926
|
+
if (!probe.alphaMode) {
|
|
927
|
+
return "The WebM output has no VP9 alpha sidecar (the ALPHA_MODE stream tag is absent), so transparency was flattened to opaque. Your ffmpeg/libvpx-vp9 build cannot emit the alpha plane on this platform. For guaranteed transparency, re-render with --format mov (ProRes 4444).";
|
|
928
|
+
}
|
|
929
|
+
if (probe.sampledAlphaFullyOpaque) {
|
|
930
|
+
return "The WebM declares alpha (ALPHA_MODE=1) but every sampled decoded pixel reads alpha=255. This may be intentional (the composition has no transparent regions in the samples) OR your ffmpeg/libvpx-vp9 build wrote the tag without emitting the alpha side data \u2014 a known Windows-build quirk. To rule it out, re-render with --format mov (ProRes 4444), or with --format png-sequence and encode the frames yourself: ffmpeg -framerate <fps> -i frame_%06d.png -c:v prores_ks -profile:v 4444 -pix_fmt yuva444p10le out.mov";
|
|
931
|
+
}
|
|
932
|
+
return void 0;
|
|
933
|
+
}
|
|
934
|
+
function probeWebmAlpha(filePath) {
|
|
935
|
+
try {
|
|
936
|
+
const ffprobePath = findFFprobe();
|
|
937
|
+
if (!ffprobePath) return { probed: false, alphaMode: false };
|
|
938
|
+
const raw = execFileSync(
|
|
939
|
+
ffprobePath,
|
|
940
|
+
[
|
|
941
|
+
"-v",
|
|
942
|
+
"error",
|
|
943
|
+
"-select_streams",
|
|
944
|
+
"v:0",
|
|
945
|
+
"-show_entries",
|
|
946
|
+
"stream=codec_name:stream_tags=alpha_mode",
|
|
947
|
+
"-of",
|
|
948
|
+
"json",
|
|
949
|
+
"--",
|
|
950
|
+
filePath
|
|
951
|
+
],
|
|
952
|
+
{ encoding: "utf-8", timeout: 15e3, windowsHide: true }
|
|
953
|
+
);
|
|
954
|
+
const parsed = JSON.parse(raw);
|
|
955
|
+
const stream = parsed.streams?.[0];
|
|
956
|
+
if (!stream || typeof stream.codec_name !== "string") {
|
|
957
|
+
return { probed: false, alphaMode: false };
|
|
958
|
+
}
|
|
959
|
+
const tags = stream.tags ?? {};
|
|
960
|
+
const alphaMode = Object.entries(tags).some(
|
|
961
|
+
([k, v]) => k.toLowerCase() === "alpha_mode" && String(v) === "1"
|
|
962
|
+
);
|
|
963
|
+
const probe = { probed: true, alphaMode };
|
|
964
|
+
if (alphaMode) {
|
|
965
|
+
const opaque = sampledAlphaIsFullyOpaque(filePath);
|
|
966
|
+
if (opaque === true) probe.sampledAlphaFullyOpaque = true;
|
|
967
|
+
}
|
|
968
|
+
return probe;
|
|
969
|
+
} catch {
|
|
970
|
+
return { probed: false, alphaMode: false };
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
var BYTES_PER_SAMPLE_FRAME = 8 * 8 * 4;
|
|
974
|
+
var MAX_SAMPLE_BYTES = BYTES_PER_SAMPLE_FRAME * 3;
|
|
975
|
+
function sampledAlphaIsFullyOpaque(filePath) {
|
|
976
|
+
const ffmpegPath = findFFmpeg();
|
|
977
|
+
if (!ffmpegPath) return void 0;
|
|
978
|
+
try {
|
|
979
|
+
const buf = execFileSync(
|
|
980
|
+
ffmpegPath,
|
|
981
|
+
[
|
|
982
|
+
"-v",
|
|
983
|
+
"error",
|
|
984
|
+
"-c:v",
|
|
985
|
+
"libvpx-vp9",
|
|
986
|
+
"-i",
|
|
987
|
+
filePath,
|
|
988
|
+
"-frames:v",
|
|
989
|
+
"3",
|
|
990
|
+
"-vf",
|
|
991
|
+
"scale=8:8",
|
|
992
|
+
"-pix_fmt",
|
|
993
|
+
"rgba",
|
|
994
|
+
"-f",
|
|
995
|
+
"rawvideo",
|
|
996
|
+
"-"
|
|
997
|
+
],
|
|
998
|
+
{
|
|
999
|
+
timeout: 3e4,
|
|
1000
|
+
maxBuffer: 4096,
|
|
1001
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1002
|
+
windowsHide: true
|
|
1003
|
+
}
|
|
1004
|
+
);
|
|
1005
|
+
if (buf.length === 0 || buf.length > MAX_SAMPLE_BYTES || buf.length % BYTES_PER_SAMPLE_FRAME !== 0) {
|
|
1006
|
+
return void 0;
|
|
1007
|
+
}
|
|
1008
|
+
for (let i = 3; i < buf.length; i += 4) {
|
|
1009
|
+
if (buf[i] !== 255) return false;
|
|
1010
|
+
}
|
|
1011
|
+
return true;
|
|
1012
|
+
} catch {
|
|
1013
|
+
return void 0;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
function warnIfWebmAlphaDropped(outputPath, format, quiet) {
|
|
1017
|
+
if (quiet || format !== "webm") return;
|
|
1018
|
+
const advisory = webmAlphaAdvisory(format, probeWebmAlpha(outputPath));
|
|
1019
|
+
if (!advisory) return;
|
|
1020
|
+
console.warn(`
|
|
1021
|
+
${c.warn("\u26A0")} ${c.bold("Transparency not preserved")}`);
|
|
1022
|
+
console.warn(` ${c.dim(advisory)}
|
|
1023
|
+
`);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// src/ui/progress.ts
|
|
1027
|
+
var { stdout } = process;
|
|
1028
|
+
function renderProgress(percent, stage, row) {
|
|
1029
|
+
const width = 25;
|
|
1030
|
+
const filled = Math.floor(percent / (100 / width));
|
|
1031
|
+
const empty = width - filled;
|
|
1032
|
+
const bar = c.progress("\u2588".repeat(filled)) + c.dim("\u2591".repeat(empty));
|
|
1033
|
+
const line = ` ${bar} ${c.bold(String(Math.round(percent)) + "%")} ${c.dim(stage)}`;
|
|
1034
|
+
if (row !== void 0 && stdout.isTTY) {
|
|
1035
|
+
stdout.write(`\x1B[${row};1H\x1B[2K${line}`);
|
|
1036
|
+
} else if (!stdout.isTTY) {
|
|
1037
|
+
stdout.write(`${line}
|
|
1038
|
+
`);
|
|
1039
|
+
} else {
|
|
1040
|
+
stdout.write(`\r\x1B[2K${line}`);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// src/utils/dockerRunArgs.ts
|
|
1045
|
+
function resolveDockerPlatform(arch = process.arch, env = process.env) {
|
|
1046
|
+
const override = env.HYPERFRAMES_DOCKER_PLATFORM;
|
|
1047
|
+
if (override && override.trim() !== "") return override.trim();
|
|
1048
|
+
return arch === "arm64" ? "linux/arm64" : "linux/amd64";
|
|
1049
|
+
}
|
|
1050
|
+
function buildDockerRunArgs(input) {
|
|
1051
|
+
const { imageTag, projectDir, outputDir, outputFilename, options } = input;
|
|
1052
|
+
const platform = input.platform ?? resolveDockerPlatform();
|
|
1053
|
+
return [
|
|
1054
|
+
"run",
|
|
1055
|
+
"--rm",
|
|
1056
|
+
"--platform",
|
|
1057
|
+
platform,
|
|
1058
|
+
"--shm-size=2g",
|
|
1059
|
+
// GPU encoding requires host GPU passthrough.
|
|
1060
|
+
...options.gpu ? ["--gpus", "all"] : [],
|
|
1061
|
+
"-v",
|
|
1062
|
+
`${projectDir}:/project:ro`,
|
|
1063
|
+
"-v",
|
|
1064
|
+
`${outputDir}:/output`,
|
|
1065
|
+
// Keep debug artifacts on the mounted host output path. The producer roots
|
|
1066
|
+
// `.debug` at dirname(PRODUCER_RENDERS_DIR), so `/output/renders` maps to
|
|
1067
|
+
// `/output/.debug/<job id>` instead of a disposable container path.
|
|
1068
|
+
...options.debug ? ["-e", "PRODUCER_RENDERS_DIR=/output/renders"] : [],
|
|
1069
|
+
imageTag,
|
|
1070
|
+
"/project",
|
|
1071
|
+
"--output",
|
|
1072
|
+
`/output/${outputFilename}`,
|
|
1073
|
+
"--fps",
|
|
1074
|
+
fpsToFfmpegArg(options.fps),
|
|
1075
|
+
"--quality",
|
|
1076
|
+
options.quality,
|
|
1077
|
+
"--format",
|
|
1078
|
+
options.format,
|
|
1079
|
+
...options.gifLoop != null ? ["--gif-loop", String(options.gifLoop)] : [],
|
|
1080
|
+
...options.hlsSegmentSeconds != null ? ["--hls-segment-seconds", String(options.hlsSegmentSeconds)] : [],
|
|
1081
|
+
...options.workers != null ? ["--workers", String(options.workers)] : [],
|
|
1082
|
+
...options.crf != null ? ["--crf", String(options.crf)] : [],
|
|
1083
|
+
...options.vp9CpuUsed != null ? ["--vp9-cpu-used", String(options.vp9CpuUsed)] : [],
|
|
1084
|
+
...options.videoBitrate ? ["--video-bitrate", options.videoBitrate] : [],
|
|
1085
|
+
...options.videoFrameFormat && options.videoFrameFormat !== "auto" ? ["--video-frame-format", options.videoFrameFormat] : [],
|
|
1086
|
+
...options.quiet ? ["--quiet"] : [],
|
|
1087
|
+
...options.debug ? ["--debug"] : [],
|
|
1088
|
+
// The in-container CLI is best-effort by default. Only forward the
|
|
1089
|
+
// explicit strict opt-in so Docker and local renders cannot drift.
|
|
1090
|
+
...options.bestEffort === false ? ["--no-best-effort"] : [],
|
|
1091
|
+
...options.gpu ? ["--gpu"] : [],
|
|
1092
|
+
...options.browserGpu ? [] : ["--no-browser-gpu"],
|
|
1093
|
+
...options.hdrMode === "force-hdr" ? ["--hdr"] : [],
|
|
1094
|
+
...options.hdrMode === "force-sdr" ? ["--sdr"] : [],
|
|
1095
|
+
...options.variables && Object.keys(options.variables).length > 0 ? ["--variables", JSON.stringify(options.variables)] : [],
|
|
1096
|
+
...options.entryFile ? ["--composition", options.entryFile] : [],
|
|
1097
|
+
...options.outputResolution ? ["--resolution", options.outputResolution] : [],
|
|
1098
|
+
...options.pageSideCompositing === false ? ["--no-page-side-compositing"] : [],
|
|
1099
|
+
...options.experimentalFastCapture ? ["--experimental-fast-capture"] : [],
|
|
1100
|
+
...options.pageNavigationTimeoutMs != null ? ["--browser-timeout", String(options.pageNavigationTimeoutMs / 1e3)] : [],
|
|
1101
|
+
...options.protocolTimeoutMs != null ? ["--protocol-timeout", String(options.protocolTimeoutMs)] : [],
|
|
1102
|
+
...options.playerReadyTimeoutMs != null ? ["--player-ready-timeout", String(options.playerReadyTimeoutMs)] : []
|
|
1103
|
+
];
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
// src/utils/dockerStderrTail.ts
|
|
1107
|
+
var MAX_TAIL_CHARS = 2e3;
|
|
1108
|
+
var MAX_LINE_CHARS = 160;
|
|
1109
|
+
var STACK_FRAME = /^at\s/;
|
|
1110
|
+
var ERROR_LINE = /error|fail|exception|cannot|not found|denied|killed|no space/i;
|
|
1111
|
+
function createStderrTail() {
|
|
1112
|
+
let buffer = "";
|
|
1113
|
+
return {
|
|
1114
|
+
push(chunk) {
|
|
1115
|
+
buffer = (buffer + chunk).slice(-MAX_TAIL_CHARS);
|
|
1116
|
+
},
|
|
1117
|
+
tail: () => buffer.trim()
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
function lastErrorLine(tail) {
|
|
1121
|
+
const lines = tail.split(/[\r\n]+/).map((line2) => line2.trim()).filter((line2) => line2 && !STACK_FRAME.test(line2));
|
|
1122
|
+
const line = [...lines].reverse().find((l) => ERROR_LINE.test(l)) ?? lines.at(-1) ?? "";
|
|
1123
|
+
return line.slice(0, MAX_LINE_CHARS);
|
|
1124
|
+
}
|
|
1125
|
+
var DockerRenderExitError = class extends Error {
|
|
1126
|
+
constructor(exitCode, stderrTail) {
|
|
1127
|
+
const last = lastErrorLine(stderrTail);
|
|
1128
|
+
super(`Docker render exited with code ${exitCode}${last ? `: ${last}` : ""}`);
|
|
1129
|
+
this.name = "DockerRenderExitError";
|
|
1130
|
+
}
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1133
|
+
// src/browser/macosOldChromeCrash.ts
|
|
1134
|
+
var DYLD_SYMBOL_NOT_FOUND = /Symbol not found:/i;
|
|
1135
|
+
var MACOS_13_ONLY_SYMBOL = /_kVTCompressionPropertyKey_ReferenceBufferCount/;
|
|
1136
|
+
var VIDEO_TOOLBOX = /VideoToolbox/;
|
|
1137
|
+
function isMacosOldChromeCrashError(errorMessage) {
|
|
1138
|
+
if (!/Failed to launch the browser process/i.test(errorMessage)) return false;
|
|
1139
|
+
if (!DYLD_SYMBOL_NOT_FOUND.test(errorMessage)) return false;
|
|
1140
|
+
return MACOS_13_ONLY_SYMBOL.test(errorMessage) || VIDEO_TOOLBOX.test(errorMessage);
|
|
1141
|
+
}
|
|
1142
|
+
function macosOldChromeCrashRemediation(errorMessage) {
|
|
1143
|
+
if (process.platform !== "darwin") return void 0;
|
|
1144
|
+
if (!isMacosOldChromeCrashError(errorMessage)) return void 0;
|
|
1145
|
+
return [
|
|
1146
|
+
"chrome-headless-shell crashed at launch (macOS dyld: Symbol not found in VideoToolbox).",
|
|
1147
|
+
"The pinned Chromium build requires macOS 13+. HyperFrames installs Chrome 150 on macOS 12 by",
|
|
1148
|
+
"itself, so this crash means a newer browser was supplied. Unset the override, or point it at",
|
|
1149
|
+
"an older chrome-headless-shell:",
|
|
1150
|
+
"",
|
|
1151
|
+
" npx @puppeteer/browsers install chrome-headless-shell@150",
|
|
1152
|
+
' export HYPERFRAMES_BROWSER_PATH="$HOME/.cache/puppeteer/chrome-headless-shell/mac-150.0.7871.124/chrome-headless-shell-mac-x64/chrome-headless-shell"',
|
|
1153
|
+
"",
|
|
1154
|
+
"(PRODUCER_HEADLESS_SHELL_PATH works as an alias for the same override.)",
|
|
1155
|
+
"Alternatively, point HYPERFRAMES_BROWSER_PATH at your installed Google Chrome",
|
|
1156
|
+
'("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome") to fall back to the screenshot',
|
|
1157
|
+
"capture path."
|
|
1158
|
+
].join("\n");
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// src/commands/render.ts
|
|
1162
|
+
var examples = [
|
|
1163
|
+
["Render to MP4", "hyperframes render --output output.mp4"],
|
|
1164
|
+
["Render a specific composition", "hyperframes render -c compositions/intro.html -o intro.mp4"],
|
|
1165
|
+
[
|
|
1166
|
+
"Upsample any composition to 4K (supersamples via Chrome DPR)",
|
|
1167
|
+
"hyperframes render --resolution 4k --output 4k.mp4"
|
|
1168
|
+
],
|
|
1169
|
+
["Render transparent overlay (ProRes)", "hyperframes render --format mov --output overlay.mov"],
|
|
1170
|
+
["Render transparent WebM overlay", "hyperframes render --format webm --output overlay.webm"],
|
|
1171
|
+
[
|
|
1172
|
+
"Render animated GIF for PRs/docs",
|
|
1173
|
+
"hyperframes render --format gif --fps 15 --gif-loop 0 --output demo.gif"
|
|
1174
|
+
],
|
|
1175
|
+
[
|
|
1176
|
+
"Render PNG sequence (RGBA frames for AE/Nuke/Fusion)",
|
|
1177
|
+
"hyperframes render --format png-sequence --output frames/"
|
|
1178
|
+
],
|
|
1179
|
+
[
|
|
1180
|
+
"Render HLS VOD (master playlist + MPEG-TS segments in a directory)",
|
|
1181
|
+
"hyperframes render --format hls --output stream/"
|
|
1182
|
+
],
|
|
1183
|
+
["High quality at 60fps", "hyperframes render --fps 60 --quality high --output hd.mp4"],
|
|
1184
|
+
["Deterministic render via Docker", "hyperframes render --docker --output deterministic.mp4"],
|
|
1185
|
+
["Parallel rendering with 6 workers", "hyperframes render --workers 6 --output fast.mp4"],
|
|
1186
|
+
["Opt out of browser GPU render", "hyperframes render --no-browser-gpu --output cpu.mp4"],
|
|
1187
|
+
[
|
|
1188
|
+
"Show full lint findings instead of the summary line",
|
|
1189
|
+
"hyperframes render --lint-verbose --output out.mp4"
|
|
1190
|
+
],
|
|
1191
|
+
[
|
|
1192
|
+
"Relocate frame cache off C: (Windows) or another small partition",
|
|
1193
|
+
"hyperframes render --frames-cache-dir D:/hf-cache --output out.mp4"
|
|
1194
|
+
],
|
|
1195
|
+
["HDR output (auto-detected)", "hyperframes render --output hdr-output.mp4"],
|
|
1196
|
+
[
|
|
1197
|
+
"Override composition variables (parametrized render)",
|
|
1198
|
+
`hyperframes render --variables '{"title":"Q4 Report","theme":"dark"}' --output q4.mp4`
|
|
1199
|
+
],
|
|
1200
|
+
[
|
|
1201
|
+
"Variables from a JSON file",
|
|
1202
|
+
"hyperframes render --variables-file ./vars.json --output out.mp4"
|
|
1203
|
+
],
|
|
1204
|
+
[
|
|
1205
|
+
"Batch render one output per variables row",
|
|
1206
|
+
'hyperframes render --batch rows.json --output "renders/{name}.mp4"'
|
|
1207
|
+
]
|
|
1208
|
+
];
|
|
1209
|
+
var render_default = defineCommand({
|
|
1210
|
+
meta: {
|
|
1211
|
+
name: "render",
|
|
1212
|
+
description: "Render a composition to MP4, WebM, MOV, GIF, HLS, or a PNG sequence"
|
|
1213
|
+
},
|
|
1214
|
+
args: {
|
|
1215
|
+
dir: {
|
|
1216
|
+
type: "positional",
|
|
1217
|
+
description: "Project directory",
|
|
1218
|
+
required: false
|
|
1219
|
+
},
|
|
1220
|
+
composition: {
|
|
1221
|
+
type: "string",
|
|
1222
|
+
alias: "c",
|
|
1223
|
+
description: "Render a specific composition file instead of index.html (e.g. compositions/intro.html). Sub-compositions using <template> wrappers must be referenced from index.html via data-composition-src. Pass `.` (or omit the flag) to render the project's index.html."
|
|
1224
|
+
},
|
|
1225
|
+
output: {
|
|
1226
|
+
type: "string",
|
|
1227
|
+
alias: "o",
|
|
1228
|
+
description: "Output path (default: renders/<name>.mp4)"
|
|
1229
|
+
},
|
|
1230
|
+
fps: {
|
|
1231
|
+
type: "string",
|
|
1232
|
+
alias: "f",
|
|
1233
|
+
description: "Frame rate. Accepts integer (24, 25, 30, 50, 60, 120, 240) or ffmpeg-style rational (30000/1001 for NTSC 29.97, 24000/1001 for 23.976, 60000/1001 for 59.94). Range 1-240. Defaults to the composition's root data-fps, else 30."
|
|
1234
|
+
// No `default` here on purpose: citty would set args.fps="30" on
|
|
1235
|
+
// omission, which would make explicitFps always non-null and short-
|
|
1236
|
+
// circuit the data-fps resolution below (resolveDefaultFpsArg). The
|
|
1237
|
+
// "30" fallback lives at the parseFps(fpsArg ?? "30") call instead.
|
|
1238
|
+
},
|
|
1239
|
+
quality: {
|
|
1240
|
+
type: "string",
|
|
1241
|
+
alias: "q",
|
|
1242
|
+
description: "Quality: draft, looks, delivery, or standard/high. looks is the default (CRF 16). delivery is high. MOV always uses the fixed alpha-preserving ProRes 4444 profile.",
|
|
1243
|
+
default: "looks"
|
|
1244
|
+
},
|
|
1245
|
+
skill: {
|
|
1246
|
+
type: "string",
|
|
1247
|
+
description: "Authoring workflow skill that initiated this render (e.g. product-launch-video). Recorded on anonymous render telemetry for per-skill usage breakdowns; ignored unless it is a slug."
|
|
1248
|
+
},
|
|
1249
|
+
format: {
|
|
1250
|
+
type: "string",
|
|
1251
|
+
description: "Output format: mp4, webm, mov, gif, png-sequence, hls (MOV/WebM render with transparency; png-sequence writes RGBA frames to a directory for AE/Nuke/Fusion ingest; gif is best at 15fps for PRs/docs; hls writes a VOD playlist directory \u2014 H.264/AAC, SDR only, no GPU encoding)",
|
|
1252
|
+
default: "mp4"
|
|
1253
|
+
},
|
|
1254
|
+
"gif-loop": {
|
|
1255
|
+
type: "string",
|
|
1256
|
+
description: "GIF loop count, 0 = infinite. Range: 0-65535. Only used with --format gif."
|
|
1257
|
+
},
|
|
1258
|
+
"hls-segment-seconds": {
|
|
1259
|
+
type: "string",
|
|
1260
|
+
description: "HLS target segment length in whole seconds (default: 4). Range: 1-60. Also fixes the encoder GOP at segment x fps frames so every segment starts on a keyframe. Only used with --format hls."
|
|
1261
|
+
},
|
|
1262
|
+
"video-frame-format": {
|
|
1263
|
+
type: "string",
|
|
1264
|
+
description: "Source video frame extraction format: auto, jpg, png (default: auto). Use png for UI recordings, screen captures, and color-sensitive source videos; alpha-capable sources always extract as PNG.",
|
|
1265
|
+
default: "auto"
|
|
1266
|
+
},
|
|
1267
|
+
workers: {
|
|
1268
|
+
type: "string",
|
|
1269
|
+
alias: "w",
|
|
1270
|
+
description: "Parallel render workers (number or 'auto'). Default: auto. Each worker launches a separate Chrome process (~256 MB RAM)."
|
|
1271
|
+
},
|
|
1272
|
+
docker: {
|
|
1273
|
+
type: "boolean",
|
|
1274
|
+
description: "Use Docker for deterministic render",
|
|
1275
|
+
default: false
|
|
1276
|
+
},
|
|
1277
|
+
hdr: {
|
|
1278
|
+
type: "boolean",
|
|
1279
|
+
description: "Force HDR output even if no HDR sources are detected",
|
|
1280
|
+
default: false
|
|
1281
|
+
},
|
|
1282
|
+
sdr: {
|
|
1283
|
+
type: "boolean",
|
|
1284
|
+
description: "Force SDR output even if HDR sources are detected",
|
|
1285
|
+
default: false
|
|
1286
|
+
},
|
|
1287
|
+
crf: {
|
|
1288
|
+
type: "string",
|
|
1289
|
+
description: "Override MP4/WebM encoder CRF. Mutually exclusive with --video-bitrate; unsupported for MOV."
|
|
1290
|
+
},
|
|
1291
|
+
"video-bitrate": {
|
|
1292
|
+
type: "string",
|
|
1293
|
+
description: "Target MP4/WebM video bitrate such as 10M. Mutually exclusive with --crf; unsupported for MOV."
|
|
1294
|
+
},
|
|
1295
|
+
"vp9-cpu-used": {
|
|
1296
|
+
type: "string",
|
|
1297
|
+
description: "libvpx-vp9 -cpu-used value for WebM encodes (-8 to 8). Higher is faster with a larger quality/size tradeoff. Env: PRODUCER_VP9_CPU_USED."
|
|
1298
|
+
},
|
|
1299
|
+
gpu: { type: "boolean", description: "Use GPU encoding", default: false },
|
|
1300
|
+
"browser-gpu": {
|
|
1301
|
+
type: "boolean",
|
|
1302
|
+
description: "Force host GPU acceleration for Chrome/WebGL capture. Default: auto (probe on first launch; fall back to software if no GPU). Use --no-browser-gpu to force software (SwiftShader)."
|
|
1303
|
+
},
|
|
1304
|
+
quiet: {
|
|
1305
|
+
type: "boolean",
|
|
1306
|
+
description: "Suppress verbose output",
|
|
1307
|
+
default: false
|
|
1308
|
+
},
|
|
1309
|
+
"lint-verbose": {
|
|
1310
|
+
type: "boolean",
|
|
1311
|
+
description: "Show full lint findings instead of the summary line",
|
|
1312
|
+
default: false
|
|
1313
|
+
},
|
|
1314
|
+
debug: {
|
|
1315
|
+
type: "boolean",
|
|
1316
|
+
description: "Write full render diagnostics and keep intermediate artifacts under the producer .debug directory.",
|
|
1317
|
+
default: false
|
|
1318
|
+
},
|
|
1319
|
+
"best-effort": {
|
|
1320
|
+
type: "boolean",
|
|
1321
|
+
description: "Allow output with structured capture-readiness warnings (default). Use --no-best-effort to fail on missing or unready media.",
|
|
1322
|
+
default: true
|
|
1323
|
+
},
|
|
1324
|
+
strict: {
|
|
1325
|
+
type: "boolean",
|
|
1326
|
+
description: "Fail render on lint errors",
|
|
1327
|
+
default: false
|
|
1328
|
+
},
|
|
1329
|
+
"strict-all": {
|
|
1330
|
+
type: "boolean",
|
|
1331
|
+
description: "Fail render on lint errors AND warnings",
|
|
1332
|
+
default: false
|
|
1333
|
+
},
|
|
1334
|
+
"max-concurrent-renders": {
|
|
1335
|
+
type: "string",
|
|
1336
|
+
description: "Max concurrent renders when using the producer server (1-10). Default: 2."
|
|
1337
|
+
},
|
|
1338
|
+
variables: {
|
|
1339
|
+
type: "string",
|
|
1340
|
+
description: `JSON object of variable values, merged over the composition's data-composition-variables defaults. Example: --variables '{"title":"Hello"}'. Read inside the composition via window.__hyperframes.getVariables().`
|
|
1341
|
+
},
|
|
1342
|
+
"variables-file": {
|
|
1343
|
+
type: "string",
|
|
1344
|
+
description: "Path to a JSON file with variable values (alternative to --variables). The file must contain a single JSON object."
|
|
1345
|
+
},
|
|
1346
|
+
"strict-variables": {
|
|
1347
|
+
type: "boolean",
|
|
1348
|
+
description: "Fail render if any --variables key is undeclared or has a wrong type vs the composition's data-composition-variables. Without this flag, mismatches are warnings.",
|
|
1349
|
+
default: false
|
|
1350
|
+
},
|
|
1351
|
+
batch: {
|
|
1352
|
+
type: "string",
|
|
1353
|
+
description: 'Path to a JSON array of variable rows (or {"rows":[...]}). Renders one output per row.'
|
|
1354
|
+
},
|
|
1355
|
+
"batch-concurrency": {
|
|
1356
|
+
type: "string",
|
|
1357
|
+
description: "Maximum number of batch rows to render at once. Default: 1, because each render already parallelizes across workers."
|
|
1358
|
+
},
|
|
1359
|
+
"batch-fail-fast": {
|
|
1360
|
+
type: "boolean",
|
|
1361
|
+
description: "Stop launching new batch rows after the first row failure.",
|
|
1362
|
+
default: false
|
|
1363
|
+
},
|
|
1364
|
+
json: {
|
|
1365
|
+
type: "boolean",
|
|
1366
|
+
description: "With --batch, emit exactly one final JSON result document.",
|
|
1367
|
+
default: false
|
|
1368
|
+
},
|
|
1369
|
+
resolution: {
|
|
1370
|
+
type: "string",
|
|
1371
|
+
description: "Output resolution preset: landscape (1920x1080), portrait (1080x1920), landscape-4k (3840x2160), portrait-4k (2160x3840), square (1080x1080), square-4k (2160x2160). Aliases: 1080p, 4k, uhd, 1080p-square, square-1080p, 4k-square. The composition is unchanged \u2014 Chrome renders at higher DPR (deviceScaleFactor) so the captured screenshot lands at the requested dimensions. Aspect ratio must match the composition; the scale must be an integer multiple. Not yet supported with --hdr."
|
|
1372
|
+
},
|
|
1373
|
+
"page-side-compositing": {
|
|
1374
|
+
type: "boolean",
|
|
1375
|
+
description: "Run shader transitions on a page-side WebGL canvas inside Chrome instead of the Node-side layered blend. ~6\xD7 faster for SDR shader-transition renders. Used for mp4, hls and gif output without HDR content; for mp4 and hls it usually turns off under --experimental-fast-capture. webm and mov output take the layered path. --no-page-side-compositing forces the layered path for mp4 and hls; gif always uses the page-side canvas.",
|
|
1376
|
+
default: true
|
|
1377
|
+
},
|
|
1378
|
+
"browser-timeout": {
|
|
1379
|
+
type: "string",
|
|
1380
|
+
description: "Puppeteer page-navigation timeout in SECONDS for the entry HTML. Increase when heavy compositions (many videos / fonts / asset requests) cannot reach domcontentloaded within the 60s default (see issue #1199). Accepts 0.001-86400 (24h cap). Note: this controls page.goto only \u2014 very heavy compositions may also need PRODUCER_PUPPETEER_PROTOCOL_TIMEOUT_MS / PRODUCER_PLAYER_READY_TIMEOUT_MS bumped (the post-goto window.__hf readiness poll has its own 45s budget). Env fallback: PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS (MILLISECONDS)."
|
|
1381
|
+
},
|
|
1382
|
+
"protocol-timeout": {
|
|
1383
|
+
type: "string",
|
|
1384
|
+
description: "CDP protocol timeout in ms. Increase on slow/low-memory machines where Chrome operations time out. Default: 300000 (5 min). Env: PRODUCER_PUPPETEER_PROTOCOL_TIMEOUT_MS."
|
|
1385
|
+
},
|
|
1386
|
+
"player-ready-timeout": {
|
|
1387
|
+
type: "string",
|
|
1388
|
+
description: "Timeout in ms for the composition player to become ready. Increase for complex compositions on slow hardware. Default: 45000 (45 s). Env: PRODUCER_PLAYER_READY_TIMEOUT_MS."
|
|
1389
|
+
},
|
|
1390
|
+
resume: {
|
|
1391
|
+
type: "boolean",
|
|
1392
|
+
description: "Segmented capture only (HF_SEGMENTED_CAPTURE=true): reuse segments a previous run of the same composition and settings already finished, recorded in renders/.hf-segments/<hash>/segments.json. Each reused segment is re-validated before it is skipped.",
|
|
1393
|
+
default: false
|
|
1394
|
+
},
|
|
1395
|
+
"keep-segments": {
|
|
1396
|
+
type: "boolean",
|
|
1397
|
+
description: "Segmented capture only: keep renders/.hf-segments/<hash> after a successful render instead of deleting it.",
|
|
1398
|
+
default: false
|
|
1399
|
+
},
|
|
1400
|
+
"low-memory-mode": {
|
|
1401
|
+
type: "boolean",
|
|
1402
|
+
description: "Force the low-memory safe render profile on (--low-memory-mode) or off (--no-low-memory-mode). Safe mode pins to 1 worker, uses screenshot capture, and skips auto-worker calibration to avoid memory thrash on constrained machines. Default: auto-detected from total RAM (<= 8 GB). Env: PRODUCER_LOW_MEMORY_MODE."
|
|
1403
|
+
},
|
|
1404
|
+
"experimental-fast-capture": {
|
|
1405
|
+
type: "boolean",
|
|
1406
|
+
description: "Capture frames via Chrome's drawElementImage API instead of Page.captureScreenshot \u2014 reads DOM paint records directly, ~2x faster. Default: on where it can engage (macOS + hardware-GPU browser); incompatible compositions and self-verification failures fall back to screenshot capture automatically. Pass =false to disable. Env: PRODUCER_EXPERIMENTAL_FAST_CAPTURE."
|
|
1407
|
+
// No `default` — an omitted flag must stay `undefined` so the `!= null`
|
|
1408
|
+
// guard below leaves PRODUCER_EXPERIMENTAL_FAST_CAPTURE untouched and the
|
|
1409
|
+
// env fallback survives (matches the --low-memory-mode idiom).
|
|
1410
|
+
},
|
|
1411
|
+
"frames-cache-dir": {
|
|
1412
|
+
type: "string",
|
|
1413
|
+
description: `Directory for the content-addressed extracted-frame cache. Use to relocate the cache off the system drive when the OS temp directory lives on a small partition (e.g. Windows C: exhaustion during long renders). Pass ${EXTRACT_CACHE_DIR_DISABLED_ALIASES.map((a) => `"${a}"`).join(" / ")} to disable caching entirely (frames extract into the render's workDir and are cleaned up when the render ends). Default: <tmpdir>/hyperframes-extract-cache-<uid>. Env: HYPERFRAMES_EXTRACT_CACHE_DIR.`
|
|
1414
|
+
}
|
|
1415
|
+
},
|
|
1416
|
+
// Keep the transport adapter thin: each phase has one ownership boundary.
|
|
1417
|
+
async run({ args }) {
|
|
1418
|
+
const plan = createRenderPlan(args);
|
|
1419
|
+
const cancellation = plan.useDocker ? void 0 : createRenderCancellationScope();
|
|
1420
|
+
try {
|
|
1421
|
+
seedProjectAuthoringSkill(plan.project.dir, args.skill);
|
|
1422
|
+
await presentRenderPlan(plan);
|
|
1423
|
+
await executeRenderPlan(
|
|
1424
|
+
plan,
|
|
1425
|
+
{
|
|
1426
|
+
renderDocker,
|
|
1427
|
+
renderLocal,
|
|
1428
|
+
checkResolution: checkRenderResolutionPreflight
|
|
1429
|
+
},
|
|
1430
|
+
cancellation
|
|
1431
|
+
);
|
|
1432
|
+
} catch (error) {
|
|
1433
|
+
if (cancellation?.signal.aborted) {
|
|
1434
|
+
const reason = cancellation.signal.reason;
|
|
1435
|
+
const message = reason instanceof Error ? reason.message : String(reason);
|
|
1436
|
+
process.stderr.write(`Render cancelled: ${message}
|
|
1437
|
+
`);
|
|
1438
|
+
requestCliExit(1);
|
|
1439
|
+
}
|
|
1440
|
+
throw error;
|
|
1441
|
+
} finally {
|
|
1442
|
+
cancellation?.dispose();
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1446
|
+
async function readCompositionDimensions(compositionHtml) {
|
|
1447
|
+
try {
|
|
1448
|
+
const { ensureDOMParser } = await import("./dom-IROKGVJI.js");
|
|
1449
|
+
ensureDOMParser();
|
|
1450
|
+
const doc = new DOMParser().parseFromString(compositionHtml, "text/html");
|
|
1451
|
+
const rootEl = doc.querySelector("[data-composition-id]");
|
|
1452
|
+
const width = parseInt(rootEl?.getAttribute("data-width") ?? "", 10);
|
|
1453
|
+
const height = parseInt(rootEl?.getAttribute("data-height") ?? "", 10);
|
|
1454
|
+
if (width > 0 && height > 0) return { width, height };
|
|
1455
|
+
} catch {
|
|
1456
|
+
}
|
|
1457
|
+
return void 0;
|
|
1458
|
+
}
|
|
1459
|
+
async function checkRenderResolutionPreflight(compositionHtml, outputResolution, modes) {
|
|
1460
|
+
if (!outputResolution) return void 0;
|
|
1461
|
+
const dims = await readCompositionDimensions(compositionHtml);
|
|
1462
|
+
if (!dims) return void 0;
|
|
1463
|
+
const effective = modes.aspectAgnostic === true ? suggestMatchingPreset(dims.width, dims.height, outputResolution) ?? outputResolution : outputResolution;
|
|
1464
|
+
const compat = checkOutputResolutionCompatibility({
|
|
1465
|
+
compositionWidth: dims.width,
|
|
1466
|
+
compositionHeight: dims.height,
|
|
1467
|
+
outputResolution: effective,
|
|
1468
|
+
alphaRequested: modes.alphaRequested,
|
|
1469
|
+
hdrRequested: modes.hdrRequested
|
|
1470
|
+
});
|
|
1471
|
+
if (compat.ok || !compat.message || !compat.kind) return void 0;
|
|
1472
|
+
return { message: compat.message, kind: compat.kind };
|
|
1473
|
+
}
|
|
1474
|
+
var DOCKER_IMAGE_PREFIX = "hyperframes-renderer";
|
|
1475
|
+
function dockerImageTag(version) {
|
|
1476
|
+
return `${DOCKER_IMAGE_PREFIX}:${version}`;
|
|
1477
|
+
}
|
|
1478
|
+
function resolveDockerfilePath() {
|
|
1479
|
+
const builtPath = resolve3(__dirname, "docker", "Dockerfile.render");
|
|
1480
|
+
const devPath = resolve3(__dirname, "..", "src", "docker", "Dockerfile.render");
|
|
1481
|
+
for (const p of [builtPath, devPath]) {
|
|
1482
|
+
try {
|
|
1483
|
+
statSync2(p);
|
|
1484
|
+
return p;
|
|
1485
|
+
} catch {
|
|
1486
|
+
continue;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
throw new Error("Dockerfile.render not found \u2014 CLI package may be corrupted");
|
|
1490
|
+
}
|
|
1491
|
+
function dockerImageExists(tag) {
|
|
1492
|
+
try {
|
|
1493
|
+
execFileSync2("docker", ["image", "inspect", tag], { stdio: "pipe", timeout: 1e4 });
|
|
1494
|
+
return true;
|
|
1495
|
+
} catch {
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
function dockerImageTagForPlatform(version, platform) {
|
|
1500
|
+
const archSuffix = platform === "linux/arm64" ? "-arm64" : "";
|
|
1501
|
+
return `${dockerImageTag(version)}${archSuffix}`;
|
|
1502
|
+
}
|
|
1503
|
+
function ensureDockerImage(version, platform, quiet) {
|
|
1504
|
+
const tag = dockerImageTagForPlatform(version, platform);
|
|
1505
|
+
if (dockerImageExists(tag)) {
|
|
1506
|
+
if (!quiet) console.log(c.dim(` Docker image: ${tag} (cached)`));
|
|
1507
|
+
return tag;
|
|
1508
|
+
}
|
|
1509
|
+
if (!quiet) console.log(c.dim(` Building Docker image: ${tag} (${platform})...`));
|
|
1510
|
+
const dockerfilePath = resolveDockerfilePath();
|
|
1511
|
+
const tmpDir = mkdtempSync(join2(tmpdir(), "hyperframes-docker-"));
|
|
1512
|
+
writeFileSync(join2(tmpDir, "Dockerfile"), readFileSync4(dockerfilePath));
|
|
1513
|
+
const targetArch = platform === "linux/arm64" ? "arm64" : "amd64";
|
|
1514
|
+
try {
|
|
1515
|
+
execFileSync2(
|
|
1516
|
+
"docker",
|
|
1517
|
+
[
|
|
1518
|
+
"build",
|
|
1519
|
+
"--platform",
|
|
1520
|
+
platform,
|
|
1521
|
+
"--build-arg",
|
|
1522
|
+
`HYPERFRAMES_VERSION=${version}`,
|
|
1523
|
+
"--build-arg",
|
|
1524
|
+
`TARGETARCH=${targetArch}`,
|
|
1525
|
+
"-t",
|
|
1526
|
+
tag,
|
|
1527
|
+
tmpDir
|
|
1528
|
+
],
|
|
1529
|
+
{ stdio: quiet ? "pipe" : "inherit", timeout: 6e5 }
|
|
1530
|
+
);
|
|
1531
|
+
} catch (error) {
|
|
1532
|
+
const message = normalizeErrorMessage(error);
|
|
1533
|
+
throw new Error(`Failed to build Docker image: ${message}`);
|
|
1534
|
+
} finally {
|
|
1535
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
1536
|
+
}
|
|
1537
|
+
if (!quiet) console.log(c.dim(` Docker image: ${tag} (built)`));
|
|
1538
|
+
return tag;
|
|
1539
|
+
}
|
|
1540
|
+
function resolveDockerHostPlatform(options) {
|
|
1541
|
+
const platform = resolveDockerPlatform();
|
|
1542
|
+
if (options.gpu && platform === "linux/arm64") {
|
|
1543
|
+
errorBox(
|
|
1544
|
+
"--gpu is not supported with --docker on arm64 hosts",
|
|
1545
|
+
"Docker Desktop/colima on Apple Silicon doesn't expose --gpus host passthrough to linux/arm64 containers.",
|
|
1546
|
+
"Drop --gpu, or run a native (non-Docker) render on this host, or set HYPERFRAMES_DOCKER_PLATFORM=linux/amd64 if you need GPU encoding (slow under qemu but works)."
|
|
1547
|
+
);
|
|
1548
|
+
failCommand();
|
|
1549
|
+
}
|
|
1550
|
+
if (!options.quiet && platform === "linux/arm64") {
|
|
1551
|
+
console.log(
|
|
1552
|
+
c.dim(
|
|
1553
|
+
" Host is arm64 \u2014 using linux/arm64 image with Playwright's chrome-headless-shell (output won't be byte-identical to amd64 renders; set HYPERFRAMES_DOCKER_PLATFORM=linux/amd64 to force parity)."
|
|
1554
|
+
)
|
|
1555
|
+
);
|
|
1556
|
+
}
|
|
1557
|
+
return platform;
|
|
1558
|
+
}
|
|
1559
|
+
async function renderDocker(projectDir, outputPath, options) {
|
|
1560
|
+
const startTime = Date.now();
|
|
1561
|
+
const dockerVersion = isDevMode() ? "latest" : VERSION;
|
|
1562
|
+
if (!options.quiet && isDevMode()) {
|
|
1563
|
+
console.log(c.dim(" Dev mode: using hyperframes@latest in Docker image"));
|
|
1564
|
+
}
|
|
1565
|
+
const platform = resolveDockerHostPlatform(options);
|
|
1566
|
+
let imageTag;
|
|
1567
|
+
try {
|
|
1568
|
+
imageTag = ensureDockerImage(dockerVersion, platform, options.quiet);
|
|
1569
|
+
} catch (error) {
|
|
1570
|
+
const message = normalizeErrorMessage(error);
|
|
1571
|
+
const isDockerMissing = /connect|not found|ENOENT/i.test(message);
|
|
1572
|
+
errorBox(
|
|
1573
|
+
isDockerMissing ? "Docker not available" : "Docker image build failed",
|
|
1574
|
+
message,
|
|
1575
|
+
isDockerMissing ? "Install Docker: https://docs.docker.com/get-docker/" : "Check Docker is running: docker info"
|
|
1576
|
+
);
|
|
1577
|
+
failCommand();
|
|
1578
|
+
}
|
|
1579
|
+
const outputDir = dirname2(outputPath);
|
|
1580
|
+
const outputFilename = basename(outputPath);
|
|
1581
|
+
const dockerArgs = buildDockerRunArgs({
|
|
1582
|
+
imageTag,
|
|
1583
|
+
projectDir: resolve3(projectDir),
|
|
1584
|
+
outputDir: resolve3(outputDir),
|
|
1585
|
+
outputFilename,
|
|
1586
|
+
platform,
|
|
1587
|
+
options: {
|
|
1588
|
+
fps: options.fps,
|
|
1589
|
+
quality: options.quality,
|
|
1590
|
+
format: options.format,
|
|
1591
|
+
gifLoop: options.gifLoop,
|
|
1592
|
+
hlsSegmentSeconds: options.hlsSegmentSeconds,
|
|
1593
|
+
workers: options.workers,
|
|
1594
|
+
gpu: options.gpu,
|
|
1595
|
+
browserGpu: options.browserGpuMode === "hardware",
|
|
1596
|
+
hdrMode: options.hdrMode,
|
|
1597
|
+
crf: options.crf,
|
|
1598
|
+
vp9CpuUsed: options.vp9CpuUsed,
|
|
1599
|
+
videoBitrate: options.videoBitrate,
|
|
1600
|
+
videoFrameFormat: options.videoFrameFormat,
|
|
1601
|
+
quiet: options.quiet,
|
|
1602
|
+
variables: options.variables,
|
|
1603
|
+
entryFile: options.entryFile,
|
|
1604
|
+
outputResolution: options.outputResolutionRaw ?? options.outputResolution,
|
|
1605
|
+
pageSideCompositing: options.pageSideCompositing,
|
|
1606
|
+
debug: options.debug,
|
|
1607
|
+
bestEffort: options.bestEffort,
|
|
1608
|
+
experimentalFastCapture: options.experimentalFastCapture,
|
|
1609
|
+
pageNavigationTimeoutMs: options.pageNavigationTimeoutMs,
|
|
1610
|
+
protocolTimeoutMs: options.protocolTimeout,
|
|
1611
|
+
playerReadyTimeoutMs: options.playerReadyTimeout
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1614
|
+
if (!options.quiet) {
|
|
1615
|
+
console.log(c.dim(" Running render in Docker container..."));
|
|
1616
|
+
console.log("");
|
|
1617
|
+
}
|
|
1618
|
+
try {
|
|
1619
|
+
await new Promise((resolvePromise, reject) => {
|
|
1620
|
+
const stderrTail = createStderrTail();
|
|
1621
|
+
const child = spawn("docker", dockerArgs, {
|
|
1622
|
+
stdio: options.quiet ? ["pipe", "pipe", "pipe"] : ["inherit", "inherit", "pipe"]
|
|
1623
|
+
});
|
|
1624
|
+
child.stderr?.on("data", (chunk) => {
|
|
1625
|
+
process.stderr.write(chunk);
|
|
1626
|
+
stderrTail.push(chunk.toString());
|
|
1627
|
+
});
|
|
1628
|
+
child.on("close", (code) => {
|
|
1629
|
+
if (code === 0) resolvePromise();
|
|
1630
|
+
else reject(new DockerRenderExitError(code, stderrTail.tail()));
|
|
1631
|
+
});
|
|
1632
|
+
child.on("error", (err) => reject(err));
|
|
1633
|
+
});
|
|
1634
|
+
} catch (error) {
|
|
1635
|
+
handleRenderError(error, options, startTime, true, "Check Docker is running: docker info");
|
|
1636
|
+
}
|
|
1637
|
+
const elapsed = Date.now() - startTime;
|
|
1638
|
+
markRenderSucceeded();
|
|
1639
|
+
runPostRenderStep(
|
|
1640
|
+
"trackRenderComplete",
|
|
1641
|
+
() => trackRenderComplete({
|
|
1642
|
+
durationMs: elapsed,
|
|
1643
|
+
fps: fpsToNumber(options.fps),
|
|
1644
|
+
quality: options.quality,
|
|
1645
|
+
workers: options.workers,
|
|
1646
|
+
docker: true,
|
|
1647
|
+
gpu: options.gpu,
|
|
1648
|
+
authoringSkill: options.authoringSkill,
|
|
1649
|
+
authoringSkillSource: options.authoringSkillSource,
|
|
1650
|
+
authoringSkillInvalid: options.authoringSkillInvalid,
|
|
1651
|
+
hfEnvOverrides: options.hfEnvOverrides,
|
|
1652
|
+
catalogUsage: options.catalogUsage,
|
|
1653
|
+
...renderOutputShapeTelemetryPayload(options),
|
|
1654
|
+
...renderEnvironmentTelemetryPayload(options),
|
|
1655
|
+
...getMemorySnapshot()
|
|
1656
|
+
})
|
|
1657
|
+
);
|
|
1658
|
+
runPostRenderStep(
|
|
1659
|
+
"printRenderComplete",
|
|
1660
|
+
() => printRenderComplete({
|
|
1661
|
+
outputPath,
|
|
1662
|
+
projectDir,
|
|
1663
|
+
desktopHint: wantsDesktopHint(options),
|
|
1664
|
+
elapsedMs: elapsed,
|
|
1665
|
+
quiet: options.quiet,
|
|
1666
|
+
format: options.format
|
|
1667
|
+
})
|
|
1668
|
+
);
|
|
1669
|
+
runPostRenderStep(
|
|
1670
|
+
"warnIfWebmAlphaDropped",
|
|
1671
|
+
() => warnIfWebmAlphaDropped(outputPath, options.format, options.quiet)
|
|
1672
|
+
);
|
|
1673
|
+
if (options.exitAfterComplete) scheduleRenderProcessExit();
|
|
1674
|
+
return { renderTimeMs: elapsed };
|
|
1675
|
+
}
|
|
1676
|
+
async function renderLocal(projectDir, outputPath, options, commandCancellation) {
|
|
1677
|
+
const cancellation = commandCancellation ?? createRenderCancellationScope();
|
|
1678
|
+
try {
|
|
1679
|
+
return await executeLocalRender(projectDir, outputPath, options, cancellation);
|
|
1680
|
+
} finally {
|
|
1681
|
+
if (!commandCancellation) cancellation.dispose();
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
async function executeLocalRender(projectDir, outputPath, options, cancellation) {
|
|
1685
|
+
cancellation.checkAncestors();
|
|
1686
|
+
cancellation.signal.throwIfAborted();
|
|
1687
|
+
let recoveredOrphanTrees = 0;
|
|
1688
|
+
try {
|
|
1689
|
+
recoveredOrphanTrees = await killOrphanedProcessesForRender(cancellation.signal);
|
|
1690
|
+
} catch {
|
|
1691
|
+
if (cancellation.signal.aborted) cancellation.signal.throwIfAborted();
|
|
1692
|
+
}
|
|
1693
|
+
cancellation.checkAncestors();
|
|
1694
|
+
cancellation.signal.throwIfAborted();
|
|
1695
|
+
if (recoveredOrphanTrees > 0 && !options.quiet) {
|
|
1696
|
+
console.warn(
|
|
1697
|
+
c.warn(
|
|
1698
|
+
` Recovered ${recoveredOrphanTrees} orphaned browser process ${recoveredOrphanTrees === 1 ? "tree" : "trees"} from an interrupted render.`
|
|
1699
|
+
)
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
const preflight = await runEnvironmentChecks({
|
|
1703
|
+
projectDir,
|
|
1704
|
+
diskPaths: [tmpdir(), dirname2(outputPath)],
|
|
1705
|
+
browserPath: options.browserPath,
|
|
1706
|
+
includeBrowser: true,
|
|
1707
|
+
includeDisk: true,
|
|
1708
|
+
includeWindowsUnc: true,
|
|
1709
|
+
signal: cancellation.signal
|
|
1710
|
+
});
|
|
1711
|
+
options = {
|
|
1712
|
+
...options,
|
|
1713
|
+
ffmpegVersionMajor: preflight.ffmpegVersionMajor,
|
|
1714
|
+
browserVersionMajor: preflight.browserVersionMajor,
|
|
1715
|
+
browserInstall: preflight.browserInstall
|
|
1716
|
+
};
|
|
1717
|
+
cancellation.checkAncestors();
|
|
1718
|
+
cancellation.signal.throwIfAborted();
|
|
1719
|
+
const failedChecks = preflight.outcomes.filter((outcome2) => !outcome2.ok);
|
|
1720
|
+
if (failedChecks.length > 0) {
|
|
1721
|
+
for (const check of failedChecks) {
|
|
1722
|
+
errorBox(check.title ?? `${check.name} check failed`, check.detail, check.hint);
|
|
1723
|
+
}
|
|
1724
|
+
failCommand();
|
|
1725
|
+
}
|
|
1726
|
+
if (!options.quiet) {
|
|
1727
|
+
for (const outcome2 of preflight.outcomes) {
|
|
1728
|
+
if (outcome2.level === "warn") {
|
|
1729
|
+
console.warn(c.warn(` ${outcome2.name}: ${outcome2.detail}`));
|
|
1730
|
+
if (outcome2.hint) console.warn(c.dim(` ${outcome2.hint}`));
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
if (preflight.ffmpegPath) process.env.HYPERFRAMES_FFMPEG_PATH = preflight.ffmpegPath;
|
|
1735
|
+
if (preflight.ffprobePath) process.env.HYPERFRAMES_FFPROBE_PATH = preflight.ffprobePath;
|
|
1736
|
+
if (preflight.browser?.executablePath && !process.env.PRODUCER_HEADLESS_SHELL_PATH) {
|
|
1737
|
+
process.env.PRODUCER_HEADLESS_SHELL_PATH = preflight.browser.executablePath;
|
|
1738
|
+
}
|
|
1739
|
+
const isHls = options.format === "hls";
|
|
1740
|
+
if (!options.gpu && (options.format === "mp4" || isHls) && preflight.ffmpegPath) {
|
|
1741
|
+
let encoderMode = "software";
|
|
1742
|
+
try {
|
|
1743
|
+
encoderMode = await detectH264EncoderModeForRender(
|
|
1744
|
+
preflight.ffmpegPath,
|
|
1745
|
+
false,
|
|
1746
|
+
cancellation.signal
|
|
1747
|
+
);
|
|
1748
|
+
} catch (error) {
|
|
1749
|
+
if (cancellation.signal.aborted) cancellation.signal.throwIfAborted();
|
|
1750
|
+
if (error instanceof H264EncoderUnavailableError && (options.hdrMode === "force-sdr" || isHls)) {
|
|
1751
|
+
errorBox(
|
|
1752
|
+
`${isHls ? "HLS" : "MP4"} H.264 encoder unavailable`,
|
|
1753
|
+
error.message,
|
|
1754
|
+
`Install an FFmpeg build with libx264 support (${getFFmpegInstallHint()})` + (isHls ? "." : ", or render WebM instead: hyperframes render --format webm --output output.webm")
|
|
1755
|
+
);
|
|
1756
|
+
failCommand();
|
|
1757
|
+
}
|
|
1758
|
+
if (!options.quiet) {
|
|
1759
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1760
|
+
console.warn(c.warn(` Unable to probe H.264 encoder capabilities: ${detail}`));
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
if (encoderMode === "gpu" && isHls) {
|
|
1764
|
+
errorBox(
|
|
1765
|
+
"HLS H.264 encoder unavailable",
|
|
1766
|
+
"FFmpeg does not include libx264, and HLS cannot fall back to VideoToolbox: fixed-length segments require the software encoder's forced-keyframe lock.",
|
|
1767
|
+
`Install an FFmpeg build with libx264 support (${getFFmpegInstallHint()}).`
|
|
1768
|
+
);
|
|
1769
|
+
failCommand();
|
|
1770
|
+
}
|
|
1771
|
+
if (encoderMode === "gpu") {
|
|
1772
|
+
console.warn(
|
|
1773
|
+
c.warn(" FFmpeg does not include libx264; falling back to VideoToolbox H.264 encoding.")
|
|
1774
|
+
);
|
|
1775
|
+
options = { ...options, gpu: true };
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
cancellation.checkAncestors();
|
|
1779
|
+
cancellation.signal.throwIfAborted();
|
|
1780
|
+
const producer = await loadProducer();
|
|
1781
|
+
const deParallelRouterActive = options.manageDeParallelRouterBreaker === true ? applyDeParallelRouterCircuitBreaker(options.quiet) : (
|
|
1782
|
+
// Not managing the breaker: the router still runs (producer default),
|
|
1783
|
+
// we just don't enforce or record the per-install trip.
|
|
1784
|
+
false
|
|
1785
|
+
);
|
|
1786
|
+
const startTime = Date.now();
|
|
1787
|
+
const logger = createRenderTelemetryLogger(
|
|
1788
|
+
producer.createConsoleLogger?.(options.debug ? "debug" : options.quiet ? "warn" : "info") ?? createNoopProducerLogger()
|
|
1789
|
+
);
|
|
1790
|
+
const engineConfig = producer.resolveConfig({
|
|
1791
|
+
browserGpuMode: options.browserGpuMode ?? "software",
|
|
1792
|
+
// Local auto opts out of the software-GPU screenshot clamp. Docker and
|
|
1793
|
+
// --no-browser-gpu request software; --resolution supersamples via screenshot.
|
|
1794
|
+
...options.browserGpuMode === "auto" && options.outputResolution == null && process.env.PRODUCER_FORCE_SCREENSHOT !== "true" ? { forceScreenshot: false } : {},
|
|
1795
|
+
...options.pageNavigationTimeoutMs != null ? { pageNavigationTimeout: options.pageNavigationTimeoutMs } : {},
|
|
1796
|
+
...options.protocolTimeout != null && { protocolTimeout: options.protocolTimeout },
|
|
1797
|
+
...options.playerReadyTimeout != null && { playerReadyTimeout: options.playerReadyTimeout },
|
|
1798
|
+
...options.vp9CpuUsed != null ? { vp9CpuUsed: options.vp9CpuUsed } : {}
|
|
1799
|
+
});
|
|
1800
|
+
const request = producer.createRenderRequest({
|
|
1801
|
+
projectDir,
|
|
1802
|
+
outputPath,
|
|
1803
|
+
engineConfig,
|
|
1804
|
+
options: {
|
|
1805
|
+
fps: options.fps,
|
|
1806
|
+
quality: options.quality,
|
|
1807
|
+
format: options.format,
|
|
1808
|
+
gifLoop: options.gifLoop,
|
|
1809
|
+
hlsSegmentSeconds: options.hlsSegmentSeconds,
|
|
1810
|
+
workers: options.workers,
|
|
1811
|
+
useGpu: options.gpu,
|
|
1812
|
+
hdrMode: options.hdrMode,
|
|
1813
|
+
crf: options.crf,
|
|
1814
|
+
videoBitrate: options.videoBitrate,
|
|
1815
|
+
videoFrameFormat: options.videoFrameFormat,
|
|
1816
|
+
variables: options.variables,
|
|
1817
|
+
entryFile: options.entryFile,
|
|
1818
|
+
outputResolution: options.outputResolution,
|
|
1819
|
+
outputResolutionAspectAgnostic: options.outputResolutionAspectAgnostic,
|
|
1820
|
+
debug: options.debug,
|
|
1821
|
+
resumeSegments: options.resumeSegments,
|
|
1822
|
+
keepSegments: options.keepSegments,
|
|
1823
|
+
strictness: options.bestEffort === false ? "strict" : "best-effort"
|
|
1824
|
+
}
|
|
1825
|
+
});
|
|
1826
|
+
const job = producer.createRenderJob(producer.renderConfigFromRequest(request, { logger }));
|
|
1827
|
+
const onProgress = options.quiet ? void 0 : (progressJob, message) => {
|
|
1828
|
+
renderProgress(progressJob.progress, message);
|
|
1829
|
+
};
|
|
1830
|
+
try {
|
|
1831
|
+
cancellation.checkAncestors();
|
|
1832
|
+
await producer.executeRenderJob(
|
|
1833
|
+
job,
|
|
1834
|
+
projectDir,
|
|
1835
|
+
outputPath,
|
|
1836
|
+
onProgress,
|
|
1837
|
+
cancellation.signal,
|
|
1838
|
+
cancellation.checkAncestors
|
|
1839
|
+
);
|
|
1840
|
+
} catch (error) {
|
|
1841
|
+
maybeConsumeDeParallelRouterTrial(deParallelRouterActive, job, options.quiet);
|
|
1842
|
+
const inContainer = process.env.CONTAINER === "true";
|
|
1843
|
+
handleRenderError(
|
|
1844
|
+
error,
|
|
1845
|
+
options,
|
|
1846
|
+
startTime,
|
|
1847
|
+
false,
|
|
1848
|
+
inContainer ? "" : "Try --docker for containerized rendering",
|
|
1849
|
+
job.failedStage,
|
|
1850
|
+
job
|
|
1851
|
+
);
|
|
1852
|
+
}
|
|
1853
|
+
markRenderSucceeded();
|
|
1854
|
+
maybeConsumeDeParallelRouterTrial(deParallelRouterActive, job, options.quiet);
|
|
1855
|
+
const elapsed = Date.now() - startTime;
|
|
1856
|
+
if (job.outcome === "completed_with_warnings") {
|
|
1857
|
+
for (const warning of job.warnings) {
|
|
1858
|
+
console.warn(c.warn(` [${warning.code}] ${warning.message}`));
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
runPostRenderStep("trackRenderMetrics", () => trackRenderMetrics(job, elapsed, options, false));
|
|
1862
|
+
runPostRenderStep(
|
|
1863
|
+
"printRenderComplete",
|
|
1864
|
+
() => printRenderComplete({
|
|
1865
|
+
outputPath,
|
|
1866
|
+
projectDir,
|
|
1867
|
+
desktopHint: wantsDesktopHint(options),
|
|
1868
|
+
elapsedMs: elapsed,
|
|
1869
|
+
quiet: options.quiet,
|
|
1870
|
+
format: options.format,
|
|
1871
|
+
perf: job.perfSummary,
|
|
1872
|
+
requestedGpuMode: options.browserGpuMode
|
|
1873
|
+
})
|
|
1874
|
+
);
|
|
1875
|
+
runPostRenderStep(
|
|
1876
|
+
"warnIfWebmAlphaDropped",
|
|
1877
|
+
() => warnIfWebmAlphaDropped(outputPath, options.format, options.quiet)
|
|
1878
|
+
);
|
|
1879
|
+
if (!options.skipFeedback) {
|
|
1880
|
+
await runPostRenderStepAsync(
|
|
1881
|
+
"maybePromptRenderFeedback",
|
|
1882
|
+
() => maybePromptRenderFeedback({
|
|
1883
|
+
renderDurationMs: elapsed,
|
|
1884
|
+
quiet: options.quiet
|
|
1885
|
+
})
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
if (options.exitAfterComplete) scheduleRenderProcessExit();
|
|
1889
|
+
const durationMs = job.perfSummary ? Math.round(job.perfSummary.compositionDurationSeconds * 1e3) : void 0;
|
|
1890
|
+
const outcome = job.outcome === "completed_with_warnings" ? "completed_with_warnings" : "completed";
|
|
1891
|
+
return {
|
|
1892
|
+
renderTimeMs: elapsed,
|
|
1893
|
+
durationMs,
|
|
1894
|
+
outcome,
|
|
1895
|
+
warnings: job.warnings.map((warning) => ({ code: warning.code, message: warning.message }))
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
function isUnrefableTimer(timer) {
|
|
1899
|
+
return typeof timer === "object" && timer !== null && "unref" in timer && typeof timer.unref === "function";
|
|
1900
|
+
}
|
|
1901
|
+
function scheduleRenderProcessExit() {
|
|
1902
|
+
const timer = setTimeout(() => requestCliExit(0), 100);
|
|
1903
|
+
if (isUnrefableTimer(timer)) timer.unref();
|
|
1904
|
+
}
|
|
1905
|
+
function getMemorySnapshot() {
|
|
1906
|
+
return {
|
|
1907
|
+
peakMemoryMb: bytesToMb(process.memoryUsage.rss()),
|
|
1908
|
+
memoryFreeMb: bytesToMb(freemem())
|
|
1909
|
+
};
|
|
1910
|
+
}
|
|
1911
|
+
function renderOutputShapeTelemetryPayload(options) {
|
|
1912
|
+
return {
|
|
1913
|
+
outputResolutionPreset: options.outputResolution,
|
|
1914
|
+
outputFormat: options.format,
|
|
1915
|
+
hdrMode: options.hdrMode,
|
|
1916
|
+
videoFrameFormat: options.videoFrameFormat,
|
|
1917
|
+
gifFpsCapped: options.gifFpsCapped
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
function renderEnvironmentTelemetryPayload(options) {
|
|
1921
|
+
return {
|
|
1922
|
+
ffmpegVersionMajor: options.ffmpegVersionMajor,
|
|
1923
|
+
browserVersionMajor: options.browserVersionMajor,
|
|
1924
|
+
browserInstall: options.browserInstall
|
|
1925
|
+
};
|
|
1926
|
+
}
|
|
1927
|
+
function metaString(meta, key) {
|
|
1928
|
+
const value = meta?.[key];
|
|
1929
|
+
return typeof value === "string" ? value : void 0;
|
|
1930
|
+
}
|
|
1931
|
+
function metaNumber(meta, key) {
|
|
1932
|
+
const value = meta?.[key];
|
|
1933
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1934
|
+
}
|
|
1935
|
+
function metaBoolean(meta, key) {
|
|
1936
|
+
const value = meta?.[key];
|
|
1937
|
+
return typeof value === "boolean" ? value : void 0;
|
|
1938
|
+
}
|
|
1939
|
+
function trackRenderTraceFromLog(message, meta) {
|
|
1940
|
+
if (message !== "[Render:trace]") return;
|
|
1941
|
+
const status = metaString(meta, "status");
|
|
1942
|
+
if (status !== "start" && status !== "end" && status !== "checkpoint" && status !== "error") {
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
trackRenderObservation({
|
|
1946
|
+
source: "cli",
|
|
1947
|
+
renderJobId: metaString(meta, "renderJobId"),
|
|
1948
|
+
phase: metaString(meta, "phase"),
|
|
1949
|
+
status,
|
|
1950
|
+
compositionHash: metaString(meta, "compositionHash"),
|
|
1951
|
+
elapsedMs: metaNumber(meta, "elapsedMs"),
|
|
1952
|
+
durationMs: metaNumber(meta, "durationMs"),
|
|
1953
|
+
message: metaString(meta, "message"),
|
|
1954
|
+
workerCount: metaNumber(meta, "workerCount"),
|
|
1955
|
+
forceScreenshot: metaBoolean(meta, "forceScreenshot"),
|
|
1956
|
+
useStreamingEncode: metaBoolean(meta, "useStreamingEncode"),
|
|
1957
|
+
useLayeredComposite: metaBoolean(meta, "useLayeredComposite"),
|
|
1958
|
+
usePageSideCompositing: metaBoolean(meta, "usePageSideCompositing"),
|
|
1959
|
+
hasHdrContent: metaBoolean(meta, "hasHdrContent"),
|
|
1960
|
+
captureMode: metaString(meta, "captureMode"),
|
|
1961
|
+
captureOperation: metaString(meta, "captureOperation"),
|
|
1962
|
+
framesCompleted: metaNumber(meta, "framesCompleted"),
|
|
1963
|
+
totalFrames: metaNumber(meta, "totalFrames"),
|
|
1964
|
+
heartbeatIndex: metaNumber(meta, "heartbeatIndex"),
|
|
1965
|
+
stageElapsedMs: metaNumber(meta, "stageElapsedMs"),
|
|
1966
|
+
videoCount: metaNumber(meta, "videoCount"),
|
|
1967
|
+
extractedVideoCount: metaNumber(meta, "extractedVideoCount"),
|
|
1968
|
+
totalFramesExtracted: metaNumber(meta, "totalFramesExtracted"),
|
|
1969
|
+
maxFramesPerVideo: metaNumber(meta, "maxFramesPerVideo"),
|
|
1970
|
+
avgFramesPerExtractedVideo: metaNumber(meta, "avgFramesPerExtractedVideo"),
|
|
1971
|
+
vfrPreflightCount: metaNumber(meta, "vfrPreflightCount"),
|
|
1972
|
+
vfrPreflightMs: metaNumber(meta, "vfrPreflightMs"),
|
|
1973
|
+
cacheHits: metaNumber(meta, "cacheHits"),
|
|
1974
|
+
cacheMisses: metaNumber(meta, "cacheMisses")
|
|
1975
|
+
});
|
|
1976
|
+
}
|
|
1977
|
+
function createRenderTelemetryLogger(base) {
|
|
1978
|
+
return {
|
|
1979
|
+
error(message, meta) {
|
|
1980
|
+
base.error(message, meta);
|
|
1981
|
+
trackRenderTraceFromLog(message, meta);
|
|
1982
|
+
},
|
|
1983
|
+
warn(message, meta) {
|
|
1984
|
+
base.warn(message, meta);
|
|
1985
|
+
trackRenderTraceFromLog(message, meta);
|
|
1986
|
+
},
|
|
1987
|
+
info(message, meta) {
|
|
1988
|
+
base.info(message, meta);
|
|
1989
|
+
trackRenderTraceFromLog(message, meta);
|
|
1990
|
+
},
|
|
1991
|
+
debug(message, meta) {
|
|
1992
|
+
base.debug(message, meta);
|
|
1993
|
+
trackRenderTraceFromLog(message, meta);
|
|
1994
|
+
},
|
|
1995
|
+
isLevelEnabled(level) {
|
|
1996
|
+
return base.isLevelEnabled?.(level) ?? true;
|
|
1997
|
+
}
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
2000
|
+
function createNoopProducerLogger() {
|
|
2001
|
+
return {
|
|
2002
|
+
error() {
|
|
2003
|
+
},
|
|
2004
|
+
warn() {
|
|
2005
|
+
},
|
|
2006
|
+
info() {
|
|
2007
|
+
},
|
|
2008
|
+
debug() {
|
|
2009
|
+
},
|
|
2010
|
+
isLevelEnabled() {
|
|
2011
|
+
return true;
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
var deParallelRouterUserManaged = false;
|
|
2016
|
+
var deParallelRouterUserManagedResolved = false;
|
|
2017
|
+
var deParallelRouterBreakerTrippedThisProcess = false;
|
|
2018
|
+
function __resetDeParallelRouterTrialStateForTests() {
|
|
2019
|
+
deParallelRouterBreakerTrippedThisProcess = false;
|
|
2020
|
+
deParallelRouterUserManaged = false;
|
|
2021
|
+
deParallelRouterUserManagedResolved = false;
|
|
2022
|
+
}
|
|
2023
|
+
function hasDeParallelRouterBreakerTripped(config) {
|
|
2024
|
+
return deParallelRouterBreakerTrippedThisProcess || Boolean(config.deParallelRouterTrialFired);
|
|
2025
|
+
}
|
|
2026
|
+
function userValueEnablesDeParallelRouter() {
|
|
2027
|
+
const raw = process.env.HF_DE_PARALLEL_ROUTER?.trim().toLowerCase();
|
|
2028
|
+
if (raw === void 0 || raw === "") return true;
|
|
2029
|
+
return !(raw === "false" || raw === "0" || raw === "off" || raw === "no");
|
|
2030
|
+
}
|
|
2031
|
+
function applyDeParallelRouterBreaker() {
|
|
2032
|
+
if (deParallelRouterUserManaged) return;
|
|
2033
|
+
process.env.HF_DE_PARALLEL_ROUTER = "false";
|
|
2034
|
+
}
|
|
2035
|
+
function applyDeParallelRouterCircuitBreaker(quiet) {
|
|
2036
|
+
if (!deParallelRouterUserManagedResolved) {
|
|
2037
|
+
deParallelRouterUserManaged = (process.env.HF_DE_PARALLEL_ROUTER ?? "").trim() !== "";
|
|
2038
|
+
deParallelRouterUserManagedResolved = true;
|
|
2039
|
+
}
|
|
2040
|
+
if (deParallelRouterUserManaged) {
|
|
2041
|
+
return userValueEnablesDeParallelRouter();
|
|
2042
|
+
}
|
|
2043
|
+
if (deParallelRouterBreakerTrippedThisProcess) {
|
|
2044
|
+
applyDeParallelRouterBreaker();
|
|
2045
|
+
return false;
|
|
2046
|
+
}
|
|
2047
|
+
if (hasDeParallelRouterBreakerTripped(readConfigFresh())) {
|
|
2048
|
+
deParallelRouterBreakerTrippedThisProcess = true;
|
|
2049
|
+
applyDeParallelRouterBreaker();
|
|
2050
|
+
if (!quiet) {
|
|
2051
|
+
console.log(
|
|
2052
|
+
c.dim(
|
|
2053
|
+
" Parallel drawElement capture stays off for this install (a previous render had to fall back). Re-enable with HF_DE_PARALLEL_ROUTER=true."
|
|
2054
|
+
)
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
return false;
|
|
2058
|
+
}
|
|
2059
|
+
return true;
|
|
2060
|
+
}
|
|
2061
|
+
function resolveDeParallelRouterOutcome(job) {
|
|
2062
|
+
const outcome = job.perfSummary?.drawElement?.parallelRouter ?? job.errorDetails?.observability?.capture.deParallelRouter;
|
|
2063
|
+
return outcome === "none" ? void 0 : outcome;
|
|
2064
|
+
}
|
|
2065
|
+
function persistDeParallelRouterTrialFired() {
|
|
2066
|
+
const MAX_ATTEMPTS = 3;
|
|
2067
|
+
let mirrored = false;
|
|
2068
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
2069
|
+
const config = readConfigFresh();
|
|
2070
|
+
if (config.deParallelRouterTrialFired && mirrored) return true;
|
|
2071
|
+
config.deParallelRouterTrialFired = true;
|
|
2072
|
+
const result = writeConfigWithResult(config);
|
|
2073
|
+
if (!result.ok) return false;
|
|
2074
|
+
mirrored = result.mirrored !== false;
|
|
2075
|
+
if (mirrored) return true;
|
|
2076
|
+
}
|
|
2077
|
+
return false;
|
|
2078
|
+
}
|
|
2079
|
+
function maybeConsumeDeParallelRouterTrial(routerActive, job, quiet) {
|
|
2080
|
+
if (!routerActive) return;
|
|
2081
|
+
const outcome = resolveDeParallelRouterOutcome(job);
|
|
2082
|
+
if (outcome === void 0) return;
|
|
2083
|
+
const config = readConfigFresh();
|
|
2084
|
+
const renderCount = (config.deParallelRouterTrialRenderCount ?? 0) + 1;
|
|
2085
|
+
config.deParallelRouterTrialRenderCount = renderCount;
|
|
2086
|
+
const fired = outcome !== "routed";
|
|
2087
|
+
if (fired) {
|
|
2088
|
+
config.deParallelRouterTrialFired = true;
|
|
2089
|
+
deParallelRouterBreakerTrippedThisProcess = true;
|
|
2090
|
+
applyDeParallelRouterBreaker();
|
|
2091
|
+
}
|
|
2092
|
+
writeConfig(config);
|
|
2093
|
+
if (fired && !deParallelRouterUserManaged) reportDeParallelRouterBreakerTrip(quiet);
|
|
2094
|
+
}
|
|
2095
|
+
function reportDeParallelRouterBreakerTrip(quiet) {
|
|
2096
|
+
const persisted = persistDeParallelRouterTrialFired();
|
|
2097
|
+
if (quiet) return;
|
|
2098
|
+
console.log(
|
|
2099
|
+
c.dim(
|
|
2100
|
+
" A frame failed verification, so parallel drawElement capture fell back to the screenshot path and is now off for this install. Re-enable: HF_DE_PARALLEL_ROUTER=true"
|
|
2101
|
+
)
|
|
2102
|
+
);
|
|
2103
|
+
if (persisted) return;
|
|
2104
|
+
console.warn(
|
|
2105
|
+
c.warn(
|
|
2106
|
+
" Could not persist the parallel drawElement circuit breaker to ~/.hyperframes/config.json (unwritable?). It stays off for this process; future runs may retry it. Set HF_DE_PARALLEL_ROUTER=false to opt out for good."
|
|
2107
|
+
)
|
|
2108
|
+
);
|
|
2109
|
+
}
|
|
2110
|
+
var KNOWN_STAGE_CODES = {
|
|
2111
|
+
Queued: "queued",
|
|
2112
|
+
"Compiling composition": "compiling_composition",
|
|
2113
|
+
"Extracting video frames": "extracting_video_frames",
|
|
2114
|
+
"Processing audio tracks": "processing_audio_tracks",
|
|
2115
|
+
"Starting frame capture": "starting_frame_capture",
|
|
2116
|
+
"Render complete": "render_complete",
|
|
2117
|
+
"Render cancelled": "render_cancelled",
|
|
2118
|
+
pipeline: "pipeline"
|
|
2119
|
+
};
|
|
2120
|
+
function normalizeStageCode(stage) {
|
|
2121
|
+
const known = KNOWN_STAGE_CODES[stage];
|
|
2122
|
+
if (known) return known;
|
|
2123
|
+
if (stage.startsWith("Starting browsers")) return "starting_browsers";
|
|
2124
|
+
const slug = stage.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
2125
|
+
return slug || "unknown";
|
|
2126
|
+
}
|
|
2127
|
+
function handleRenderError(error, options, startTime, docker, hint, failedStage, job) {
|
|
2128
|
+
const message = normalizeErrorMessage(error);
|
|
2129
|
+
trackRenderError({
|
|
2130
|
+
fps: fpsToNumber(options.fps),
|
|
2131
|
+
quality: options.quality,
|
|
2132
|
+
docker,
|
|
2133
|
+
workers: options.workers,
|
|
2134
|
+
gpu: options.gpu,
|
|
2135
|
+
authoringSkill: options.authoringSkill,
|
|
2136
|
+
authoringSkillSource: options.authoringSkillSource,
|
|
2137
|
+
authoringSkillInvalid: options.authoringSkillInvalid,
|
|
2138
|
+
hfEnvOverrides: options.hfEnvOverrides,
|
|
2139
|
+
elapsedMs: Date.now() - startTime,
|
|
2140
|
+
errorMessage: message,
|
|
2141
|
+
failedStage,
|
|
2142
|
+
...renderOutputShapeTelemetryPayload(options),
|
|
2143
|
+
...renderEnvironmentTelemetryPayload(options),
|
|
2144
|
+
// A bucketable failure taxonomy alongside the free-text error_message
|
|
2145
|
+
// above: error.name is one of ~20 typed producer error classes
|
|
2146
|
+
// (CaptureFailure, DrawElementCaptureError, SwiftShaderAssertionError, …);
|
|
2147
|
+
// failed_stage_code is the same job.currentStage value normalized to a
|
|
2148
|
+
// stable code. Error-conditional by nature — there is no equivalent on
|
|
2149
|
+
// the render_complete success path, since nothing failed to name.
|
|
2150
|
+
errorName: error instanceof Error ? error.name : "unknown",
|
|
2151
|
+
failedStageCode: normalizeStageCode(failedStage || "pipeline"),
|
|
2152
|
+
...renderJobObservabilityTelemetryPayload(job),
|
|
2153
|
+
...getMemorySnapshot()
|
|
2154
|
+
});
|
|
2155
|
+
if (job?.id) recordRecentRender(job.id, false);
|
|
2156
|
+
if (options.throwOnError) {
|
|
2157
|
+
throw new Error(message);
|
|
2158
|
+
}
|
|
2159
|
+
const remediation = chromeLaunchRemediation(message);
|
|
2160
|
+
if (remediation) {
|
|
2161
|
+
errorBox("Render failed \u2014 Chrome could not launch", message, remediation);
|
|
2162
|
+
failCommand();
|
|
2163
|
+
}
|
|
2164
|
+
const macosRemediation = macosOldChromeCrashRemediation(message);
|
|
2165
|
+
if (macosRemediation) {
|
|
2166
|
+
errorBox("Render failed \u2014 Chrome could not launch", message, macosRemediation);
|
|
2167
|
+
failCommand();
|
|
2168
|
+
}
|
|
2169
|
+
const windowsRemediation = windowsChromeCrashRemediation(message);
|
|
2170
|
+
if (windowsRemediation) {
|
|
2171
|
+
errorBox(
|
|
2172
|
+
"Render failed \u2014 chrome-headless-shell crashed at launch",
|
|
2173
|
+
message,
|
|
2174
|
+
windowsRemediation
|
|
2175
|
+
);
|
|
2176
|
+
failCommand();
|
|
2177
|
+
}
|
|
2178
|
+
errorBox("Render failed", message, hint);
|
|
2179
|
+
failCommand();
|
|
2180
|
+
}
|
|
2181
|
+
function trackRenderMetrics(job, elapsedMs, options, docker) {
|
|
2182
|
+
recordRecentRender(job.id, true);
|
|
2183
|
+
const perf = job.perfSummary;
|
|
2184
|
+
const compositionDurationMs = perf ? Math.round(perf.compositionDurationSeconds * 1e3) : void 0;
|
|
2185
|
+
const speedRatio = compositionDurationMs && compositionDurationMs > 0 && elapsedMs > 0 ? Math.round(compositionDurationMs / elapsedMs * 100) / 100 : void 0;
|
|
2186
|
+
const stages = perf?.stages ?? {};
|
|
2187
|
+
const extract = perf?.videoExtractBreakdown;
|
|
2188
|
+
trackRenderComplete({
|
|
2189
|
+
durationMs: elapsedMs,
|
|
2190
|
+
fps: fpsToNumber(options.fps),
|
|
2191
|
+
quality: options.quality,
|
|
2192
|
+
workers: options.workers ?? perf?.workers,
|
|
2193
|
+
workersBoundBy: perf?.workerSizing?.boundBy,
|
|
2194
|
+
workersCpuBased: perf?.workerSizing?.cpuBasedWorkers,
|
|
2195
|
+
workersMemoryBased: perf?.workerSizing?.memoryBasedWorkers,
|
|
2196
|
+
workersHeapBased: perf?.workerSizing?.heapBasedWorkers,
|
|
2197
|
+
workersFrameBased: perf?.workerSizing?.frameBasedWorkers,
|
|
2198
|
+
workersHeapLimitMb: perf?.workerSizing?.heapLimitMb,
|
|
2199
|
+
workersExceedHeapAdvisory: perf?.workerSizing?.exceedsHeapAdvisory,
|
|
2200
|
+
docker,
|
|
2201
|
+
gpu: options.gpu,
|
|
2202
|
+
authoringSkill: options.authoringSkill,
|
|
2203
|
+
authoringSkillSource: options.authoringSkillSource,
|
|
2204
|
+
authoringSkillInvalid: options.authoringSkillInvalid,
|
|
2205
|
+
hfEnvOverrides: options.hfEnvOverrides,
|
|
2206
|
+
catalogUsage: options.catalogUsage,
|
|
2207
|
+
...renderOutputShapeTelemetryPayload(options),
|
|
2208
|
+
...renderEnvironmentTelemetryPayload(options),
|
|
2209
|
+
chromeBrowserRssPeakMb: perf?.chromeMemory?.browserRssPeakMb,
|
|
2210
|
+
chromeRendererRssPeakMb: perf?.chromeMemory?.rendererRssPeakMb,
|
|
2211
|
+
chromeRssLastMb: perf?.chromeMemory?.rssLastMb,
|
|
2212
|
+
chromeGpuProcessSeenLastSample: perf?.chromeMemory?.gpuProcessSeenLastSample,
|
|
2213
|
+
chromeMemorySamples: perf?.chromeMemory?.samples,
|
|
2214
|
+
staticDedupEnabled: perf?.staticDedup?.enabled,
|
|
2215
|
+
staticDedupArmed: perf?.staticDedup?.armed,
|
|
2216
|
+
staticDedupSkipReason: perf?.staticDedup?.skipReason,
|
|
2217
|
+
staticDedupPredictedFrames: perf?.staticDedup?.predictedFrames,
|
|
2218
|
+
staticDedupReusedFrames: perf?.staticDedup?.reusedFrames,
|
|
2219
|
+
beginFrameNoDamageFrames: perf?.beginFrameReuse?.noDamageFrames,
|
|
2220
|
+
beginFrameHasDamageFrames: perf?.beginFrameReuse?.hasDamageFrames,
|
|
2221
|
+
deCaptureMode: perf?.drawElement?.mode,
|
|
2222
|
+
vfxHostCount: perf?.drawElement?.vfxHostCount,
|
|
2223
|
+
vfxCapture: perf?.drawElement?.vfxCapture,
|
|
2224
|
+
vfxTypes: perf?.drawElement?.vfxTypes,
|
|
2225
|
+
deCompileGate: perf?.drawElement?.compileGate,
|
|
2226
|
+
deClampReason: perf?.drawElement?.clampReason,
|
|
2227
|
+
deWorkerInversion: perf?.drawElement?.workerInversion,
|
|
2228
|
+
dePreInversionWorkers: perf?.drawElement?.preInversionWorkers,
|
|
2229
|
+
compositionElementCount: perf?.drawElement?.compositionElementCount,
|
|
2230
|
+
compositionElementCountSource: perf?.drawElement?.compositionElementCountSource,
|
|
2231
|
+
compositionElementTags: perf?.drawElement?.compositionElementTags,
|
|
2232
|
+
arollVideoCount: perf?.drawElement?.arollVideoCount,
|
|
2233
|
+
heygenVideoCount: perf?.drawElement?.heygenVideoCount,
|
|
2234
|
+
adaptersUsed: perf?.drawElement?.adaptersUsed,
|
|
2235
|
+
audioCount: perf?.drawElement?.audioCount,
|
|
2236
|
+
imageCount: perf?.drawElement?.imageCount,
|
|
2237
|
+
subCompositionCount: perf?.drawElement?.subCompositionCount,
|
|
2238
|
+
audioGroupCount: perf?.drawElement?.audioGroupCount,
|
|
2239
|
+
colorGradingCount: perf?.drawElement?.colorGradingCount,
|
|
2240
|
+
hasLut: perf?.drawElement?.hasLut,
|
|
2241
|
+
rootBodyMismatch: perf?.drawElement?.rootBodyMismatch,
|
|
2242
|
+
rootBodyDeltaPxBucket: perf?.drawElement?.rootBodyDeltaPxBucket,
|
|
2243
|
+
deShortBand: perf?.drawElement?.shortBand,
|
|
2244
|
+
deParallelRouter: perf?.drawElement?.parallelRouter,
|
|
2245
|
+
dePreRouterWorkers: perf?.drawElement?.preRouterWorkers,
|
|
2246
|
+
deGateReason: perf?.drawElement?.gateReason,
|
|
2247
|
+
gpuRenderer: perf?.drawElement?.gpuRenderer,
|
|
2248
|
+
deWorkerEncode: perf?.drawElement?.workerEncode,
|
|
2249
|
+
deVerifyArmed: perf?.drawElement?.verifyArmed,
|
|
2250
|
+
deVerifyChecked: perf?.drawElement?.verifyChecked,
|
|
2251
|
+
deVerifyMinDb: perf?.drawElement?.verifyMinDb,
|
|
2252
|
+
deVerifyInitMs: perf?.drawElement?.verifyInitMs,
|
|
2253
|
+
deSelfVerifyFallback: perf?.drawElement?.selfVerifyFallback,
|
|
2254
|
+
deFallbackReason: perf?.drawElement?.fallbackReason,
|
|
2255
|
+
deFallbackFailedDb: perf?.drawElement?.fallbackFailedDb,
|
|
2256
|
+
deFallbackFrameIndex: perf?.drawElement?.fallbackFrameIndex,
|
|
2257
|
+
deFallbackThresholdDb: perf?.drawElement?.fallbackThresholdDb,
|
|
2258
|
+
deBlankSuspects: perf?.drawElement?.blankSuspects,
|
|
2259
|
+
deBlankDeterministicAccepts: perf?.drawElement?.blankDeterministicAccepts,
|
|
2260
|
+
deBlankRecaptures: perf?.drawElement?.blankRecaptures,
|
|
2261
|
+
deBoundaryFrames: perf?.drawElement?.boundaryFrames,
|
|
2262
|
+
deNcprFallbacks: perf?.drawElement?.ncprFallbacks,
|
|
2263
|
+
deFrameTimeouts: perf?.drawElement?.frameTimeouts,
|
|
2264
|
+
compositionDurationMs,
|
|
2265
|
+
compositionWidth: perf?.resolution.width,
|
|
2266
|
+
compositionHeight: perf?.resolution.height,
|
|
2267
|
+
totalFrames: perf?.totalFrames,
|
|
2268
|
+
speedRatio,
|
|
2269
|
+
captureAvgMs: perf?.captureAvgMs,
|
|
2270
|
+
captureP50Ms: perf?.captureP50Ms,
|
|
2271
|
+
subTimelineWait: perf?.subTimelineWait,
|
|
2272
|
+
videoCount: perf?.videoCount,
|
|
2273
|
+
capturePeakMs: perf?.capturePeakMs,
|
|
2274
|
+
tmpPeakBytes: perf?.tmpPeakBytes,
|
|
2275
|
+
stageCompileMs: stages.compileMs,
|
|
2276
|
+
stageVideoExtractMs: stages.videoExtractMs,
|
|
2277
|
+
stageAudioProcessMs: stages.audioProcessMs,
|
|
2278
|
+
stageCaptureMs: stages.captureMs,
|
|
2279
|
+
stageCaptureSetupMs: stages.captureSetupMs,
|
|
2280
|
+
stageCaptureFrameMs: stages.captureFrameMs,
|
|
2281
|
+
stageEncodeMs: stages.encodeMs,
|
|
2282
|
+
stageAssembleMs: stages.assembleMs,
|
|
2283
|
+
extractResolveMs: extract?.resolveMs,
|
|
2284
|
+
extractHdrProbeMs: extract?.hdrProbeMs,
|
|
2285
|
+
extractHdrPreflightMs: extract?.hdrPreflightMs,
|
|
2286
|
+
extractHdrPreflightCount: extract?.hdrPreflightCount,
|
|
2287
|
+
extractVfrProbeMs: extract?.vfrProbeMs,
|
|
2288
|
+
extractVfrPreflightMs: extract?.vfrPreflightMs,
|
|
2289
|
+
extractVfrPreflightCount: extract?.vfrPreflightCount,
|
|
2290
|
+
extractPhase3Ms: extract?.extractMs,
|
|
2291
|
+
extractCacheHits: extract?.cacheHits,
|
|
2292
|
+
extractCacheMisses: extract?.cacheMisses,
|
|
2293
|
+
...renderJobObservabilityTelemetryPayload(job),
|
|
2294
|
+
...getMemorySnapshot()
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
function readOutputFootprint(outputPath) {
|
|
2298
|
+
try {
|
|
2299
|
+
const stat = statSync2(outputPath);
|
|
2300
|
+
if (!stat.isDirectory()) return { fileSize: formatBytes(stat.size), isDirectory: false };
|
|
2301
|
+
let total = 0;
|
|
2302
|
+
for (const entry of readdirSync(outputPath, { withFileTypes: true })) {
|
|
2303
|
+
if (!entry.isFile()) continue;
|
|
2304
|
+
try {
|
|
2305
|
+
total += statSync2(join2(outputPath, entry.name)).size;
|
|
2306
|
+
} catch {
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
return { fileSize: formatBytes(total), isDirectory: true };
|
|
2310
|
+
} catch {
|
|
2311
|
+
return { fileSize: "unknown", isDirectory: false };
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
function wantsDesktopHint(options) {
|
|
2315
|
+
return options.desktopHint !== false;
|
|
2316
|
+
}
|
|
2317
|
+
function printRenderComplete(input) {
|
|
2318
|
+
if (input.quiet) return;
|
|
2319
|
+
const { outputPath, elapsedMs, perf } = input;
|
|
2320
|
+
const { fileSize, isDirectory } = readOutputFootprint(outputPath);
|
|
2321
|
+
const detail = formatRenderSummaryDetail({
|
|
2322
|
+
elapsedMs,
|
|
2323
|
+
outputDurationSeconds: perf?.compositionDurationSeconds,
|
|
2324
|
+
isDirectory,
|
|
2325
|
+
frameCount: perf?.totalFrames,
|
|
2326
|
+
playlistDirectory: input.format === "hls"
|
|
2327
|
+
});
|
|
2328
|
+
console.log("");
|
|
2329
|
+
console.log(c.success("\u25C7") + " " + c.accent(outputPath));
|
|
2330
|
+
console.log(" " + c.bold(fileSize) + c.dim(" \xB7 " + detail));
|
|
2331
|
+
if (perf) printRenderPipeline(perf, input.requestedGpuMode);
|
|
2332
|
+
const hint = input.desktopHint ? desktopHint(input.projectDir) : null;
|
|
2333
|
+
if (hint) console.log(" " + c.dim(hint));
|
|
2334
|
+
}
|
|
2335
|
+
function printRenderPipeline(perf, requestedGpuMode) {
|
|
2336
|
+
const capture = {
|
|
2337
|
+
captureMode: resolvePrintedCaptureMode(
|
|
2338
|
+
perf.drawElement?.mode,
|
|
2339
|
+
perf.observability?.capture.captureMode
|
|
2340
|
+
),
|
|
2341
|
+
browserGpuMode: perf.observability?.capture.browserGpuMode
|
|
2342
|
+
};
|
|
2343
|
+
const pipeline = formatRenderPipelineDetail({
|
|
2344
|
+
...capture,
|
|
2345
|
+
streamingEncode: perf.observability?.capture.useStreamingEncode,
|
|
2346
|
+
stages: perf.stages
|
|
2347
|
+
});
|
|
2348
|
+
if (pipeline) console.log(" " + c.dim(pipeline));
|
|
2349
|
+
const hint = formatScreenshotFallbackHint({
|
|
2350
|
+
...capture,
|
|
2351
|
+
requestedGpuMode,
|
|
2352
|
+
platform: process.platform
|
|
2353
|
+
});
|
|
2354
|
+
if (hint) console.log(" " + c.dim(hint));
|
|
2355
|
+
}
|
|
2356
|
+
export {
|
|
2357
|
+
__resetDeParallelRouterTrialStateForTests,
|
|
2358
|
+
checkRenderResolutionPreflight,
|
|
2359
|
+
render_default as default,
|
|
2360
|
+
examples,
|
|
2361
|
+
normalizeStageCode,
|
|
2362
|
+
renderLintContinuationHint,
|
|
2363
|
+
renderLocal,
|
|
2364
|
+
resolveBrowserGpuForCli,
|
|
2365
|
+
runRenderLint,
|
|
2366
|
+
wantsDesktopHint
|
|
2367
|
+
};
|