@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
package/src/audio.mjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Volumen final a −14 LUFS (lo que reproduce Instagram), en dos pasadas de loudnorm.
|
|
2
|
+
// El mezclador del motor no normaliza: en la cata 2 la edición salió a −16,1 y el reel a −15,0.
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
function ffmpegRun(ffmpeg, args) {
|
|
6
|
+
const r = spawnSync(ffmpeg, ['-nostdin', '-hide_banner', ...args], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
7
|
+
if (r.status !== 0) throw new Error(`ffmpeg falló: ${(r.stderr || r.error?.message || '').slice(-400)}`);
|
|
8
|
+
return r.stderr; // ffmpeg informa por stderr
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function hasAudio(ffprobe, input) {
|
|
12
|
+
const r = spawnSync(ffprobe, ['-v', 'error', '-select_streams', 'a', '-show_entries', 'stream=index', '-of', 'csv=p=0', input], { encoding: 'utf8' });
|
|
13
|
+
return r.status === 0 && r.stdout.trim().length > 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Sonoridad integrada (LUFS) de un fichero. */
|
|
17
|
+
export function loudness(ffmpeg, input) {
|
|
18
|
+
const text = ffmpegRun(ffmpeg, ['-i', input, '-af', 'ebur128', '-f', 'null', '-']);
|
|
19
|
+
const m = text.slice(text.lastIndexOf('Summary:')).match(/I:\s+(-?[\d.]+) LUFS/);
|
|
20
|
+
return m ? Number(m[1]) : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Copia `input` en `output` con el audio normalizado; el vídeo no se recodifica. */
|
|
24
|
+
export function normalizeLoudness(ffmpeg, input, output, { lufs = -14, tp = -1, lra = 11 } = {}) {
|
|
25
|
+
const base = `loudnorm=I=${lufs}:TP=${tp}:LRA=${lra}`;
|
|
26
|
+
const report = ffmpegRun(ffmpeg, ['-i', input, '-af', `${base}:print_format=json`, '-f', 'null', '-']);
|
|
27
|
+
const s = JSON.parse(report.slice(report.lastIndexOf('{'), report.lastIndexOf('}') + 1));
|
|
28
|
+
const filter = `${base}:measured_I=${s.input_i}:measured_TP=${s.input_tp}:measured_LRA=${s.input_lra}:measured_thresh=${s.input_thresh}:offset=${s.target_offset}:linear=true`;
|
|
29
|
+
ffmpegRun(ffmpeg, ['-y', '-i', input, '-c:v', 'copy', '-af', filter, '-ar', '48000', '-c:a', 'aac', '-b:a', '192k', '-movflags', '+faststart', output]);
|
|
30
|
+
return { before: Number(s.input_i), after: lufs };
|
|
31
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1",
|
|
3
|
+
"baseUrl": "https://media.ignix.social/editor/bin",
|
|
4
|
+
"platforms": {
|
|
5
|
+
"darwin-x64": {
|
|
6
|
+
"ffmpeg": {
|
|
7
|
+
"file": "ffmpeg",
|
|
8
|
+
"size": 25060568,
|
|
9
|
+
"sha256": "d4d01b1c196a4c6e3000be608f906991fe41914840a1ce0dcdf66256c3ee4c40",
|
|
10
|
+
"build": "ffmpeg 7.1.2 LGPL + VideoToolbox, scripts/build-ffmpeg-macos.sh"
|
|
11
|
+
},
|
|
12
|
+
"ffprobe": {
|
|
13
|
+
"file": "ffprobe",
|
|
14
|
+
"size": 24973512,
|
|
15
|
+
"sha256": "dd9f843f01a934c8358c9a235d8e44349fe50692418dd79ba328be7f4fecbd85",
|
|
16
|
+
"build": "ffmpeg 7.1.2 LGPL, scripts/build-ffmpeg-macos.sh"
|
|
17
|
+
},
|
|
18
|
+
"whisper": {
|
|
19
|
+
"file": "whisper-cli",
|
|
20
|
+
"size": 2912480,
|
|
21
|
+
"sha256": "73fc58436c1e1a9d2cc3ea08bddf18bf78270d8c6940c5fd89a3c9cb31535efe",
|
|
22
|
+
"build": "whisper.cpp v1.7.6, scripts/build-whisper-macos.sh"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"darwin-arm64": {
|
|
26
|
+
"ffmpeg": {
|
|
27
|
+
"file": "ffmpeg",
|
|
28
|
+
"size": 20858536,
|
|
29
|
+
"sha256": "ba5d9f9e59dd9588b88c97a526d971d07ccc60d1f101f47e2f9fac3c03ff2846",
|
|
30
|
+
"build": "ffmpeg 7.1.2 LGPL + VideoToolbox, CI binaries.yml (macos-15, run 37322341901)"
|
|
31
|
+
},
|
|
32
|
+
"ffprobe": {
|
|
33
|
+
"file": "ffprobe",
|
|
34
|
+
"size": 20799752,
|
|
35
|
+
"sha256": "5c7c6da2f0a7c14ac7aaf934afdfd6e0efa232955226a287b986fcb37e5992b9",
|
|
36
|
+
"build": "ffmpeg 7.1.2 LGPL, CI binaries.yml (macos-15, run 37322341901)"
|
|
37
|
+
},
|
|
38
|
+
"whisper": {
|
|
39
|
+
"file": "whisper-cli",
|
|
40
|
+
"size": 2573144,
|
|
41
|
+
"sha256": "215d93a2edc77f8929311f127f368727859e13833e925652315ca5ea774595ee",
|
|
42
|
+
"build": "whisper.cpp v1.7.6, CI binaries.yml (macos-15, run 37322341901)"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/binaries.mjs
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Binarios nativos que Ignix Editor necesita (ffmpeg, ffprobe, whisper-cli) por sistema.
|
|
2
|
+
// Orden de búsqueda: variable de entorno → caché (~/.ignix-editor/bin/<plataforma>) →
|
|
3
|
+
// descarga desde media.ignix.social con su sha256 comprobado. Chrome lo gestiona el motor
|
|
4
|
+
// (descarga oficial de Google la primera vez).
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
import { chmodSync, createWriteStream, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { Readable } from 'node:stream';
|
|
8
|
+
import { pipeline } from 'node:stream/promises';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
import { dirname, join } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
export const HOME = process.env.IGNIX_EDITOR_HOME || join(homedir(), '.ignix-editor');
|
|
14
|
+
export const PLATFORM = `${process.platform}-${process.arch}`; // darwin-x64, darwin-arm64, win32-x64…
|
|
15
|
+
const EXE = process.platform === 'win32' ? '.exe' : '';
|
|
16
|
+
|
|
17
|
+
const manifest = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), 'binaries.json'), 'utf8'));
|
|
18
|
+
|
|
19
|
+
export const TOOLS = {
|
|
20
|
+
ffmpeg: { env: 'IGNIX_EDITOR_FFMPEG', file: `ffmpeg${EXE}` },
|
|
21
|
+
ffprobe: { env: 'IGNIX_EDITOR_FFPROBE', file: `ffprobe${EXE}` },
|
|
22
|
+
whisper: { env: 'IGNIX_EDITOR_WHISPER', file: `whisper-cli${EXE}` },
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const binDir = () => join(HOME, 'bin', PLATFORM, manifest.version);
|
|
26
|
+
|
|
27
|
+
/** Ruta del binario si ya está disponible, sin descargar nada. */
|
|
28
|
+
export function findTool(name) {
|
|
29
|
+
const t = TOOLS[name];
|
|
30
|
+
const fromEnv = process.env[t.env];
|
|
31
|
+
if (fromEnv) return existsSync(fromEnv) ? { path: fromEnv, source: 'env' } : { path: null, source: 'env', error: `${t.env} apunta a ${fromEnv}, que no existe` };
|
|
32
|
+
const cached = join(binDir(), t.file);
|
|
33
|
+
if (existsSync(cached)) return { path: cached, source: 'cache' };
|
|
34
|
+
const entry = manifest.platforms[PLATFORM]?.[name];
|
|
35
|
+
return { path: null, source: entry ? 'download' : 'unavailable' };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Ruta del binario, descargándolo la primera vez. */
|
|
39
|
+
export async function ensureTool(name, log = () => {}) {
|
|
40
|
+
const found = findTool(name);
|
|
41
|
+
if (found.path) return found.path;
|
|
42
|
+
if (found.error) throw new Error(found.error);
|
|
43
|
+
const entry = manifest.platforms[PLATFORM]?.[name];
|
|
44
|
+
if (!entry) {
|
|
45
|
+
throw new Error(`${name} todavía no está publicado para ${PLATFORM}. Mientras tanto, apunta ${TOOLS[name].env} a un ${TOOLS[name].file} local.`);
|
|
46
|
+
}
|
|
47
|
+
const url = `${manifest.baseUrl}/${manifest.version}/${PLATFORM}/${entry.file}`;
|
|
48
|
+
log(`Descargando ${name} (${(entry.size / 1e6).toFixed(0)} MB)…`);
|
|
49
|
+
const res = await fetch(url);
|
|
50
|
+
if (!res.ok) throw new Error(`No se pudo descargar ${name}: ${res.status} ${url}`);
|
|
51
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
52
|
+
const sha = createHash('sha256').update(buf).digest('hex');
|
|
53
|
+
if (sha !== entry.sha256) throw new Error(`El ${name} descargado no coincide con su huella (sha256). No se usa.`);
|
|
54
|
+
const dir = binDir();
|
|
55
|
+
mkdirSync(dir, { recursive: true });
|
|
56
|
+
const dest = join(dir, TOOLS[name].file);
|
|
57
|
+
writeFileSync(`${dest}.part`, buf);
|
|
58
|
+
chmodSync(`${dest}.part`, 0o755);
|
|
59
|
+
renameSync(`${dest}.part`, dest);
|
|
60
|
+
return dest;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Modelos de whisper (ggml, MIT), en ~/.ignix-editor/models. */
|
|
64
|
+
export const WHISPER_MODELS = {
|
|
65
|
+
medium: { file: 'ggml-medium.bin', size: 1533763059 },
|
|
66
|
+
small: { file: 'ggml-small.bin', size: 487601967 },
|
|
67
|
+
base: { file: 'ggml-base.bin', size: 147951465 },
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export async function ensureWhisperModel(model = 'medium', log = () => {}) {
|
|
71
|
+
const m = WHISPER_MODELS[model];
|
|
72
|
+
if (!m) throw new Error(`Modelo desconocido: ${model}. Opciones: ${Object.keys(WHISPER_MODELS).join(', ')}`);
|
|
73
|
+
const dir = join(HOME, 'models');
|
|
74
|
+
const dest = join(dir, m.file);
|
|
75
|
+
if (existsSync(dest)) return dest;
|
|
76
|
+
mkdirSync(dir, { recursive: true });
|
|
77
|
+
log(`Descargando el modelo de transcripción ${model} (${(m.size / 1e9).toFixed(1)} GB, solo la primera vez)…`);
|
|
78
|
+
const res = await fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${m.file}`);
|
|
79
|
+
if (!res.ok) throw new Error(`No se pudo descargar el modelo ${model}: ${res.status}`);
|
|
80
|
+
await pipeline(Readable.fromWeb(res.body), createWriteStream(`${dest}.part`));
|
|
81
|
+
renameSync(`${dest}.part`, dest);
|
|
82
|
+
return dest;
|
|
83
|
+
}
|
package/src/cli.mjs
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
// ignix-editor — CLI de Ignix Editor. El motor (HyperFrames, en vendor/) corre siempre por
|
|
2
|
+
// debajo con nuestro entorno: sin telemetría, sin actualizaciones solas, con nuestros binarios.
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { HOME, PLATFORM, TOOLS, ensureTool, ensureWhisperModel, findTool } from './binaries.mjs';
|
|
9
|
+
import { prepare, projectHtml } from './prepare.mjs';
|
|
10
|
+
import { validateHtml } from './validate.mjs';
|
|
11
|
+
import { loudness, hasAudio, normalizeLoudness } from './audio.mjs';
|
|
12
|
+
import { alignToScript, transcribe } from './transcribe.mjs';
|
|
13
|
+
|
|
14
|
+
const PKG_DIR = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
15
|
+
const PKG = JSON.parse(readFileSync(join(PKG_DIR, 'package.json'), 'utf8'));
|
|
16
|
+
const ENGINE = join(PKG_DIR, 'vendor', 'hyperframes', 'bin', 'hyperframes.mjs');
|
|
17
|
+
const UPSTREAM = JSON.parse(readFileSync(join(PKG_DIR, 'vendor', 'hyperframes', 'UPSTREAM.json'), 'utf8'));
|
|
18
|
+
export const VIDEOS_DIR = join(homedir(), 'ignix-videos');
|
|
19
|
+
|
|
20
|
+
const log = (...a) => console.error(...a);
|
|
21
|
+
const fail = (msg) => {
|
|
22
|
+
log(`✗ ${msg}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// ── argumentos: posicionales, nuestras opciones y el resto pasa al motor tal cual
|
|
27
|
+
function parseArgs(argv, ours) {
|
|
28
|
+
const pos = [];
|
|
29
|
+
const opts = {};
|
|
30
|
+
const rest = [];
|
|
31
|
+
for (let i = 0; i < argv.length; i++) {
|
|
32
|
+
const a = argv[i];
|
|
33
|
+
const m = a.match(/^--([^=]+)(?:=(.*))?$/);
|
|
34
|
+
const key = m?.[1] ?? (a === '-o' ? 'output' : null);
|
|
35
|
+
if (key && key in ours) {
|
|
36
|
+
if (ours[key] === 'bool') opts[key] = m?.[2] !== 'false';
|
|
37
|
+
else opts[key] = m?.[2] ?? argv[++i];
|
|
38
|
+
} else if (key && key.startsWith('no-') && key.slice(3) in ours && ours[key.slice(3)] === 'bool') opts[key.slice(3)] = false;
|
|
39
|
+
else if (a.startsWith('-')) rest.push(a);
|
|
40
|
+
else if (rest.length && rest[rest.length - 1].startsWith('-') && !rest[rest.length - 1].includes('=') && pos.length >= 1) rest.push(a);
|
|
41
|
+
else pos.push(a);
|
|
42
|
+
}
|
|
43
|
+
return { pos, opts, rest };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ── el motor
|
|
47
|
+
async function engineEnv() {
|
|
48
|
+
const env = {
|
|
49
|
+
...process.env,
|
|
50
|
+
HYPERFRAMES_NO_TELEMETRY: '1',
|
|
51
|
+
DO_NOT_TRACK: '1',
|
|
52
|
+
HYPERFRAMES_NO_UPDATE_CHECK: '1',
|
|
53
|
+
HYPERFRAMES_NO_AUTO_INSTALL: '1',
|
|
54
|
+
HYPERFRAMES_SKIP_SKILLS: '1',
|
|
55
|
+
HYPERFRAMES_FONT_CACHE_DIR: join(HOME, 'cache', 'fonts'),
|
|
56
|
+
};
|
|
57
|
+
const ffmpeg = await ensureTool('ffmpeg', log);
|
|
58
|
+
const ffprobe = await ensureTool('ffprobe', log);
|
|
59
|
+
env.HYPERFRAMES_FFMPEG_PATH = ffmpeg;
|
|
60
|
+
env.HYPERFRAMES_FFPROBE_PATH = ffprobe;
|
|
61
|
+
const whisper = findTool('whisper');
|
|
62
|
+
if (whisper.path) env.HYPERFRAMES_WHISPER_PATH = whisper.path;
|
|
63
|
+
// Por si alguna parte del motor llama a «ffmpeg» por su nombre: los nuestros van primero en el PATH.
|
|
64
|
+
const shim = join(HOME, 'shim', PLATFORM);
|
|
65
|
+
rmSync(shim, { recursive: true, force: true });
|
|
66
|
+
mkdirSync(shim, { recursive: true });
|
|
67
|
+
symlinkSync(ffmpeg, join(shim, TOOLS.ffmpeg.file));
|
|
68
|
+
symlinkSync(ffprobe, join(shim, TOOLS.ffprobe.file));
|
|
69
|
+
env.PATH = `${shim}${process.platform === 'win32' ? ';' : ':'}${env.PATH ?? ''}`;
|
|
70
|
+
return { env, ffmpeg, ffprobe };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function runEngine(args, env, cwd) {
|
|
74
|
+
const r = spawnSync(process.execPath, [ENGINE, ...args], { stdio: 'inherit', env, cwd });
|
|
75
|
+
return r.status ?? 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── comprobaciones propias
|
|
79
|
+
function validateProject(dir) {
|
|
80
|
+
const issues = projectHtml(dir).flatMap(validateHtml);
|
|
81
|
+
for (const i of issues) log(`${i.level === 'error' ? '✗' : '⚠'} ${i.rule} ${i.file.replace(dir + '/', '')}:${i.line} — ${i.msg}`);
|
|
82
|
+
const errors = issues.filter((i) => i.level === 'error').length;
|
|
83
|
+
log(errors ? `✗ ${errors} error(es) de Ignix Editor` : `✓ Ignix Editor: HTML y recursos correctos${issues.length ? ` (${issues.length} aviso(s))` : ''}`);
|
|
84
|
+
return errors;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const projectDir = (p) => {
|
|
88
|
+
const dir = resolve(p ?? '.');
|
|
89
|
+
if (!existsSync(join(dir, 'index.html'))) fail(`No hay index.html en ${dir}. ¿Es la carpeta del proyecto? (créala con: ignix-editor init <nombre>)`);
|
|
90
|
+
return dir;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// ── comandos
|
|
94
|
+
const commands = {
|
|
95
|
+
async doctor() {
|
|
96
|
+
const major = Number(process.versions.node.split('.')[0]);
|
|
97
|
+
log(`${major >= 22 ? '✓' : '✗'} Node ${process.versions.node}${major >= 22 ? '' : ' — hace falta Node 22 o superior'}`);
|
|
98
|
+
log(`✓ Ignix Editor ${PKG.version} · motor HyperFrames ${UPSTREAM.version} (parches: ${UPSTREAM.patches.join(', ')})`);
|
|
99
|
+
log(` Plataforma ${PLATFORM} · datos en ${HOME}`);
|
|
100
|
+
let ok = major >= 22;
|
|
101
|
+
for (const name of Object.keys(TOOLS)) {
|
|
102
|
+
const f = findTool(name);
|
|
103
|
+
const line = f.path ? `✓ ${name}: ${f.path}${f.source === 'env' ? ' (variable de entorno)' : ''}` : f.error ? `✗ ${name}: ${f.error}` : f.source === 'download' ? `• ${name}: se descargará la primera vez` : `✗ ${name}: aún no publicado para ${PLATFORM} (apunta ${TOOLS[name].env} a uno local)`;
|
|
104
|
+
log(line);
|
|
105
|
+
if (!f.path && f.source !== 'download' && name !== 'whisper') ok = false;
|
|
106
|
+
}
|
|
107
|
+
if (findTool('ffmpeg').path) {
|
|
108
|
+
const enc = spawnSync(findTool('ffmpeg').path, ['-hide_banner', '-encoders'], { encoding: 'utf8' }).stdout ?? '';
|
|
109
|
+
const h264 = /\blibx264\b/.test(enc) ? 'libx264' : /\bh264_videotoolbox\b/.test(enc) ? 'VideoToolbox' : null;
|
|
110
|
+
log(`${h264 ? '✓' : '✗'} codificador H.264: ${h264 ?? 'ninguno (hace falta libx264 o VideoToolbox)'}`);
|
|
111
|
+
if (!h264) ok = false;
|
|
112
|
+
}
|
|
113
|
+
process.exit(ok ? 0 : 1);
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
async init(argv) {
|
|
117
|
+
const { pos, opts } = parseArgs(argv, { dir: 'str' });
|
|
118
|
+
const name = pos[0];
|
|
119
|
+
if (!name || !/^[\w.-]+$/.test(name)) fail('Uso: ignix-editor init <nombre> [--dir carpeta] (nombre sin espacios)');
|
|
120
|
+
const dir = resolve(opts.dir ?? join(VIDEOS_DIR, name));
|
|
121
|
+
if (existsSync(dir)) fail(`${dir} ya existe. Elige otro nombre o trabaja dentro de ese proyecto.`);
|
|
122
|
+
cpSync(join(PKG_DIR, 'templates', 'blank'), dir, { recursive: true });
|
|
123
|
+
mkdirSync(join(dir, 'assets', 'fonts'), { recursive: true });
|
|
124
|
+
cpSync(join(PKG_DIR, 'node_modules', 'gsap', 'dist', 'gsap.min.js'), join(dir, 'assets', 'gsap.min.js'));
|
|
125
|
+
for (const w of [700, 800, 900]) {
|
|
126
|
+
for (const sub of ['latin', 'latin-ext']) {
|
|
127
|
+
const f = `montserrat-${sub}-${w}-normal.woff2`;
|
|
128
|
+
cpSync(join(PKG_DIR, 'node_modules', '@fontsource', 'montserrat', 'files', f), join(dir, 'assets', 'fonts', f));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
cpSync(join(PKG_DIR, 'src', 'runtime', 'ignix-frame.js'), join(dir, 'ignix-frame.js'));
|
|
132
|
+
const html = readFileSync(join(dir, 'index.html'), 'utf8').replaceAll('__ID__', name.toLowerCase().replace(/[^a-z0-9]+/g, '-'));
|
|
133
|
+
writeFileSync(join(dir, 'index.html'), html);
|
|
134
|
+
console.log(dir);
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
async check(argv) {
|
|
138
|
+
const { pos, rest } = parseArgs(argv, {});
|
|
139
|
+
const dir = projectDir(pos[0]);
|
|
140
|
+
const errors = validateProject(dir);
|
|
141
|
+
const { build, snapped } = prepare(dir);
|
|
142
|
+
if (snapped) log(`• ${snapped} tiempo(s) ajustado(s) al fotograma`);
|
|
143
|
+
const { env } = await engineEnv();
|
|
144
|
+
const code = runEngine(['check', build, ...rest], env, dir);
|
|
145
|
+
process.exit(errors ? 1 : code);
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
async snapshot(argv) {
|
|
149
|
+
const { pos, rest } = parseArgs(argv, { output: 'str' });
|
|
150
|
+
const dir = projectDir(pos[0]);
|
|
151
|
+
const { build } = prepare(dir);
|
|
152
|
+
const { env } = await engineEnv();
|
|
153
|
+
const out = resolve(dir, 'snapshots');
|
|
154
|
+
rmSync(out, { recursive: true, force: true });
|
|
155
|
+
process.exit(runEngine(['snapshot', build, '-o', out, '--describe', 'false', ...rest], env, dir));
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
async render(argv) {
|
|
159
|
+
const { pos, opts, rest } = parseArgs(argv, { output: 'str', lufs: 'str', normalize: 'bool', force: 'bool' });
|
|
160
|
+
const dir = projectDir(pos[0]);
|
|
161
|
+
if (validateProject(dir) && !opts.force) fail('Arregla los errores de arriba antes de renderizar (o --force si sabes lo que haces).');
|
|
162
|
+
const { build, snapped } = prepare(dir);
|
|
163
|
+
if (snapped) log(`• ${snapped} tiempo(s) ajustado(s) al fotograma`);
|
|
164
|
+
const { env, ffmpeg, ffprobe } = await engineEnv();
|
|
165
|
+
const output = resolve(opts.output ?? join(dir, 'renders', `${basename(dir)}.mp4`));
|
|
166
|
+
mkdirSync(dirname(output), { recursive: true });
|
|
167
|
+
const raw = join(build, 'raw.mp4');
|
|
168
|
+
const code = runEngine(['render', build, '-o', raw, ...rest], env, dir);
|
|
169
|
+
if (code !== 0 || !existsSync(raw)) fail('El render falló (mira los mensajes de arriba).');
|
|
170
|
+
if (opts.normalize !== false && hasAudio(ffprobe, raw)) {
|
|
171
|
+
const lufs = Number(opts.lufs ?? -14);
|
|
172
|
+
const r = normalizeLoudness(ffmpeg, raw, output, { lufs });
|
|
173
|
+
log(`✓ Volumen: ${r.before.toFixed(1)} → ${loudness(ffmpeg, output)?.toFixed(1)} LUFS`);
|
|
174
|
+
} else cpSync(raw, output);
|
|
175
|
+
console.log(output);
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
async preview(argv) {
|
|
179
|
+
const { pos, rest } = parseArgs(argv, {});
|
|
180
|
+
const dir = projectDir(pos[0]);
|
|
181
|
+
const { build } = prepare(dir);
|
|
182
|
+
const { env } = await engineEnv();
|
|
183
|
+
log('Vista previa de la copia de trabajo: si cambias el proyecto, vuelve a lanzar este comando.');
|
|
184
|
+
process.exit(runEngine(['preview', build, ...rest], env, dir));
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
async transcribe(argv) {
|
|
188
|
+
const { pos, opts } = parseArgs(argv, { lang: 'str', model: 'str', script: 'str', output: 'str', threads: 'str' });
|
|
189
|
+
const input = pos[0] && resolve(pos[0]);
|
|
190
|
+
if (!input || !existsSync(input)) fail('Uso: ignix-editor transcribe <audio|vídeo> [--lang es] [--model medium] [--script "texto dicho"] [-o palabras.json]');
|
|
191
|
+
const ffmpeg = await ensureTool('ffmpeg', log);
|
|
192
|
+
const ffprobe = await ensureTool('ffprobe', log);
|
|
193
|
+
const whisper = await ensureTool('whisper', log);
|
|
194
|
+
const model = await ensureWhisperModel(opts.model ?? 'medium', log);
|
|
195
|
+
let words = transcribe({ ffmpeg, whisper, model, input, language: opts.lang ?? 'es', threads: Number(opts.threads ?? 8) });
|
|
196
|
+
if (opts.script) {
|
|
197
|
+
const dur = Number(spawnSync(ffprobe, ['-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', input], { encoding: 'utf8' }).stdout.trim());
|
|
198
|
+
words = alignToScript(opts.script, words, dur);
|
|
199
|
+
}
|
|
200
|
+
const json = JSON.stringify({ language: opts.lang ?? 'es', words }, null, 1);
|
|
201
|
+
if (opts.output) writeFileSync(resolve(opts.output), json);
|
|
202
|
+
else console.log(json);
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
async ffmpeg(argv) {
|
|
206
|
+
const r = spawnSync(await ensureTool('ffmpeg', log), argv, { stdio: 'inherit' });
|
|
207
|
+
process.exit(r.status ?? 1);
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
async ffprobe(argv) {
|
|
211
|
+
const r = spawnSync(await ensureTool('ffprobe', log), argv, { stdio: 'inherit' });
|
|
212
|
+
process.exit(r.status ?? 1);
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
async skills(argv) {
|
|
216
|
+
const { pos, opts } = parseArgs(argv, { dir: 'str' });
|
|
217
|
+
if (pos[0] !== 'add') fail('Uso: ignix-editor skills add [--dir ~/.claude/skills]');
|
|
218
|
+
const target = resolve(opts.dir ?? join(homedir(), '.claude', 'skills'), 'ignix-editor');
|
|
219
|
+
rmSync(target, { recursive: true, force: true });
|
|
220
|
+
cpSync(join(PKG_DIR, 'skills', 'ignix-editor'), target, { recursive: true });
|
|
221
|
+
log(`✓ Skill instalada en ${target}`);
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
async version() {
|
|
225
|
+
console.log(`ignix-editor ${PKG.version} (motor HyperFrames ${UPSTREAM.version})`);
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
async help() {
|
|
229
|
+
console.log(`Ignix Editor ${PKG.version} — vídeo con HTML, renderizado en tu ordenador.
|
|
230
|
+
|
|
231
|
+
ignix-editor doctor comprueba Node, ffmpeg, whisper y el codificador
|
|
232
|
+
ignix-editor init <nombre> crea ~/ignix-videos/<nombre> listo para trabajar
|
|
233
|
+
ignix-editor check [carpeta] HTML, recursos, maqueta, movimiento y contraste
|
|
234
|
+
ignix-editor snapshot [carpeta] --at 0,2.5,5 fotogramas sueltos para revisar
|
|
235
|
+
ignix-editor render [carpeta] [-o salida.mp4] [--lufs -14] [--no-normalize]
|
|
236
|
+
ignix-editor preview [carpeta] vista previa en el navegador
|
|
237
|
+
ignix-editor transcribe <fichero> [--lang es] [--script "texto"] [-o palabras.json]
|
|
238
|
+
ignix-editor ffmpeg|ffprobe <args> el ffmpeg de Ignix Editor
|
|
239
|
+
ignix-editor skills add instala la skill para Claude
|
|
240
|
+
|
|
241
|
+
Basado en HyperFrames (Apache-2.0) de HeyGen, Inc. Ver NOTICE.`);
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export async function main(argv) {
|
|
246
|
+
const [cmd = 'help', ...rest] = argv;
|
|
247
|
+
const fn = commands[cmd === '--version' || cmd === '-v' ? 'version' : cmd === '--help' || cmd === '-h' ? 'help' : cmd];
|
|
248
|
+
if (!fn) fail(`Comando desconocido: ${cmd}. Usa: ignix-editor help`);
|
|
249
|
+
try {
|
|
250
|
+
await fn(rest);
|
|
251
|
+
} catch (e) {
|
|
252
|
+
fail(e.message);
|
|
253
|
+
}
|
|
254
|
+
}
|
package/src/prepare.mjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Copia de trabajo del proyecto para el motor (.ignix-build/), con los arreglos de las catas:
|
|
2
|
+
// · tiempos de los clips ajustados al fotograma más cercano (el motor TRUNCA data-media-start × fps:
|
|
3
|
+
// con 4 decimales, 97/30 = 3.2333 daba el fotograma 96 en vez del 97);
|
|
4
|
+
// · ignix-frame.js de esta versión del editor, siempre al día.
|
|
5
|
+
// El proyecto del usuario no se toca.
|
|
6
|
+
import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
|
|
10
|
+
const RUNTIME = join(dirname(fileURLToPath(import.meta.url)), 'runtime', 'ignix-frame.js');
|
|
11
|
+
const SKIP = new Set(['.ignix-build', 'renders', 'snapshots', 'node_modules', '.git', '.DS_Store']);
|
|
12
|
+
// Vídeo y audio no se copian (pueden pesar gigas): enlace a la ruta absoluta del original.
|
|
13
|
+
const MEDIA = /\.(mp4|mov|m4v|webm|mkv|avi|wav|mp3|m4a|aac|ogg|flac)$/i;
|
|
14
|
+
|
|
15
|
+
function mirror(src, dest) {
|
|
16
|
+
mkdirSync(dest, { recursive: true });
|
|
17
|
+
for (const name of readdirSync(src)) {
|
|
18
|
+
if (SKIP.has(name)) continue;
|
|
19
|
+
const from = join(src, name);
|
|
20
|
+
const to = join(dest, name);
|
|
21
|
+
const st = statSync(from);
|
|
22
|
+
if (st.isDirectory()) mirror(from, to);
|
|
23
|
+
else if (MEDIA.test(name)) symlinkSync(realpathSync(from), to);
|
|
24
|
+
else copyFileSync(from, to);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function htmlFiles(dir) {
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const name of readdirSync(dir)) {
|
|
31
|
+
if (SKIP.has(name)) continue;
|
|
32
|
+
const p = join(dir, name);
|
|
33
|
+
if (statSync(p).isDirectory()) out.push(...htmlFiles(p));
|
|
34
|
+
else if (name.endsWith('.html')) out.push(p);
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function projectHtml(dir) {
|
|
40
|
+
return htmlFiles(dir);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Ajusta data-start / data-duration / data-media-start al fotograma más cercano. */
|
|
44
|
+
export function snapTimes(html, fps) {
|
|
45
|
+
let changes = 0;
|
|
46
|
+
const out = html.replace(/\b(data-(?:start|duration|media-start))="(-?\d+(?:\.\d+)?)"/g, (m, attr, raw) => {
|
|
47
|
+
const n = Math.round(Number(raw) * fps);
|
|
48
|
+
// media-start: el motor hace floor(t × fps); un pelo por encima del fotograma lo deja exacto.
|
|
49
|
+
const v = attr === 'data-media-start' ? (n + 1e-4) / fps : n / fps;
|
|
50
|
+
const s = Number(v.toFixed(9)).toString();
|
|
51
|
+
if (s !== raw) changes++;
|
|
52
|
+
return `${attr}="${s}"`;
|
|
53
|
+
});
|
|
54
|
+
return { html: out, changes };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function prepare(projectDir) {
|
|
58
|
+
const build = join(projectDir, '.ignix-build');
|
|
59
|
+
rmSync(build, { recursive: true, force: true });
|
|
60
|
+
mirror(projectDir, build);
|
|
61
|
+
|
|
62
|
+
const root = join(build, 'index.html');
|
|
63
|
+
if (!existsSync(root)) throw new Error(`No hay index.html en ${projectDir}`);
|
|
64
|
+
const fps = Number(readFileSync(root, 'utf8').match(/data-fps="(\d+(?:\.\d+)?)"/)?.[1] ?? 30);
|
|
65
|
+
|
|
66
|
+
let snapped = 0;
|
|
67
|
+
for (const f of htmlFiles(build)) {
|
|
68
|
+
const { html, changes } = snapTimes(readFileSync(f, 'utf8'), fps);
|
|
69
|
+
if (changes) writeFileSync(f, html);
|
|
70
|
+
snapped += changes;
|
|
71
|
+
}
|
|
72
|
+
cpSync(RUNTIME, join(build, 'ignix-frame.js'));
|
|
73
|
+
return { build, fps, snapped };
|
|
74
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ignix-frame.js — animación como función pura del tiempo (Ignix Editor).
|
|
3
|
+
*
|
|
4
|
+
* El render pide cada fotograma por separado y en cualquier orden. Si lo que se ve en el
|
|
5
|
+
* segundo t depende SOLO de t (nada de estado acumulado, nada medido en la página mientras
|
|
6
|
+
* corre), lo que se escribe es lo que sale. Uso:
|
|
7
|
+
*
|
|
8
|
+
* IgnixFrame.run({ id: 'reel', duration: 18.9, fps: 30 }, (t, f) => {
|
|
9
|
+
* el.style.opacity = IgnixFrame.lerp(t, [0, 0.4], [0, 1], IgnixFrame.ease.out);
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* `id` es el data-composition-id del nodo raíz. Necesita GSAP cargado antes.
|
|
13
|
+
*/
|
|
14
|
+
(function () {
|
|
15
|
+
const clamp01 = (x) => Math.min(1, Math.max(0, x));
|
|
16
|
+
|
|
17
|
+
// Curva cúbica de Bézier como en CSS (x1, y1, x2, y2).
|
|
18
|
+
function bezier(x1, y1, x2, y2) {
|
|
19
|
+
return (t) => {
|
|
20
|
+
let u = t;
|
|
21
|
+
for (let i = 0; i < 8; i++) {
|
|
22
|
+
const x = 3 * (1 - u) ** 2 * u * x1 + 3 * (1 - u) * u * u * x2 + u ** 3 - t;
|
|
23
|
+
const dx = 3 * (1 - u) ** 2 * x1 + 6 * (1 - u) * u * (x2 - x1) + 3 * u * u * (1 - x2);
|
|
24
|
+
if (Math.abs(dx) < 1e-6) break;
|
|
25
|
+
u = clamp01(u - x / dx);
|
|
26
|
+
}
|
|
27
|
+
return 3 * (1 - u) ** 2 * u * y1 + 3 * (1 - u) * u * u * y2 + u ** 3;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const ease = {
|
|
32
|
+
linear: (t) => t,
|
|
33
|
+
out: bezier(0.22, 1, 0.36, 1), // entrada rápida que se posa (por defecto)
|
|
34
|
+
inOut: bezier(0.65, 0, 0.35, 1), // movimientos de cámara
|
|
35
|
+
in: (t) => t * t * t,
|
|
36
|
+
outCubic: (t) => 1 - (1 - t) ** 3, // = Easing.out(Easing.cubic) de Remotion = power2.out de GSAP
|
|
37
|
+
inOutSine: (t) => -(Math.cos(Math.PI * t) - 1) / 2,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Valor entre dos puntos en el tiempo: lerp(t, [t0, t1], [v0, v1], ease). Fuera del tramo, se queda en el extremo.
|
|
41
|
+
function lerp(t, range, values, e = ease.linear) {
|
|
42
|
+
const [a, b] = range;
|
|
43
|
+
const [y0, y1] = values;
|
|
44
|
+
return y0 + (y1 - y0) * e(clamp01((t - a) / (b - a)));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Muelle amortiguado en forma cerrada (masa 1): de 0 a 1 empezando en t=0 (segundos).
|
|
48
|
+
// stiffness/damping como en Remotion. Sin estado: se puede pedir cualquier t.
|
|
49
|
+
function spring(t, { stiffness = 220, damping = 14 } = {}) {
|
|
50
|
+
if (t <= 0) return 0;
|
|
51
|
+
const w0 = Math.sqrt(stiffness);
|
|
52
|
+
const z = damping / (2 * w0);
|
|
53
|
+
if (z < 1) {
|
|
54
|
+
const wd = w0 * Math.sqrt(1 - z * z);
|
|
55
|
+
return 1 - Math.exp(-z * w0 * t) * (Math.cos(wd * t) + ((z * w0) / wd) * Math.sin(wd * t));
|
|
56
|
+
}
|
|
57
|
+
return 1 - Math.exp(-w0 * t) * (1 + w0 * t);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Valor por tramos: keys = [[t, valor], ...]; en cada t pasa al nuevo valor en `dur` segundos.
|
|
61
|
+
// El valor puede ser un número o una lista de números (posiciones, rectángulos).
|
|
62
|
+
function keyed(t, keys, dur = 0.5, e = ease.out) {
|
|
63
|
+
let v = keys[0][1];
|
|
64
|
+
for (let i = 1; i < keys.length; i++) {
|
|
65
|
+
const [tk, val] = keys[i];
|
|
66
|
+
if (t < tk) break;
|
|
67
|
+
const p = e(clamp01((t - tk) / dur));
|
|
68
|
+
v = Array.isArray(val) ? val.map((x, j) => v[j] + (x - v[j]) * p) : v + (val - v) * p;
|
|
69
|
+
}
|
|
70
|
+
return v;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Registra la línea de tiempo: un único reloj que llama a render(t, fotograma).
|
|
74
|
+
function run({ id, duration, fps = 30 }, render) {
|
|
75
|
+
if (!window.gsap) throw new Error('ignix-frame: carga GSAP antes que este fichero');
|
|
76
|
+
if (!id) throw new Error('ignix-frame: falta id (el data-composition-id del nodo raíz)');
|
|
77
|
+
const last = Math.max(0, Math.round(duration * fps) - 1);
|
|
78
|
+
const draw = (sec) => {
|
|
79
|
+
const f = Math.min(last, Math.max(0, Math.round(sec * fps)));
|
|
80
|
+
render(f / fps, f);
|
|
81
|
+
};
|
|
82
|
+
const clock = { t: 0 };
|
|
83
|
+
const tl = window.gsap.timeline({ paused: true });
|
|
84
|
+
tl.to(clock, { t: duration, duration, ease: 'none', onUpdate: () => draw(clock.t) }, 0);
|
|
85
|
+
draw(0);
|
|
86
|
+
window.__timelines = window.__timelines || {};
|
|
87
|
+
window.__timelines[id] = tl;
|
|
88
|
+
return tl;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
window.IgnixFrame = { run, lerp, spring, keyed, bezier, ease, clamp01 };
|
|
92
|
+
})();
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Transcripción en el ordenador del usuario con whisper.cpp: cada palabra con su inicio y fin
|
|
2
|
+
// en segundos. Con `script` (el texto que se sabe que se dijo, p. ej. una voz generada) manda
|
|
3
|
+
// el guion en las palabras y whisper en los tiempos: whisper confunde palabras («ADM», «tiene»)
|
|
4
|
+
// y a veces se come el final de una frase.
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
7
|
+
import { tmpdir } from 'node:os';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
|
|
10
|
+
const norm = (s) => s.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/[^\p{L}\p{N}]/gu, '');
|
|
11
|
+
|
|
12
|
+
export function transcribe({ ffmpeg, whisper, model, input, language = 'es', threads = 8 }) {
|
|
13
|
+
const tmp = mkdtempSync(join(tmpdir(), 'ignix-editor-asr-'));
|
|
14
|
+
try {
|
|
15
|
+
const wav = join(tmp, 'audio.wav');
|
|
16
|
+
const a = spawnSync(ffmpeg, ['-nostdin', '-hide_banner', '-loglevel', 'error', '-y', '-i', input, '-vn', '-ar', '16000', '-ac', '1', '-c:a', 'pcm_s16le', wav], { encoding: 'utf8' });
|
|
17
|
+
if (a.status !== 0) throw new Error(`No se pudo leer el audio de ${input}: ${a.stderr.slice(-300)}`);
|
|
18
|
+
const out = join(tmp, 'out');
|
|
19
|
+
const args = ['-m', model, '-l', language, '-ml', '1', '-sow', '-oj', '-of', out, '-t', String(threads), '-f', wav];
|
|
20
|
+
const run = (extra) => spawnSync(whisper, [...extra, ...args], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
21
|
+
// En Mac Intel la GPU (Metal) se cuelga con whisper: CPU directamente. En el resto, GPU y,
|
|
22
|
+
// si falla, otra vez por CPU.
|
|
23
|
+
const intelMac = process.platform === 'darwin' && process.arch === 'x64';
|
|
24
|
+
let w = run(intelMac ? ['-ng'] : []);
|
|
25
|
+
if (w.status !== 0 && !intelMac) w = run(['-ng']);
|
|
26
|
+
if (w.status !== 0) throw new Error(`whisper falló: ${(w.stderr || '').slice(-400)}`);
|
|
27
|
+
const j = JSON.parse(readFileSync(`${out}.json`, 'utf8'));
|
|
28
|
+
const words = [];
|
|
29
|
+
for (const seg of j.transcription ?? []) {
|
|
30
|
+
const t = seg.text.trim();
|
|
31
|
+
if (!t || /^\[.*\]$/.test(t)) continue; // [MÚSICA], [MUSIC]…
|
|
32
|
+
words.push({ t, s: seg.offsets.from / 1000, e: seg.offsets.to / 1000 });
|
|
33
|
+
}
|
|
34
|
+
return words;
|
|
35
|
+
} finally {
|
|
36
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Palabras del guion con los tiempos de whisper. `end` = duración del audio. */
|
|
41
|
+
export function alignToScript(script, tokens, end) {
|
|
42
|
+
const sw = script.split(/\s+/).filter(Boolean);
|
|
43
|
+
const out = [];
|
|
44
|
+
let i = 0;
|
|
45
|
+
for (let j = 0; j < tokens.length && i < sw.length; j++) {
|
|
46
|
+
const tk = tokens[j];
|
|
47
|
+
const tEnd = j + 1 < tokens.length ? tokens[j + 1].s : Math.max(tk.e, end);
|
|
48
|
+
// whisper juntó dos palabras en una («a DM» → «ADM»)
|
|
49
|
+
if (i + 1 < sw.length && norm(sw[i] + sw[i + 1]) === norm(tk.t) && norm(sw[i]) !== norm(tk.t)) {
|
|
50
|
+
const mid = tk.s + (tEnd - tk.s) * (sw[i].length / (sw[i].length + sw[i + 1].length));
|
|
51
|
+
out.push({ t: sw[i], s: tk.s, e: mid }, { t: sw[i + 1], s: mid, e: tEnd });
|
|
52
|
+
i += 2;
|
|
53
|
+
} else {
|
|
54
|
+
out.push({ t: sw[i], s: tk.s, e: tEnd });
|
|
55
|
+
i += 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Palabras que whisper no devolvió: reparte el último tramo entre la última palabra y las que faltan.
|
|
59
|
+
if (i < sw.length && out.length) {
|
|
60
|
+
const last = out.pop();
|
|
61
|
+
const rest = [last.t, ...sw.slice(i)];
|
|
62
|
+
const total = rest.reduce((n, w) => n + w.length, 0);
|
|
63
|
+
let s = last.s;
|
|
64
|
+
for (const w of rest) {
|
|
65
|
+
const e = s + (end - last.s) * (w.length / total);
|
|
66
|
+
out.push({ t: w, s, e });
|
|
67
|
+
s = e;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return out.map((w) => ({ t: w.t, s: +w.s.toFixed(3), e: +w.e.toFixed(3) }));
|
|
71
|
+
}
|