hyperframes 0.8.184 → 0.8.185
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/dist/{add-5ZTD3MUZ.js → add-ODTNPRGG.js} +14 -14
- package/dist/{agentPromptGenerator-VIIPZCJ3.js → agentPromptGenerator-KYO5MKTW.js} +1 -1
- package/dist/{animatedGifPrep-AGASIWVA.js → animatedGifPrep-PEP5GWOJ.js} +9 -9
- package/dist/api.js +17 -17
- package/dist/{asset-LSTEMPIB.js → asset-EZG42XPA.js} +2 -2
- package/dist/{assetCataloger-BKBMNL3A.js → assetCataloger-OHAJFCA7.js} +9 -9
- package/dist/{audio-KGK44XE4.js → audio-65R4T74I.js} +16 -15
- package/dist/{auth-MJWKYK77.js → auth-VP2SIZFN.js} +1 -1
- package/dist/{autoUpdate-2GGDKYR2.js → autoUpdate-RVSUX4SS.js} +2 -2
- package/dist/{backgroundChecks-7GRX5VQY.js → backgroundChecks-LEHK74NS.js} +3 -3
- package/dist/backgroundChecksWorker.js +3 -3
- package/dist/{batchRender-BCV2LELR.js → batchRender-3X6CL7PK.js} +5 -5
- package/dist/{beats-7BCFRBAL.js → beats-66VPQLSC.js} +6 -6
- package/dist/{benchmark-2R6CN5MQ.js → benchmark-PBJVTOJP.js} +10 -10
- package/dist/{browser-6AFGOI7G.js → browser-TPL5MWGC.js} +3 -3
- package/dist/{bundleWithLocalizedFonts-2EGPA5ZO.js → bundleWithLocalizedFonts-67MLTHKM.js} +2 -2
- package/dist/{capture-HOIAW6MO.js → capture-F3GNMRZM.js} +13 -13
- package/dist/{capture-HA2UHLIU.js → capture-YYRE7EV3.js} +2 -2
- package/dist/{captureCompositionFrame-4236FVWJ.js → captureCompositionFrame-PXV2ISHD.js} +13 -13
- package/dist/{catalog-A6CZAWW4.js → catalog-6SDD3OHF.js} +14 -14
- package/dist/{catch-up-TNA4DJOA.js → catch-up-CWIVA5VG.js} +4 -4
- package/dist/{check-5E5U2EQZ.js → check-YQ6REK2S.js} +34 -34
- package/dist/{checkBrowser-FNINXBMZ.js → checkBrowser-5XZCBRXM.js} +31 -31
- package/dist/{chunk-2ULXZ4PG.js → chunk-2TAS5O4P.js} +56 -11
- package/dist/{chunk-3TXNNBI2.js → chunk-37CNYTQQ.js} +2 -2
- package/dist/chunk-3NPOFC43.js +3805 -0
- package/dist/{chunk-EEP5Y5IE.js → chunk-46HEFGXJ.js} +1 -1
- package/dist/{chunk-2XA7KXQO.js → chunk-4CTNDBE3.js} +2 -2
- package/dist/{chunk-MFAETWIF.js → chunk-55YELV7B.js} +1 -1
- package/dist/{chunk-LRGYPXHF.js → chunk-5GUKZRQN.js} +1 -1
- package/dist/{chunk-SAX7HQ5E.js → chunk-6ASIXMFP.js} +1 -1
- package/dist/{chunk-SN7KI5JA.js → chunk-6GPR3G3C.js} +2 -2
- package/dist/{chunk-E32ZQ2WO.js → chunk-6RIZY7OP.js} +1 -1
- package/dist/{chunk-5CS4T6C6.js → chunk-7L37AB57.js} +1 -1
- package/dist/{chunk-BCHSTE7U.js → chunk-7PS6RVWD.js} +1 -1
- package/dist/{chunk-X3CG5YQA.js → chunk-7RAY4WZP.js} +3 -3
- package/dist/{chunk-YWHCXIMD.js → chunk-A6QCO474.js} +5 -5
- package/dist/{chunk-YMS5FOMC.js → chunk-B2A56S5C.js} +1 -1
- package/dist/{chunk-IWTNTUPQ.js → chunk-BH7TTIPN.js} +11 -13
- package/dist/{chunk-DWUGKEHR.js → chunk-BRAPBUPQ.js} +1 -1
- package/dist/{chunk-R2BFTECP.js → chunk-CX3USX23.js} +3 -3
- package/dist/{chunk-JB6ARMQS.js → chunk-D42NU3DZ.js} +1 -1
- package/dist/{chunk-GDEV42FA.js → chunk-EMAWIZ54.js} +481 -36
- package/dist/{chunk-UNNXFKVG.js → chunk-EMSDWBG3.js} +2 -2
- package/dist/{chunk-CXABAXB3.js → chunk-ESBMUZXZ.js} +1 -1
- package/dist/{chunk-EM7C7H7S.js → chunk-F3OPUWQX.js} +7 -7
- package/dist/{chunk-YOZPQCSR.js → chunk-FX6RUJUY.js} +3 -3
- package/dist/{chunk-PSKEKWVU.js → chunk-G2UANIDX.js} +1 -1
- package/dist/{chunk-UKOTVJFV.js → chunk-H5SM5PJI.js} +1 -1
- package/dist/{chunk-YWNJTZGN.js → chunk-H6UY725W.js} +2 -2
- package/dist/{chunk-PFYWVUHA.js → chunk-HDIRZGK4.js} +1 -1
- package/dist/{chunk-HR23IKLZ.js → chunk-HHSJJFVM.js} +2 -2
- package/dist/{chunk-LLC4CS6I.js → chunk-HXUTX5GR.js} +3 -3
- package/dist/{chunk-RGXVEYHI.js → chunk-I3IH5MV5.js} +6 -10
- package/dist/{chunk-Q33P4EAC.js → chunk-I45HL3VP.js} +3 -3
- package/dist/{chunk-TYXH3EKP.js → chunk-I5JRXMCV.js} +16 -1
- package/dist/{chunk-4N4P3ZWL.js → chunk-I7QMXZSB.js} +2 -2
- package/dist/{chunk-ICJEAFPD.js → chunk-IDFNKFPL.js} +7 -7
- package/dist/{chunk-VNVQGDPC.js → chunk-IDGLGXPA.js} +1 -1
- package/dist/{chunk-2PVE4WS2.js → chunk-IPDKZ5IN.js} +33 -6
- package/dist/{chunk-ABZYYUUH.js → chunk-ISTRDGIX.js} +1 -1
- package/dist/{chunk-3MDJIWOV.js → chunk-IVEFOUZI.js} +46 -30
- package/dist/{chunk-4KKKBEP3.js → chunk-J5XEZ24I.js} +3 -3
- package/dist/{chunk-7HJALUIO.js → chunk-K2ZKXTVL.js} +1 -1
- package/dist/{chunk-TE427YID.js → chunk-K73RJB23.js} +2 -2
- package/dist/{chunk-3QVMJ7GX.js → chunk-KQ4JEJLF.js} +9 -9
- package/dist/{chunk-J3QM7AHP.js → chunk-KROXPHXX.js} +9 -3
- package/dist/{chunk-OLZENUPI.js → chunk-LLFQA7XF.js} +1 -1
- package/dist/chunk-LLMSX6V6.js +17 -0
- package/dist/{chunk-WTFUDNW2.js → chunk-LYKSTRAY.js} +3 -3
- package/dist/{chunk-VDM3FEDP.js → chunk-OAG47RE6.js} +1 -1
- package/dist/{chunk-FGJEUV4S.js → chunk-PHMBMOXF.js} +1 -1
- package/dist/{chunk-7MB2ZAQF.js → chunk-PMMQRJDE.js} +1 -1
- package/dist/{chunk-ADDHW2FS.js → chunk-Q447CX26.js} +82 -12
- package/dist/{chunk-YALM6XN4.js → chunk-Q47FAYYK.js} +3 -3
- package/dist/{chunk-ZOCHDXDG.js → chunk-RTBSA3EA.js} +1 -1
- package/dist/{chunk-UJKUB2LH.js → chunk-RUEGYANA.js} +11 -11
- package/dist/{chunk-OYLO6TYK.js → chunk-RUOG4VB7.js} +1 -1
- package/dist/{chunk-ZRHO6YMM.js → chunk-SKYPMHQC.js} +4 -4
- package/dist/{chunk-ES426XRJ.js → chunk-SQVRXHOW.js} +3 -3
- package/dist/{chunk-QL2PNIXC.js → chunk-TAX2ZJAP.js} +24 -16
- package/dist/{chunk-KN46TGHV.js → chunk-TOI35GN2.js} +1 -1
- package/dist/{chunk-74JMKLVU.js → chunk-UPR3MU6Z.js} +1 -1
- package/dist/{chunk-JIUTXKWA.js → chunk-WQLKDL35.js} +2 -1
- package/dist/{chunk-WHPN2TIT.js → chunk-X6L6MD5B.js} +5 -5
- package/dist/{chunk-7NRI7HYX.js → chunk-XWC7CNPY.js} +1 -1
- package/dist/{clean-HGASSMWI.js → clean-7J6ZCCGV.js} +18 -18
- package/dist/cli.js +53 -53
- package/dist/{cloud-JPDVNXHN.js → cloud-7IJCJCDD.js} +4 -4
- package/dist/{cloudrun-AMMGSDRP.js → cloudrun-UNZRIIDB.js} +7 -7
- package/dist/commands/contrast-audit.browser.js +1 -2
- package/dist/commands/layout-audit.browser.js +196 -0
- package/dist/{compare-LHHVHUN3.js → compare-Q7VW5JZT.js} +28 -28
- package/dist/{compiler-Q3N6QXMT.js → compiler-KPHYGFXL.js} +6 -6
- package/dist/{component-D72J32Q7.js → component-UUBREJKN.js} +3 -3
- package/dist/{compositions-UQRJ5ROG.js → compositions-T4FTKIDP.js} +13 -13
- package/dist/{delete-P42VIDDA.js → delete-WZQF2IIA.js} +2 -2
- package/dist/{deploy-WZTH57O4.js → deploy-JU7A3XNC.js} +1 -1
- package/dist/{deterministicFonts-VQ5UBMXY.js → deterministicFonts-EGAAE7QL.js} +3 -3
- package/dist/{dist-SENYPQGW.js → dist-LM7AVHOU.js} +3 -3
- package/dist/{dist-DYS24AMA.js → dist-ULGTPSU4.js} +8 -4
- package/dist/docs/data-attributes.md +1 -1
- package/dist/{doctor-KEJIG2SK.js → doctor-VSNGRKXJ.js} +13 -13
- package/dist/{events-CYKSNR7N.js → events-CRW2DYUT.js} +3 -3
- package/dist/{events-UZXFQPMT.js → events-E63YBUL2.js} +3 -3
- package/dist/{feedback-LXNQF7CA.js → feedback-OSZWVR6N.js} +8 -8
- package/dist/{ffmpeg-BYHON577.js → ffmpeg-JLH3Z7G7.js} +9 -9
- package/dist/{figma-EIQ35PS6.js → figma-2BQNNR53.js} +3 -3
- package/dist/fontLocalizeCli.js +12 -12
- package/dist/{get-CC2YL7QO.js → get-P2XI53QW.js} +2 -2
- package/dist/{gpuPolicy-VFSACUQV.js → gpuPolicy-NTKQJY75.js} +9 -9
- package/dist/{grade-compare-TUQL7IV2.js → grade-compare-OYASIHIB.js} +29 -29
- package/dist/{gsapParserAcorn-7NCK2LVT.js → gsapParserAcorn-SKODXC2N.js} +2 -2
- package/dist/{help-ROROO5K6.js → help-HK6K2N4G.js} +1 -1
- package/dist/{history-PNELYLXX.js → history-JMTYKLXW.js} +6 -6
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +63 -63
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/{info-4FZTH6AS.js → info-AW7CIVRE.js} +9 -9
- package/dist/{init-I43GHHVP.js → init-6KIDG4LB.js} +30 -30
- package/dist/{inspect-IT4TYIZ3.js → inspect-B7BLYMRZ.js} +29 -29
- package/dist/{installer-CWOJVK5K.js → installer-ZP2LQZUQ.js} +7 -7
- package/dist/{keyframes-3FBOGVD4.js → keyframes-EQ36A5JE.js} +7 -7
- package/dist/{lambda-H3V32I7M.js → lambda-E6VURLIS.js} +9 -9
- package/dist/{layout-BZ5LYJ5C.js → layout-XYC64QQQ.js} +29 -29
- package/dist/{lint-ZTNSGP2S.js → lint-V5DJYWBX.js} +9 -9
- package/dist/{lintProject-C2ONSH2U.js → lintProject-JATQKR64.js} +3 -3
- package/dist/{list-XM4GWJYY.js → list-RUGVRTVD.js} +2 -2
- package/dist/{login-H6HYKMWX.js → login-ZTKGKXGS.js} +4 -4
- package/dist/{manager-TWVDSJXO.js → manager-JUP7PM6N.js} +10 -10
- package/dist/{media-treatment-N7MY5NXB.js → media-treatment-VIUPK4OR.js} +15 -15
- package/dist/{models-WEMIMYBD.js → models-LJS2HBOZ.js} +13 -13
- package/dist/{motionShot-RHICTVPU.js → motionShot-3UAXZ7SN.js} +16 -16
- package/dist/{normalize-audio-ZFUZCJE3.js → normalize-audio-SBYI4YIH.js} +4 -4
- package/dist/{open-IBJ4FL3G.js → open-S27TUD3A.js} +14 -14
- package/dist/{parakeetRunner-XXO4WSLR.js → parakeetRunner-ETLMLJ4L.js} +14 -14
- package/dist/{pipeline-6ML3LUVK.js → pipeline-I2M22M24.js} +10 -10
- package/dist/{play-RV4NAVF5.js → play-COJU6VJK.js} +21 -21
- package/dist/{preflight-R3DEFMLA.js → preflight-FZ24NCHH.js} +10 -10
- package/dist/{present-5TBJGE6B.js → present-YAHKLC5D.js} +17 -17
- package/dist/{preview-FLKZ5CXJ.js → preview-KQOEU5YE.js} +20 -20
- package/dist/{producer-7XYSPVKH.js → producer-DTNNG4T6.js} +1 -1
- package/dist/{projectConfig-TBU2VWZX.js → projectConfig-4A76VYUP.js} +9 -9
- package/dist/{publication-CWWUJYJ5.js → publication-SQPMC2W3.js} +4 -4
- package/dist/{publish-FSNE4FEB.js → publish-QUEJBGGT.js} +11 -11
- package/dist/{remove-background-MDFWRWCT.js → remove-background-FP2ETAQH.js} +11 -11
- package/dist/{render-F4JQ553X.js → render-BIFIL4U6.js} +31 -31
- package/dist/{render-DBGQZAZT.js → render-GQFXJWLV.js} +17 -29
- package/dist/{render-LWZKXCLY.js → render-P664SMC7.js} +5 -5
- package/dist/{render-batch-PU7NMLIJ.js → render-batch-ZCPMYH6Z.js} +5 -5
- package/dist/renderSetupWorker.js +3 -3
- package/dist/{resolver-RUBGFXPC.js → resolver-BUC2GFZQ.js} +6 -6
- package/dist/{sherpa-X2TBNO6P.js → sherpa-HFT6XEP6.js} +13 -13
- package/dist/skills/hyperframes/SKILL.md +52 -174
- package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/FRAME.md +289 -0
- package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/caption-skin.html +220 -0
- package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
- package/dist/skills/hyperframes/assets/frame-presets/blockframe/FRAME.md +275 -0
- package/dist/skills/hyperframes/assets/frame-presets/blockframe/caption-skin.html +223 -0
- package/dist/skills/hyperframes/assets/frame-presets/blockframe/frame-showcase.html +1347 -0
- package/dist/skills/hyperframes/assets/frame-presets/blue-professional/FRAME.md +307 -0
- package/dist/skills/hyperframes/assets/frame-presets/blue-professional/caption-skin.html +222 -0
- package/dist/skills/hyperframes/assets/frame-presets/blue-professional/frame-showcase.html +1372 -0
- package/dist/skills/hyperframes/assets/frame-presets/bold-poster/FRAME.md +275 -0
- package/dist/skills/hyperframes/assets/frame-presets/bold-poster/caption-skin.html +229 -0
- package/dist/skills/hyperframes/assets/frame-presets/bold-poster/frame-showcase.html +1140 -0
- package/dist/skills/hyperframes/assets/frame-presets/broadside/FRAME.md +284 -0
- package/dist/skills/hyperframes/assets/frame-presets/broadside/caption-skin.html +224 -0
- package/dist/skills/hyperframes/assets/frame-presets/broadside/frame-showcase.html +1166 -0
- package/dist/skills/hyperframes/assets/frame-presets/capsule/FRAME.md +284 -0
- package/dist/skills/hyperframes/assets/frame-presets/capsule/caption-skin.html +223 -0
- package/dist/skills/hyperframes/assets/frame-presets/capsule/frame-showcase.html +1465 -0
- package/dist/skills/hyperframes/assets/frame-presets/cartesian/FRAME.md +278 -0
- package/dist/skills/hyperframes/assets/frame-presets/cartesian/caption-skin.html +221 -0
- package/dist/skills/hyperframes/assets/frame-presets/cartesian/frame-showcase.html +1263 -0
- package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/FRAME.md +265 -0
- package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/caption-skin.html +237 -0
- package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/FRAME.md +277 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/caption-skin.html +223 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-400.woff2 +0 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-700.woff2 +0 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-400.woff2 +0 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-700.woff2 +0 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-400.woff2 +0 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-700.woff2 +0 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-eb-garamond.txt +93 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-inter.txt +93 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-jetbrains-mono.txt +93 -0
- package/dist/skills/hyperframes/assets/frame-presets/code-editorial/frame-showcase.html +1438 -0
- package/dist/skills/hyperframes/assets/frame-presets/coral/FRAME.md +314 -0
- package/dist/skills/hyperframes/assets/frame-presets/coral/caption-skin.html +225 -0
- package/dist/skills/hyperframes/assets/frame-presets/coral/frame-showcase.html +1268 -0
- package/dist/skills/hyperframes/assets/frame-presets/creative-mode/FRAME.md +333 -0
- package/dist/skills/hyperframes/assets/frame-presets/creative-mode/caption-skin.html +226 -0
- package/dist/skills/hyperframes/assets/frame-presets/creative-mode/frame-showcase.html +1330 -0
- package/dist/skills/hyperframes/assets/frame-presets/daisy-days/FRAME.md +274 -0
- package/dist/skills/hyperframes/assets/frame-presets/daisy-days/caption-skin.html +229 -0
- package/dist/skills/hyperframes/assets/frame-presets/daisy-days/frame-showcase.html +1444 -0
- package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/FRAME.md +265 -0
- package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/caption-skin.html +222 -0
- package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/frame-showcase.html +1273 -0
- package/dist/skills/hyperframes/references/captions.md +46 -0
- package/dist/skills/hyperframes/references/film.md +47 -0
- package/dist/skills/hyperframes/references/format.md +157 -0
- package/dist/skills/hyperframes/references/look.md +69 -0
- package/dist/skills/hyperframes/references/motion.md +94 -0
- package/dist/skills/hyperframes/references/overlays.md +39 -0
- package/dist/skills/hyperframes/references/plugin-installation.md +3 -3
- package/dist/skills/hyperframes/references/review.md +51 -0
- package/dist/skills/hyperframes/references/runtimes.md +43 -0
- package/dist/skills/hyperframes/references/skill-lifecycle.md +21 -13
- package/dist/skills/hyperframes/references/sound.md +43 -0
- package/dist/skills/hyperframes/references/spec.md +76 -0
- package/dist/skills/hyperframes/references/story.md +103 -0
- package/dist/skills/hyperframes/references/storyboard-format.md +30 -22
- package/dist/skills/hyperframes/references/storyboard.md +36 -0
- package/dist/skills/hyperframes/references/types/3d.md +25 -0
- package/dist/skills/hyperframes/references/types/character.md +20 -0
- package/dist/skills/hyperframes/references/types/data.md +19 -0
- package/dist/skills/hyperframes/references/types/explainer.md +34 -0
- package/dist/skills/hyperframes/references/types/launch.md +31 -0
- package/dist/skills/hyperframes/references/types/music.md +24 -0
- package/dist/skills/hyperframes/references/types/vertical.md +23 -0
- package/dist/skills/hyperframes/scripts/bake-basemap.mjs +324 -0
- package/dist/skills/hyperframes/scripts/lib/main-module.test.mjs +1 -6
- package/dist/skills/hyperframes/scripts/locate.mjs +228 -0
- package/dist/skills/hyperframes-cli/SKILL.md +76 -179
- package/dist/skills/hyperframes-cli/references/beats.md +1 -1
- package/dist/skills/hyperframes-cli/references/cloud.md +2 -2
- package/dist/skills/hyperframes-cli/references/cloudrun.md +1 -1
- package/dist/skills/hyperframes-cli/references/conventions.md +17 -0
- package/dist/skills/hyperframes-cli/references/feedback.md +14 -0
- package/dist/skills/hyperframes-cli/references/init-and-scaffold.md +11 -7
- package/dist/skills/hyperframes-cli/references/lambda.md +1 -1
- package/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +19 -8
- package/dist/skills/hyperframes-cli/references/preview-render.md +8 -2
- package/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +8 -0
- package/dist/skills/media-use/SKILL.md +47 -91
- package/dist/skills/media-use/audio/references/bgm.md +1 -1
- package/dist/skills/media-use/audio/references/captions/authoring.md +1 -2
- package/dist/skills/media-use/audio/references/captions/motion.md +5 -5
- package/dist/skills/media-use/audio/references/tts.md +0 -3
- package/dist/skills/media-use/audio/scripts/audio.mjs +5 -6
- package/dist/skills/media-use/audio/scripts/carve.mjs +560 -0
- package/dist/skills/media-use/audio/scripts/carve.test.mjs +254 -0
- package/dist/skills/media-use/audio/scripts/extract-audio-data.py +199 -0
- package/dist/skills/media-use/references/local.md +24 -0
- package/dist/skills/media-use/references/memory.md +4 -4
- package/dist/skills/media-use/references/mixing.md +71 -0
- package/dist/skills/media-use/references/operations.md +1 -1
- package/dist/skills/media-use/scripts/compatibility.test.mjs +1 -56
- package/dist/skills/media-use/scripts/lib/prefs-store.mjs +1 -1
- package/dist/skills/media-use/scripts/lib/recipe-store.mjs +1 -1
- package/dist/skills/media-use/scripts/prefs.mjs +2 -3
- package/dist/skills/media-use/scripts/recipe.mjs +1 -3
- package/dist/{skills-WHKMWO2D.js → skills-3WEVO3NU.js} +20 -13
- package/dist/{skillsUpdateCheck-XQGZGJJG.js → skillsUpdateCheck-BFPWFOK5.js} +3 -3
- package/dist/{snapshot-M4NUUSNU.js → snapshot-WDQ6S7CJ.js} +457 -98
- package/dist/{src-6MSC62U2.js → src-NPR2JZOJ.js} +11 -11
- package/dist/{src-4UYM2K3S.js → src-RZ574OKP.js} +8 -8
- package/dist/{staticProjectServer-ERDTFP45.js → staticProjectServer-FTGTEZI4.js} +17 -17
- package/dist/studio/assets/{hyperframes-player-DEncBxR7.js → hyperframes-player-CoOdf435.js} +1 -1
- package/dist/studio/assets/{index-Cc22mgvY.js → index-CR85xg2x.js} +1 -1
- package/dist/studio/assets/{index-BABXr78Q.js → index-C_6rTpaB.js} +5 -5
- package/dist/studio/index.html +1 -1
- package/dist/{studio-api-SAKD3VKC.js → studio-api-TAWB7B23.js} +11 -11
- package/dist/{studioServer-IRI7EVOM.js → studioServer-HRQGJTBU.js} +48 -48
- package/dist/{telemetry-F4XADVAF.js → telemetry-QZ6HJF4W.js} +3 -3
- package/dist/templates/_shared/AGENTS.md +14 -19
- package/dist/templates/_shared/CLAUDE.md +14 -19
- package/dist/templates/blank/index.html +10 -4
- package/dist/{timeline-5I444RRE.js → timeline-IKUEW42T.js} +20 -19
- package/dist/{tokens-LRRYM35A.js → tokens-AUGUEWHS.js} +2 -2
- package/dist/{transcribe-44XDFNVU.js → transcribe-7734CG3N.js} +18 -18
- package/dist/{transcribe-WHYHWAB2.js → transcribe-FWU6EMEO.js} +12 -12
- package/dist/{updateCheck-7CPH3CAZ.js → updateCheck-VIPQ3FPW.js} +2 -2
- package/dist/{upgrade-WW4GQ2RI.js → upgrade-4VNDQTVO.js} +2 -2
- package/dist/{urlDownloader-OHLLP45A.js → urlDownloader-6CXL4CL7.js} +8 -8
- package/dist/{validate-VNCDH2LW.js → validate-QWCMVWID.js} +23 -23
- package/dist/{video-5OHTLL2D.js → video-245Q5WN4.js} +9 -9
- package/dist/warmCheck.js +36 -36
- package/package.json +1 -1
- package/dist/chunk-R2SQBPMH.js +0 -3805
- package/dist/skills/hyperframes/references/brief-contract.md +0 -108
- package/dist/skills/hyperframes/references/brief-format.md +0 -72
- package/dist/skills/hyperframes/references/capability-menu.md +0 -47
- package/dist/skills/hyperframes/references/frame-worker-core.md +0 -82
- package/dist/skills/hyperframes/references/intent-interview.md +0 -73
- package/dist/skills/hyperframes/references/pitch-round.md +0 -40
- package/dist/skills/hyperframes/references/production-loop.md +0 -26
- package/dist/skills/hyperframes/references/review-loop.md +0 -37
- package/dist/skills/hyperframes/references/route-briefs.md +0 -11
- package/dist/skills/hyperframes/references/routes/embedded-captions.md +0 -11
- package/dist/skills/hyperframes/references/routes/faceless-explainer.md +0 -12
- package/dist/skills/hyperframes/references/routes/general-video.md +0 -12
- package/dist/skills/hyperframes/references/routes/motion-graphics.md +0 -11
- package/dist/skills/hyperframes/references/routes/music-to-video.md +0 -12
- package/dist/skills/hyperframes/references/routes/pr-to-video.md +0 -28
- package/dist/skills/hyperframes/references/routes/product-launch-video.md +0 -13
- package/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +0 -9
- package/dist/skills/hyperframes/references/routes/slideshow.md +0 -11
- package/dist/skills/hyperframes/references/routes/talking-head-recut.md +0 -11
- package/dist/skills/hyperframes/references/script-format.md +0 -52
- package/dist/skills/hyperframes/references/subagent-dispatch.md +0 -35
- package/dist/skills/hyperframes/references/workflow-catalog.md +0 -10
- package/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +0 -176
- package/dist/skills/media-use/audio/scripts/lib/host-audio.mjs +0 -28
- package/dist/skills/media-use/audio/scripts/lib/host-audio.test.mjs +0 -106
|
@@ -7,6 +7,9 @@ var __dirname = __hf_dirname(__filename);
|
|
|
7
7
|
import {
|
|
8
8
|
writeCaptureFileSync
|
|
9
9
|
} from "./chunk-MRF4AMKD.js";
|
|
10
|
+
import {
|
|
11
|
+
toDomNode
|
|
12
|
+
} from "./chunk-LLMSX6V6.js";
|
|
10
13
|
import {
|
|
11
14
|
parseAngle
|
|
12
15
|
} from "./chunk-KZI44OPA.js";
|
|
@@ -22,7 +25,7 @@ import {
|
|
|
22
25
|
findFFmpeg,
|
|
23
26
|
findFFprobe,
|
|
24
27
|
getFFmpegInstallHint
|
|
25
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-K2ZKXTVL.js";
|
|
26
29
|
import {
|
|
27
30
|
pngDimensions,
|
|
28
31
|
reportArtifacts,
|
|
@@ -30,20 +33,20 @@ import {
|
|
|
30
33
|
} from "./chunk-57GN6KWT.js";
|
|
31
34
|
import {
|
|
32
35
|
captureArtifactRevision
|
|
33
|
-
} from "./chunk-
|
|
34
|
-
import "./chunk-
|
|
36
|
+
} from "./chunk-OAG47RE6.js";
|
|
37
|
+
import "./chunk-PHMBMOXF.js";
|
|
35
38
|
import "./chunk-X7MTZ4T2.js";
|
|
36
39
|
import {
|
|
37
40
|
resolveProject
|
|
38
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-5GUKZRQN.js";
|
|
39
42
|
import {
|
|
40
43
|
serveStaticProjectHtml
|
|
41
|
-
} from "./chunk-
|
|
42
|
-
import "./chunk-
|
|
44
|
+
} from "./chunk-J5XEZ24I.js";
|
|
45
|
+
import "./chunk-H6UY725W.js";
|
|
43
46
|
import "./chunk-X7MTZ4T2.js";
|
|
44
47
|
import "./chunk-XUHOIDKG.js";
|
|
45
|
-
import "./chunk-
|
|
46
|
-
import "./chunk-
|
|
48
|
+
import "./chunk-KQ4JEJLF.js";
|
|
49
|
+
import "./chunk-SKYPMHQC.js";
|
|
47
50
|
import "./chunk-6JR2XUEE.js";
|
|
48
51
|
import "./chunk-TTVHYD5R.js";
|
|
49
52
|
import {
|
|
@@ -53,7 +56,7 @@ import {
|
|
|
53
56
|
recordArtifacts,
|
|
54
57
|
retainSnapshotOutput
|
|
55
58
|
} from "./chunk-U6RXZNZE.js";
|
|
56
|
-
import "./chunk-
|
|
59
|
+
import "./chunk-6GPR3G3C.js";
|
|
57
60
|
import "./chunk-ALVXFXUG.js";
|
|
58
61
|
import {
|
|
59
62
|
DEFAULT_ZOOM_SCALE,
|
|
@@ -63,43 +66,44 @@ import {
|
|
|
63
66
|
resolveCropRegion,
|
|
64
67
|
runFfmpegOnce,
|
|
65
68
|
seekCompositionTimeline
|
|
66
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-IDFNKFPL.js";
|
|
67
70
|
import "./chunk-FH7WODJH.js";
|
|
68
|
-
import "./chunk-
|
|
71
|
+
import "./chunk-TOI35GN2.js";
|
|
69
72
|
import "./chunk-MOEGCMKI.js";
|
|
70
|
-
import "./chunk-
|
|
73
|
+
import "./chunk-SQVRXHOW.js";
|
|
71
74
|
import "./chunk-DKPNNYBZ.js";
|
|
72
|
-
import "./chunk-
|
|
75
|
+
import "./chunk-G2UANIDX.js";
|
|
73
76
|
import "./chunk-K2FLNJVB.js";
|
|
74
77
|
import "./chunk-442JNXRM.js";
|
|
75
78
|
import "./chunk-EHSBBBR2.js";
|
|
76
79
|
import "./chunk-DQBY7FRR.js";
|
|
77
80
|
import {
|
|
78
81
|
resolveLocalBrowserGpuMode
|
|
79
|
-
} from "./chunk-
|
|
80
|
-
import "./chunk-
|
|
82
|
+
} from "./chunk-EMSDWBG3.js";
|
|
83
|
+
import "./chunk-HDIRZGK4.js";
|
|
81
84
|
import "./chunk-XT7X6QCP.js";
|
|
82
85
|
import "./chunk-4YYJOFKS.js";
|
|
83
86
|
import "./chunk-HVW7ABXD.js";
|
|
84
|
-
import "./chunk-
|
|
87
|
+
import "./chunk-RTBSA3EA.js";
|
|
85
88
|
import {
|
|
86
89
|
runWithConcurrencyLimit
|
|
87
90
|
} from "./chunk-JHOCK3DG.js";
|
|
88
|
-
import "./chunk-
|
|
89
|
-
import "./chunk-
|
|
91
|
+
import "./chunk-HXUTX5GR.js";
|
|
92
|
+
import "./chunk-PMMQRJDE.js";
|
|
90
93
|
import "./chunk-AWDFDFI3.js";
|
|
91
94
|
import "./chunk-P6LJ4Y32.js";
|
|
92
95
|
import "./chunk-GMECXFAN.js";
|
|
93
|
-
import "./chunk-
|
|
96
|
+
import "./chunk-7L37AB57.js";
|
|
94
97
|
import "./chunk-EOVYQ3IG.js";
|
|
95
|
-
import "./chunk-
|
|
96
|
-
import "./chunk-
|
|
98
|
+
import "./chunk-WQLKDL35.js";
|
|
99
|
+
import "./chunk-H5SM5PJI.js";
|
|
97
100
|
import "./chunk-VWG7OQKU.js";
|
|
98
101
|
import {
|
|
99
102
|
defineCommand
|
|
100
103
|
} from "./chunk-S3S4TGEH.js";
|
|
101
104
|
import "./chunk-54HJ63Q2.js";
|
|
102
105
|
import {
|
|
106
|
+
CliRuntimeError,
|
|
103
107
|
failCommand
|
|
104
108
|
} from "./chunk-JVBRJMOP.js";
|
|
105
109
|
import {
|
|
@@ -108,23 +112,26 @@ import {
|
|
|
108
112
|
import "./chunk-KLIKCX6Q.js";
|
|
109
113
|
import "./chunk-EVMY7IPL.js";
|
|
110
114
|
import "./chunk-7FMUTGOH.js";
|
|
111
|
-
import "./chunk-
|
|
115
|
+
import "./chunk-I3IH5MV5.js";
|
|
112
116
|
import "./chunk-IZCW2NKT.js";
|
|
113
117
|
import {
|
|
114
118
|
createRuntimeStartTimeResolver,
|
|
115
119
|
isClipVisibleAt,
|
|
116
120
|
isInClipWindow
|
|
117
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-KROXPHXX.js";
|
|
118
122
|
import "./chunk-RQVDTPGD.js";
|
|
119
|
-
import "./chunk-
|
|
123
|
+
import "./chunk-Q47FAYYK.js";
|
|
120
124
|
import {
|
|
121
125
|
readElementRateSpec,
|
|
122
126
|
sourceTimeAt,
|
|
123
127
|
timeAtSourceTime
|
|
124
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-3NPOFC43.js";
|
|
125
129
|
import "./chunk-VC76R6W2.js";
|
|
126
130
|
import "./chunk-UJKQWGFF.js";
|
|
127
|
-
import
|
|
131
|
+
import {
|
|
132
|
+
topLevelElements,
|
|
133
|
+
trackKindOf
|
|
134
|
+
} from "./chunk-B2A56S5C.js";
|
|
128
135
|
import "./chunk-OFQWTKPW.js";
|
|
129
136
|
import "./chunk-DPVXBVLL.js";
|
|
130
137
|
import "./chunk-3GXQPCJC.js";
|
|
@@ -142,23 +149,26 @@ import "./chunk-XT6MXC7A.js";
|
|
|
142
149
|
import "./chunk-4UMPIPCQ.js";
|
|
143
150
|
import {
|
|
144
151
|
lintProject
|
|
145
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-Q447CX26.js";
|
|
146
153
|
import "./chunk-VAS6HQX3.js";
|
|
147
154
|
import "./chunk-6BNTGNGD.js";
|
|
148
|
-
import "./chunk-
|
|
155
|
+
import "./chunk-RUOG4VB7.js";
|
|
149
156
|
import "./chunk-MMQ52NIZ.js";
|
|
150
157
|
import "./chunk-BSQ7XANM.js";
|
|
151
158
|
import {
|
|
152
159
|
parseHTML
|
|
153
160
|
} from "./chunk-SDYDNHEE.js";
|
|
154
161
|
import "./chunk-IXLUTE6N.js";
|
|
155
|
-
import "./chunk-
|
|
162
|
+
import "./chunk-I5JRXMCV.js";
|
|
156
163
|
import "./chunk-W2LGJSEN.js";
|
|
164
|
+
import {
|
|
165
|
+
withMeta
|
|
166
|
+
} from "./chunk-ISTRDGIX.js";
|
|
157
167
|
import "./chunk-K4WIOZFP.js";
|
|
158
168
|
import "./chunk-XUXGIA7H.js";
|
|
159
169
|
import "./chunk-WERLJGIC.js";
|
|
160
170
|
import "./chunk-ISN5GRYI.js";
|
|
161
|
-
import "./chunk-
|
|
171
|
+
import "./chunk-I7QMXZSB.js";
|
|
162
172
|
import {
|
|
163
173
|
normalizeErrorMessage
|
|
164
174
|
} from "./chunk-KNU5COPB.js";
|
|
@@ -182,6 +192,15 @@ function sampleSnapshotRange([start, end], frames, duration, exclusiveEnd = fals
|
|
|
182
192
|
const last = exclusiveEnd || end === duration ? end - Math.min(1e-3, (end - start) / (frames * 2)) : end;
|
|
183
193
|
return Array.from({ length: frames }, (_, i) => start + (last - start) * i / (frames - 1));
|
|
184
194
|
}
|
|
195
|
+
function snapshotStartResolver(document2, durations) {
|
|
196
|
+
return createRuntimeStartTimeResolver({
|
|
197
|
+
documentRef: document2,
|
|
198
|
+
timelineRegistry: Object.fromEntries(
|
|
199
|
+
Object.entries(durations).map(([key, value]) => [key, { duration: () => value }])
|
|
200
|
+
),
|
|
201
|
+
includeAuthoredTimingAttrs: true
|
|
202
|
+
});
|
|
203
|
+
}
|
|
185
204
|
function resolveSnapshotCompositionRange(html, durations, id, duration) {
|
|
186
205
|
const { document: document2 } = parseHTML(html);
|
|
187
206
|
const matches = Array.from(document2.querySelectorAll("[data-composition-id]")).filter(
|
|
@@ -191,14 +210,7 @@ function resolveSnapshotCompositionRange(html, durations, id, duration) {
|
|
|
191
210
|
throw new Error(
|
|
192
211
|
`Composition ID ${JSON.stringify(id)} matched ${matches.length} elements; expected exactly one`
|
|
193
212
|
);
|
|
194
|
-
const
|
|
195
|
-
Object.entries(durations).map(([key, value]) => [key, { duration: () => value }])
|
|
196
|
-
);
|
|
197
|
-
const resolver = createRuntimeStartTimeResolver({
|
|
198
|
-
documentRef: document2,
|
|
199
|
-
timelineRegistry: registry,
|
|
200
|
-
includeAuthoredTimingAttrs: true
|
|
201
|
-
});
|
|
213
|
+
const resolver = snapshotStartResolver(document2, durations);
|
|
202
214
|
let start = 0, end = duration;
|
|
203
215
|
for (let el = matches[0]; el; el = el.parentElement) {
|
|
204
216
|
if (!el.hasAttribute("data-composition-id") && !el.hasAttribute("data-start")) continue;
|
|
@@ -219,6 +231,208 @@ import { randomUUID } from "crypto";
|
|
|
219
231
|
import { existsSync, mkdtempSync, readFileSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
220
232
|
import { tmpdir } from "os";
|
|
221
233
|
import { resolve, join, relative, isAbsolute, basename, posix } from "path";
|
|
234
|
+
|
|
235
|
+
// src/commands/snapshotReview.ts
|
|
236
|
+
var REVIEW_SETTLE_SEC = 0.3;
|
|
237
|
+
var REVIEW_MID_GAP_SEC = 0.5;
|
|
238
|
+
var REVIEW_SEAM_OFFSETS = [-0.2, -0.1, 0, 0.1, 0.2];
|
|
239
|
+
var REVIEW_PHONE_WIDTH = 360;
|
|
240
|
+
var SAME_TIME_SEC = 0.05;
|
|
241
|
+
var EVEN_BEATS = 5;
|
|
242
|
+
function roundMs(value) {
|
|
243
|
+
return Math.round(value * 1e3) / 1e3;
|
|
244
|
+
}
|
|
245
|
+
function sceneId(el, index) {
|
|
246
|
+
return el.id || el.getAttribute("data-composition-id") || el.getAttribute("data-layout-name") || `${el.tagName.toLowerCase()}-${index + 1}`;
|
|
247
|
+
}
|
|
248
|
+
function resolveReviewTimeline(html, durations, duration, compositionId) {
|
|
249
|
+
const bounds = compositionId ? resolveSnapshotCompositionRange(html, durations, compositionId, duration) : [0, duration];
|
|
250
|
+
const { document: document2 } = parseHTML(html);
|
|
251
|
+
const target = compositionId ? Array.from(document2.querySelectorAll("[data-composition-id]")).find(
|
|
252
|
+
(el) => el.getAttribute("data-composition-id") === compositionId
|
|
253
|
+
) : document2.querySelector("[data-composition-id]");
|
|
254
|
+
if (!target) {
|
|
255
|
+
return { window: bounds, scenes: [], beats: [], notes: ["No composition root found."] };
|
|
256
|
+
}
|
|
257
|
+
const resolver = snapshotStartResolver(document2, durations);
|
|
258
|
+
const span = (el) => {
|
|
259
|
+
const start = resolver.resolveStartForElement(el, 0);
|
|
260
|
+
if (!Number.isFinite(start)) return null;
|
|
261
|
+
const length = resolver.resolveDurationForElement(el);
|
|
262
|
+
const from = Math.max(bounds[0], start);
|
|
263
|
+
const to = Math.min(bounds[1], length != null ? start + length : bounds[1]);
|
|
264
|
+
return to > from ? [roundMs(from), roundMs(to)] : null;
|
|
265
|
+
};
|
|
266
|
+
const scenes = [];
|
|
267
|
+
const rows = topLevelElements(toDomNode(target)).filter((node) => {
|
|
268
|
+
const kind = trackKindOf(node).kind;
|
|
269
|
+
return kind === "video" || kind === "graphics";
|
|
270
|
+
});
|
|
271
|
+
rows.forEach((node, index) => {
|
|
272
|
+
const interval = span(node.el);
|
|
273
|
+
if (interval)
|
|
274
|
+
scenes.push({ id: sceneId(node.el, index), start: interval[0], end: interval[1] });
|
|
275
|
+
});
|
|
276
|
+
const beats = [];
|
|
277
|
+
const notes = [];
|
|
278
|
+
for (const el of Array.from(target.querySelectorAll("[data-beat]"))) {
|
|
279
|
+
const name = el.getAttribute("data-beat")?.trim() || sceneId(el, beats.length);
|
|
280
|
+
const timed = el.hasAttribute("data-start") || el.hasAttribute("data-composition-id");
|
|
281
|
+
const interval = timed ? span(el) : null;
|
|
282
|
+
if (!interval) {
|
|
283
|
+
notes.push(`data-beat="${name}" was skipped: give it a data-start so the beat has a time.`);
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
beats.push({ time: settledTime(interval[0], interval[1]), label: `beat:${name}` });
|
|
287
|
+
}
|
|
288
|
+
scenes.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
289
|
+
return { window: bounds, scenes, beats, notes };
|
|
290
|
+
}
|
|
291
|
+
function sceneBeats(scene) {
|
|
292
|
+
const settled = settledTime(scene.start, scene.end);
|
|
293
|
+
const middle = roundMs((scene.start + scene.end) / 2);
|
|
294
|
+
const beats = [{ time: settled, label: scene.id }];
|
|
295
|
+
return middle - settled >= REVIEW_MID_GAP_SEC ? [...beats, { time: middle, label: `${scene.id} mid` }] : beats;
|
|
296
|
+
}
|
|
297
|
+
function settledTime(start, end) {
|
|
298
|
+
return roundMs(Math.min(start + REVIEW_SETTLE_SEC, (start + end) / 2));
|
|
299
|
+
}
|
|
300
|
+
function planReview(timeline, lastFrame) {
|
|
301
|
+
const { window: bounds, scenes } = timeline;
|
|
302
|
+
const notes = [...timeline.notes];
|
|
303
|
+
const clamp = (time) => roundMs(Math.min(Math.max(time, bounds[0]), lastFrame));
|
|
304
|
+
const distinctStarts = mergeBeats(
|
|
305
|
+
scenes.map((scene) => ({ time: scene.start, label: scene.id }))
|
|
306
|
+
);
|
|
307
|
+
const beats = mergeBeats([
|
|
308
|
+
...distinctStarts.length >= 2 ? scenes.flatMap(sceneBeats) : evenBeats(bounds, notes),
|
|
309
|
+
...timeline.beats
|
|
310
|
+
]).map((beat) => ({ ...beat, time: clamp(beat.time) }));
|
|
311
|
+
const seams = seamTimes(scenes, bounds).map((time) => ({
|
|
312
|
+
time,
|
|
313
|
+
...seamSides(scenes, time),
|
|
314
|
+
times: REVIEW_SEAM_OFFSETS.map((offset) => clamp(time + offset))
|
|
315
|
+
}));
|
|
316
|
+
return { window: bounds, scenes, beats, seams, notes };
|
|
317
|
+
}
|
|
318
|
+
function evenBeats(bounds, notes) {
|
|
319
|
+
notes.push(
|
|
320
|
+
`Fewer than two scene starts; ${EVEN_BEATS} beats are spread evenly instead. Time scenes as sub-composition hosts or clips to review each one.`
|
|
321
|
+
);
|
|
322
|
+
const [start, end] = bounds;
|
|
323
|
+
return Array.from({ length: EVEN_BEATS }, (_, index) => {
|
|
324
|
+
const time = roundMs(start + (index + 0.5) / EVEN_BEATS * (end - start));
|
|
325
|
+
return { time, label: `t=${time}` };
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
function mergeBeats(beats) {
|
|
329
|
+
const merged = [];
|
|
330
|
+
for (const beat of [...beats].sort((a, b) => a.time - b.time)) {
|
|
331
|
+
const same = merged.find((entry) => Math.abs(entry.time - beat.time) < SAME_TIME_SEC);
|
|
332
|
+
if (same) same.label = `${same.label} + ${beat.label}`;
|
|
333
|
+
else merged.push({ ...beat });
|
|
334
|
+
}
|
|
335
|
+
return merged;
|
|
336
|
+
}
|
|
337
|
+
function seamTimes(scenes, bounds) {
|
|
338
|
+
const inside = (time) => time > bounds[0] + SAME_TIME_SEC && time < bounds[1] - SAME_TIME_SEC;
|
|
339
|
+
const starts = scenes.map((scene) => scene.start).filter(inside);
|
|
340
|
+
const ends = scenes.map((scene) => scene.end).filter(inside).filter((end) => !starts.some((start) => Math.abs(start - end) < SAME_TIME_SEC));
|
|
341
|
+
const seams = [];
|
|
342
|
+
for (const time of [...starts, ...ends].sort((a, b) => a - b)) {
|
|
343
|
+
if (!seams.some((seam) => Math.abs(seam - time) < SAME_TIME_SEC)) seams.push(time);
|
|
344
|
+
}
|
|
345
|
+
return seams;
|
|
346
|
+
}
|
|
347
|
+
function seamSides(scenes, time) {
|
|
348
|
+
const before = scenes.filter((scene) => scene.start < time - SAME_TIME_SEC && scene.end >= time - SAME_TIME_SEC).sort((a, b) => b.start - a.start)[0];
|
|
349
|
+
const after = scenes.filter((scene) => Math.abs(scene.start - time) < SAME_TIME_SEC).sort((a, b) => a.end - b.end)[0];
|
|
350
|
+
const next = after ?? scenes.find((scene) => scene.start > time);
|
|
351
|
+
return { from: before?.id ?? null, to: next?.id ?? null };
|
|
352
|
+
}
|
|
353
|
+
function pad(index) {
|
|
354
|
+
return String(index).padStart(2, "0");
|
|
355
|
+
}
|
|
356
|
+
function stamp(time) {
|
|
357
|
+
return `${Number(time.toFixed(3))}s`;
|
|
358
|
+
}
|
|
359
|
+
var SEAM_TILE_LABELS = ["cut -0.2", "-0.1", "cut", "+0.1", "+0.2"];
|
|
360
|
+
function reviewFrames(plan) {
|
|
361
|
+
const beats = plan.beats.map((beat, index) => ({
|
|
362
|
+
role: "beat",
|
|
363
|
+
index: index + 1,
|
|
364
|
+
time: beat.time,
|
|
365
|
+
label: beat.label,
|
|
366
|
+
file: `beat-${pad(index + 1)}-at-${stamp(beat.time)}.png`
|
|
367
|
+
}));
|
|
368
|
+
const seams = plan.seams.flatMap(
|
|
369
|
+
(seam, index) => seam.times.map((time, slot) => ({
|
|
370
|
+
role: "seam",
|
|
371
|
+
index: index + 1,
|
|
372
|
+
time,
|
|
373
|
+
label: slot === 2 ? `cut ${seam.from ?? "start"} -> ${seam.to ?? "end"}` : SEAM_TILE_LABELS[slot] ?? "",
|
|
374
|
+
file: `seam-${pad(index + 1)}-${slot + 1}-at-${stamp(time)}.png`
|
|
375
|
+
}))
|
|
376
|
+
);
|
|
377
|
+
return [...beats, ...seams];
|
|
378
|
+
}
|
|
379
|
+
var BEAT_SHEET_PAGE = 16;
|
|
380
|
+
async function writeReviewSheets(dir, frames, written) {
|
|
381
|
+
const { createContactSheet } = await import("./contactSheet-CAGMKI3E.js");
|
|
382
|
+
const { join: join2 } = await import("path");
|
|
383
|
+
const captured = frames.flatMap((frame) => {
|
|
384
|
+
const path = written(frame);
|
|
385
|
+
return path ? [{ frame, path }] : [];
|
|
386
|
+
});
|
|
387
|
+
const beats = captured.filter((entry) => entry.frame.role === "beat");
|
|
388
|
+
const beatLabel = ({ frame }) => `${stamp(frame.time)} ${frame.label}`;
|
|
389
|
+
const pages = async (name, cellWidth, colsFor) => {
|
|
390
|
+
const sheets = [];
|
|
391
|
+
for (let start = 0; start < beats.length; start += BEAT_SHEET_PAGE) {
|
|
392
|
+
const page = beats.slice(start, start + BEAT_SHEET_PAGE);
|
|
393
|
+
const suffix = beats.length > BEAT_SHEET_PAGE ? `-${start / BEAT_SHEET_PAGE + 1}` : "";
|
|
394
|
+
const sheet = await createContactSheet(
|
|
395
|
+
page.map((entry) => entry.path),
|
|
396
|
+
join2(dir, `${name}${suffix}.jpg`),
|
|
397
|
+
{
|
|
398
|
+
cols: colsFor(page.length),
|
|
399
|
+
maxImages: page.length,
|
|
400
|
+
cellWidth,
|
|
401
|
+
labelMode: "custom",
|
|
402
|
+
labels: page.map(beatLabel)
|
|
403
|
+
}
|
|
404
|
+
);
|
|
405
|
+
if (sheet) sheets.push(sheet);
|
|
406
|
+
}
|
|
407
|
+
return sheets;
|
|
408
|
+
};
|
|
409
|
+
const seams = [];
|
|
410
|
+
const seamNumbers = [
|
|
411
|
+
...new Set(captured.filter((e) => e.frame.role === "seam").map((e) => e.frame.index))
|
|
412
|
+
];
|
|
413
|
+
for (const index of seamNumbers) {
|
|
414
|
+
const strip = captured.filter((e) => e.frame.role === "seam" && e.frame.index === index);
|
|
415
|
+
const sheet = await createContactSheet(
|
|
416
|
+
strip.map((entry) => entry.path),
|
|
417
|
+
join2(dir, `review-seam-${pad(index)}.jpg`),
|
|
418
|
+
{
|
|
419
|
+
cols: strip.length,
|
|
420
|
+
maxImages: strip.length,
|
|
421
|
+
cellWidth: 384,
|
|
422
|
+
labelMode: "custom",
|
|
423
|
+
labels: strip.map(({ frame }) => `${stamp(frame.time)} ${frame.label}`)
|
|
424
|
+
}
|
|
425
|
+
);
|
|
426
|
+
if (sheet) seams.push(sheet);
|
|
427
|
+
}
|
|
428
|
+
return {
|
|
429
|
+
beats: await pages("review-beats", 480, (count) => count <= 3 ? count : count <= 9 ? 3 : 4),
|
|
430
|
+
seams,
|
|
431
|
+
phone: await pages("review-phone", REVIEW_PHONE_WIDTH, (count) => Math.min(4, count))
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/commands/snapshot.ts
|
|
222
436
|
function orbitStageSource() {
|
|
223
437
|
return `function(cam) {
|
|
224
438
|
var root = document.querySelector("[data-composition-id]")
|
|
@@ -479,7 +693,8 @@ function serveCapturePage(projectDir, html, proxy) {
|
|
|
479
693
|
return serveStaticProjectHtml(projectDir, html, void 0, [], proxy === true);
|
|
480
694
|
}
|
|
481
695
|
async function captureSnapshots(projectDir, opts) {
|
|
482
|
-
const
|
|
696
|
+
const log = opts.log ?? ((message) => console.log(message));
|
|
697
|
+
const { bundleWithLocalizedFonts } = await import("./bundleWithLocalizedFonts-67MLTHKM.js");
|
|
483
698
|
const capture = await captureArtifactRevision(projectDir).catch(warnSnapshotsNotRecorded);
|
|
484
699
|
const invocation = randomUUID();
|
|
485
700
|
const artifacts = [];
|
|
@@ -487,6 +702,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
487
702
|
const warnings = [];
|
|
488
703
|
let completed = false;
|
|
489
704
|
const numFrames = opts.frames ?? 5;
|
|
705
|
+
let review;
|
|
706
|
+
let reviewList;
|
|
707
|
+
const reviewPaths = /* @__PURE__ */ new Map();
|
|
490
708
|
const html = await bundleWithLocalizedFonts(projectDir);
|
|
491
709
|
const server = await serveCapturePage(projectDir, html, opts.autoProxy);
|
|
492
710
|
const savedPaths = [];
|
|
@@ -518,10 +736,10 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
518
736
|
const parts = [`${fontReport.loaded.length} loaded`];
|
|
519
737
|
if (fontReport.errored.length > 0) parts.push(`${fontReport.errored.length} failed`);
|
|
520
738
|
if (fontReport.unused.length > 0) parts.push(`${fontReport.unused.length} unused`);
|
|
521
|
-
|
|
739
|
+
log(`
|
|
522
740
|
${c.dim("Fonts:")} ${parts.join(", ")}`);
|
|
523
741
|
if (fontReport.errored.length > 0) {
|
|
524
|
-
|
|
742
|
+
log(` ${c.error("Fonts FAILED:")} ${fontReport.errored.join(", ")}`);
|
|
525
743
|
}
|
|
526
744
|
}
|
|
527
745
|
if (fontReport.errored.length)
|
|
@@ -537,19 +755,20 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
537
755
|
return 0;
|
|
538
756
|
});
|
|
539
757
|
if (duration <= 0 && !opts.at?.length) {
|
|
540
|
-
return [];
|
|
758
|
+
return { paths: [] };
|
|
541
759
|
}
|
|
760
|
+
const readTiming = () => page.evaluate(() => ({
|
|
761
|
+
html: document.documentElement.outerHTML,
|
|
762
|
+
durations: Object.fromEntries(
|
|
763
|
+
Object.entries(window.__timelines ?? {}).map(([id, timeline]) => [
|
|
764
|
+
id,
|
|
765
|
+
Number(timeline.duration?.())
|
|
766
|
+
])
|
|
767
|
+
)
|
|
768
|
+
}));
|
|
542
769
|
let range = opts.range;
|
|
543
|
-
if (opts.composition) {
|
|
544
|
-
const timing = await
|
|
545
|
-
html: document.documentElement.outerHTML,
|
|
546
|
-
durations: Object.fromEntries(
|
|
547
|
-
Object.entries(window.__timelines ?? {}).map(([id, timeline]) => [
|
|
548
|
-
id,
|
|
549
|
-
Number(timeline.duration?.())
|
|
550
|
-
])
|
|
551
|
-
)
|
|
552
|
-
}));
|
|
770
|
+
if (opts.composition && !opts.review) {
|
|
771
|
+
const timing = await readTiming();
|
|
553
772
|
range = resolveSnapshotCompositionRange(
|
|
554
773
|
timing.html,
|
|
555
774
|
timing.durations,
|
|
@@ -557,7 +776,18 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
557
776
|
duration
|
|
558
777
|
);
|
|
559
778
|
}
|
|
560
|
-
|
|
779
|
+
if (opts.review) {
|
|
780
|
+
const timing = await readTiming();
|
|
781
|
+
const timeline = resolveReviewTimeline(
|
|
782
|
+
timing.html,
|
|
783
|
+
timing.durations,
|
|
784
|
+
duration,
|
|
785
|
+
opts.composition
|
|
786
|
+
);
|
|
787
|
+
review = planReview(timeline, Math.min(timeline.window[1], duration) - 1 / 30);
|
|
788
|
+
reviewList = reviewFrames(review);
|
|
789
|
+
}
|
|
790
|
+
const { times: positions, appendedTail } = reviewList ? { times: reviewList.map((frame) => frame.time), appendedTail: false } : range ? {
|
|
561
791
|
times: sampleSnapshotRange(range, numFrames, duration, !!opts.composition),
|
|
562
792
|
appendedTail: false
|
|
563
793
|
} : computeSnapshotTimes(duration, {
|
|
@@ -566,11 +796,15 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
566
796
|
includeEnd: opts.includeEnd
|
|
567
797
|
});
|
|
568
798
|
if (range)
|
|
569
|
-
|
|
799
|
+
log(
|
|
570
800
|
` Sampling ${positions.length} frames within ${range[0]}\u2013${range[1]}s${opts.composition ? ` (composition ${opts.composition})` : ""}`
|
|
571
801
|
);
|
|
802
|
+
if (review)
|
|
803
|
+
log(
|
|
804
|
+
` Review: ${review.beats.length} beat(s) and ${review.seams.length} seam(s) within ${review.window[0]}\u2013${review.window[1]}s${opts.composition ? ` (composition ${opts.composition})` : ""}`
|
|
805
|
+
);
|
|
572
806
|
if (appendedTail) {
|
|
573
|
-
|
|
807
|
+
log(
|
|
574
808
|
` ${c.dim(`Note: added an end-of-timeline frame at ${positions[positions.length - 1].toFixed(2)}s. Short beats between your --at times may still be skipped \u2014 pass them explicitly.`)}`
|
|
575
809
|
);
|
|
576
810
|
}
|
|
@@ -592,7 +826,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
592
826
|
let syncVideoFrameVisibility = null;
|
|
593
827
|
let extractMediaMetadata = null;
|
|
594
828
|
try {
|
|
595
|
-
const engine = await import("./src-
|
|
829
|
+
const engine = await import("./src-RZ574OKP.js");
|
|
596
830
|
injectVideoFramesBatch = engine.injectVideoFramesBatch;
|
|
597
831
|
syncVideoFrameVisibility = engine.syncVideoFrameVisibility;
|
|
598
832
|
extractMediaMetadata = engine.extractMediaMetadata;
|
|
@@ -730,7 +964,8 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
730
964
|
await recaptureSnapshotComposite(page);
|
|
731
965
|
const timeLabel = formatSnapshotTimestamp(time);
|
|
732
966
|
const slot = opts.keep ? `at-${timeLabel}` : `${String(i).padStart(2, "0")}-at-${timeLabel}`;
|
|
733
|
-
const
|
|
967
|
+
const reviewFrame = reviewList?.[i];
|
|
968
|
+
const filename = reviewFrame ? reviewFrame.file : opts.keep ? `${slot}.png` : `frame-${slot}.png`;
|
|
734
969
|
const framePath = join(snapshotDir, filename);
|
|
735
970
|
let crop;
|
|
736
971
|
if (opts.zoom) {
|
|
@@ -769,9 +1004,11 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
769
1004
|
zoom: opts.zoom,
|
|
770
1005
|
zoomScale: opts.zoom ? opts.zoomScale ?? DEFAULT_ZOOM_SCALE : 1,
|
|
771
1006
|
angle: opts.angle,
|
|
772
|
-
browserGpuMode: opts.browserGpuMode
|
|
1007
|
+
browserGpuMode: opts.browserGpuMode,
|
|
1008
|
+
...reviewFrame ? { review: { role: reviewFrame.role, label: reviewFrame.label } } : {}
|
|
773
1009
|
}
|
|
774
1010
|
});
|
|
1011
|
+
if (reviewFrame) reviewPaths.set(reviewFrame, framePath);
|
|
775
1012
|
if (opts.against) {
|
|
776
1013
|
const refPng = await extractVideoFrameToBuffer(opts.against, time);
|
|
777
1014
|
if (!refPng) {
|
|
@@ -807,20 +1044,32 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
807
1044
|
artifacts,
|
|
808
1045
|
opts.zoom,
|
|
809
1046
|
warnings,
|
|
810
|
-
completed
|
|
1047
|
+
completed,
|
|
1048
|
+
log
|
|
811
1049
|
) : false;
|
|
812
1050
|
if (!recorded) {
|
|
813
1051
|
const paths = [...replaced, ...artifacts.map((artifact) => artifact.image)];
|
|
814
1052
|
if (paths.length > 0) await forgetRecordedArtifacts(projectDir, paths).catch(() => void 0);
|
|
815
1053
|
}
|
|
816
1054
|
}
|
|
817
|
-
return
|
|
1055
|
+
return {
|
|
1056
|
+
paths: savedPaths,
|
|
1057
|
+
...review && reviewList ? {
|
|
1058
|
+
review: {
|
|
1059
|
+
plan: review,
|
|
1060
|
+
frames: reviewList.flatMap((frame) => {
|
|
1061
|
+
const path = reviewPaths.get(frame);
|
|
1062
|
+
return path ? [{ ...frame, path }] : [];
|
|
1063
|
+
})
|
|
1064
|
+
}
|
|
1065
|
+
} : {}
|
|
1066
|
+
};
|
|
818
1067
|
}
|
|
819
1068
|
function warnSnapshotsNotRecorded(error) {
|
|
820
1069
|
console.warn(` ${c.warn("\u26A0")} Snapshots were not recorded: ${normalizeErrorMessage(error)}`);
|
|
821
1070
|
return void 0;
|
|
822
1071
|
}
|
|
823
|
-
async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, warnings, completed) {
|
|
1072
|
+
async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, warnings, completed, log) {
|
|
824
1073
|
const records = await recordArtifacts(
|
|
825
1074
|
projectDir,
|
|
826
1075
|
capture,
|
|
@@ -833,10 +1082,65 @@ async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, war
|
|
|
833
1082
|
).catch(warnSnapshotsNotRecorded);
|
|
834
1083
|
const record = records?.[0];
|
|
835
1084
|
if (!record) return false;
|
|
836
|
-
|
|
837
|
-
|
|
1085
|
+
log(` Revision: ${record.revision ?? "none"} (${record.attribution})`);
|
|
1086
|
+
log(` State: ${join(projectDir, ".hyperframes", "video-state.json")}`);
|
|
838
1087
|
return true;
|
|
839
1088
|
}
|
|
1089
|
+
function snapshotEnvelope(projectDir, outputDir, captured, extra) {
|
|
1090
|
+
const review = captured.review;
|
|
1091
|
+
const frames = review ? review.frames.map((frame) => ({
|
|
1092
|
+
path: frame.path,
|
|
1093
|
+
time: frame.time,
|
|
1094
|
+
role: frame.role,
|
|
1095
|
+
label: frame.label
|
|
1096
|
+
})) : captured.paths.map((path) => ({ path: resolve(projectDir, path), time: timeFromName(path) }));
|
|
1097
|
+
return {
|
|
1098
|
+
ok: true,
|
|
1099
|
+
outputDir,
|
|
1100
|
+
frames,
|
|
1101
|
+
contactSheets: extra.contactSheets.map((sheet) => resolve(sheet)),
|
|
1102
|
+
...extra.describedPath ? { descriptions: extra.describedPath } : {},
|
|
1103
|
+
...review ? {
|
|
1104
|
+
review: {
|
|
1105
|
+
window: review.plan.window,
|
|
1106
|
+
scenes: review.plan.scenes,
|
|
1107
|
+
beats: review.plan.beats.map((beat, index) => ({
|
|
1108
|
+
...beat,
|
|
1109
|
+
path: review.frames.find(
|
|
1110
|
+
(frame) => frame.role === "beat" && frame.index === index + 1
|
|
1111
|
+
)?.path
|
|
1112
|
+
})),
|
|
1113
|
+
seams: review.plan.seams.map((seam, index) => ({
|
|
1114
|
+
...seam,
|
|
1115
|
+
paths: review.frames.filter((frame) => frame.role === "seam" && frame.index === index + 1).map((frame) => frame.path),
|
|
1116
|
+
sheet: extra.reviewSheets?.seams[index]
|
|
1117
|
+
})),
|
|
1118
|
+
sheets: extra.reviewSheets ?? { beats: [], seams: [], phone: [] },
|
|
1119
|
+
notes: review.plan.notes
|
|
1120
|
+
}
|
|
1121
|
+
} : {}
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
function timeFromName(path) {
|
|
1125
|
+
const match = /at-([\d.]+)s\.png$/.exec(path);
|
|
1126
|
+
return match ? Number(match[1]) : null;
|
|
1127
|
+
}
|
|
1128
|
+
function printReview(review, sheets, log) {
|
|
1129
|
+
const beats = review.plan.beats.map(
|
|
1130
|
+
(beat) => `${formatSnapshotTimestamp(beat.time)} ${beat.label}`
|
|
1131
|
+
);
|
|
1132
|
+
log(` Beat sheet (settled frame per scene): ${sheets.beats.join(", ") || "none"}`);
|
|
1133
|
+
log(` ${c.dim(beats.join(" \xB7 "))}`);
|
|
1134
|
+
review.plan.seams.forEach((seam, index) => {
|
|
1135
|
+
const sides = `${seam.from ?? "start"} -> ${seam.to ?? "end"}`;
|
|
1136
|
+
const strip = sheets.seams[index] ?? "not written";
|
|
1137
|
+
log(` Seam ${index + 1} at ${formatSnapshotTimestamp(seam.time)} (${sides}): ${strip}`);
|
|
1138
|
+
});
|
|
1139
|
+
log(
|
|
1140
|
+
` Phone sheet (beats at ${REVIEW_PHONE_WIDTH} px wide): ${sheets.phone.join(", ") || "none"}`
|
|
1141
|
+
);
|
|
1142
|
+
for (const note of review.plan.notes) log(` ${c.dim(note)}`);
|
|
1143
|
+
}
|
|
840
1144
|
var snapshot_default = defineCommand({
|
|
841
1145
|
meta: {
|
|
842
1146
|
name: "snapshot",
|
|
@@ -902,6 +1206,16 @@ var snapshot_default = defineCommand({
|
|
|
902
1206
|
type: "string",
|
|
903
1207
|
description: "Reference video (e.g. footage being rebuilt): also save its frame at each captured time and a render|reference pair sheet"
|
|
904
1208
|
},
|
|
1209
|
+
review: {
|
|
1210
|
+
type: "boolean",
|
|
1211
|
+
description: "Capture the review set instead of evenly spaced frames: each scene at its start + 0.3 s and its middle, and each data-beat at its start + 0.3 s, on review-beats.jpg, a 5-frame strip around every cut (review-seam-NN.jpg), and the beat frames at phone width (review-phone.jpg). Scopes to --composition; ignores --frames.",
|
|
1212
|
+
default: false
|
|
1213
|
+
},
|
|
1214
|
+
json: {
|
|
1215
|
+
type: "boolean",
|
|
1216
|
+
description: "Print one JSON envelope (paths, times, sheets; the review plan under --review)",
|
|
1217
|
+
default: false
|
|
1218
|
+
},
|
|
905
1219
|
describe: {
|
|
906
1220
|
type: "string",
|
|
907
1221
|
description: "Gemini vision frame analysis. Runs by default when GEMINI_API_KEY is set. Pass a custom question (e.g. --describe 'Is the logo visible in every beat?') to override the default prompt, or --describe false to opt out."
|
|
@@ -918,8 +1232,22 @@ var snapshot_default = defineCommand({
|
|
|
918
1232
|
}
|
|
919
1233
|
},
|
|
920
1234
|
async run({ args }) {
|
|
1235
|
+
const asJson = args.json === true;
|
|
1236
|
+
const log = (message) => asJson ? console.error(message) : console.log(message);
|
|
1237
|
+
const fail = (message) => {
|
|
1238
|
+
if (asJson) console.log(JSON.stringify(withMeta({ ok: false, error: message }), null, 2));
|
|
1239
|
+
else log(message);
|
|
1240
|
+
failCommand();
|
|
1241
|
+
};
|
|
921
1242
|
if ([args.at, args.range, args.composition].filter((value) => value !== void 0).length > 1)
|
|
922
1243
|
throw new Error("Use only one of --at, --range, or --composition");
|
|
1244
|
+
const reviewMode = args.review === true;
|
|
1245
|
+
if (reviewMode) {
|
|
1246
|
+
const clash = ["at", "range", "zoom", "keep", "against"].find(
|
|
1247
|
+
(flag) => args[flag] !== void 0 && args[flag] !== false
|
|
1248
|
+
);
|
|
1249
|
+
if (clash) throw new Error(`--review picks its own frames; drop --${clash}`);
|
|
1250
|
+
}
|
|
923
1251
|
const frames = parseInt(args.frames, 10) || 5;
|
|
924
1252
|
const range = args.range === void 0 ? void 0 : parseSnapshotRange(String(args.range));
|
|
925
1253
|
const composition = args.composition === void 0 ? void 0 : String(args.composition).trim();
|
|
@@ -928,28 +1256,32 @@ var snapshot_default = defineCommand({
|
|
|
928
1256
|
const lintResult = await lintProject(project.dir);
|
|
929
1257
|
if (hasDefinitiveEntryMismatch(lintResult)) {
|
|
930
1258
|
const candidate = definitiveEntryMismatchComposition(lintResult);
|
|
931
|
-
|
|
1259
|
+
log("");
|
|
932
1260
|
for (const line of formatLintFindings(lintResult, { errorsFirst: true })) {
|
|
933
|
-
|
|
1261
|
+
log(line);
|
|
934
1262
|
}
|
|
935
|
-
|
|
936
|
-
|
|
1263
|
+
log("");
|
|
1264
|
+
log(c.error(" Aborting snapshot because the default index.html entry is blank."));
|
|
937
1265
|
if (candidate && posix.basename(candidate) === "index.html") {
|
|
938
1266
|
const candidateDir = posix.dirname(candidate);
|
|
939
1267
|
const target = `<project>/${candidateDir}`;
|
|
940
|
-
|
|
1268
|
+
log(
|
|
941
1269
|
c.dim(
|
|
942
1270
|
` Move or mount the authored file, or snapshot its directory directly: hyperframes snapshot ${target}. Only use the directory form when its assets are self-contained under that directory; otherwise mount it from the project root.`
|
|
943
1271
|
)
|
|
944
1272
|
);
|
|
945
1273
|
} else if (candidate) {
|
|
946
|
-
|
|
1274
|
+
log(
|
|
947
1275
|
c.dim(
|
|
948
1276
|
` Move or mount ${candidate} as a project index.html before snapshotting; snapshot accepts project directories, not individual HTML files.`
|
|
949
1277
|
)
|
|
950
1278
|
);
|
|
951
1279
|
}
|
|
952
|
-
|
|
1280
|
+
log("");
|
|
1281
|
+
if (asJson) {
|
|
1282
|
+
const error = "The default index.html entry is blank; see the lint findings on stderr.";
|
|
1283
|
+
console.log(JSON.stringify(withMeta({ ok: false, error }), null, 2));
|
|
1284
|
+
}
|
|
953
1285
|
failCommand();
|
|
954
1286
|
}
|
|
955
1287
|
const timeout = parseInt(args.timeout, 10) || 5e3;
|
|
@@ -960,20 +1292,18 @@ var snapshot_default = defineCommand({
|
|
|
960
1292
|
const zoomTarget = args.zoom ? parseZoomTarget(String(args.zoom)) : void 0;
|
|
961
1293
|
const zoomScale = parseZoomScale(args["zoom-scale"]);
|
|
962
1294
|
const against = args.against ? resolve(String(args.against)) : void 0;
|
|
963
|
-
if (against && !existsSync(against))
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
}
|
|
967
|
-
const label = atTimestamps ? `${atTimestamps.length} frames at [${atTimestamps.map(formatSnapshotTimestamp).join(", ")}]` : `${frames} frames`;
|
|
1295
|
+
if (against && !existsSync(against))
|
|
1296
|
+
fail(`${c.error("\u2717")} --against video not found: ${against}`);
|
|
1297
|
+
const label = reviewMode ? "review frames (beats, seams, phone)" : atTimestamps ? `${atTimestamps.length} frames at [${atTimestamps.map(formatSnapshotTimestamp).join(", ")}]` : `${frames} frames`;
|
|
968
1298
|
const angleLabel = camera && (camera.yaw !== 0 || camera.pitch !== 0) ? ` ${c.dim(`(angle yaw ${camera.yaw}\xB0 pitch ${camera.pitch}\xB0)`)}` : "";
|
|
969
|
-
|
|
1299
|
+
log(`${c.accent("\u25C6")} Capturing ${label} from ${c.accent(project.name)}${angleLabel}`);
|
|
970
1300
|
let managedSnapshotDir;
|
|
971
1301
|
try {
|
|
972
1302
|
const snapshotDir = args.output ? resolve(String(args.output)) : artifactDirectory(project.dir, "snapshots");
|
|
973
1303
|
if (!args.output) managedSnapshotDir = snapshotDir;
|
|
974
1304
|
if (args.output) retainSnapshotOutput(project.dir, snapshotDir);
|
|
975
1305
|
await withProjectLock(project.dir, "snapshot", async () => {
|
|
976
|
-
const
|
|
1306
|
+
const captured = await captureSnapshots(project.dir, {
|
|
977
1307
|
frames,
|
|
978
1308
|
range,
|
|
979
1309
|
composition,
|
|
@@ -987,53 +1317,71 @@ var snapshot_default = defineCommand({
|
|
|
987
1317
|
autoProxy: args.proxy,
|
|
988
1318
|
browserGpuMode: resolveLocalBrowserGpuMode(args["browser-gpu"]),
|
|
989
1319
|
against,
|
|
990
|
-
keep: args.keep === true
|
|
1320
|
+
keep: args.keep === true,
|
|
1321
|
+
review: reviewMode,
|
|
1322
|
+
log
|
|
991
1323
|
});
|
|
1324
|
+
const paths = captured.paths;
|
|
992
1325
|
reportArtifacts(
|
|
993
1326
|
"snapshot",
|
|
994
1327
|
"frame",
|
|
995
1328
|
paths.map((path) => resolve(project.dir, path))
|
|
996
1329
|
);
|
|
997
1330
|
if (paths.length === 0) {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
${c.error("\u2717")} Could not determine composition duration \u2014 no frames captured`
|
|
1001
|
-
);
|
|
1002
|
-
failCommand();
|
|
1331
|
+
fail(`
|
|
1332
|
+
${c.error("\u2717")} Could not determine composition duration \u2014 no frames captured`);
|
|
1003
1333
|
}
|
|
1004
|
-
|
|
1334
|
+
log(`
|
|
1005
1335
|
${c.success("\u25C7")} ${paths.length} snapshots saved to ${snapshotDir}`);
|
|
1006
1336
|
for (const p of paths) {
|
|
1007
|
-
|
|
1337
|
+
log(` ${p}`);
|
|
1008
1338
|
}
|
|
1009
1339
|
if (against) {
|
|
1010
|
-
|
|
1340
|
+
log(
|
|
1011
1341
|
` ${c.dim("ref-*.png + pair-*.jpg")} beside each frame (reference frame, render | reference sheet)`
|
|
1012
1342
|
);
|
|
1013
1343
|
}
|
|
1344
|
+
let contactSheets = [];
|
|
1345
|
+
let reviewSheets;
|
|
1014
1346
|
try {
|
|
1015
1347
|
const { createSnapshotContactSheet } = await import("./contactSheet-CAGMKI3E.js");
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1348
|
+
if (captured.review) {
|
|
1349
|
+
const written = new Map(
|
|
1350
|
+
captured.review.frames.map((frame) => [frame.file, frame.path])
|
|
1351
|
+
);
|
|
1352
|
+
reviewSheets = await writeReviewSheets(
|
|
1353
|
+
snapshotDir,
|
|
1354
|
+
captured.review.frames,
|
|
1355
|
+
(frame) => written.get(frame.file) ?? null
|
|
1356
|
+
);
|
|
1357
|
+
contactSheets = [...reviewSheets.beats, ...reviewSheets.seams, ...reviewSheets.phone];
|
|
1358
|
+
printReview(captured.review, reviewSheets, log);
|
|
1359
|
+
} else if (args.keep !== true) {
|
|
1360
|
+
contactSheets = await createSnapshotContactSheet(
|
|
1361
|
+
snapshotDir,
|
|
1362
|
+
join(snapshotDir, "contact-sheet.jpg")
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
reportArtifacts("snapshot", "contact-sheet", contactSheets);
|
|
1366
|
+
if (!captured.review) {
|
|
1367
|
+
for (const sheet of contactSheets) {
|
|
1368
|
+
log(` ${resolve(sheet)} (grid view for AI review)`);
|
|
1369
|
+
}
|
|
1023
1370
|
}
|
|
1024
1371
|
} catch (err) {
|
|
1025
1372
|
console.warn(
|
|
1026
1373
|
` ${c.warn("\u26A0")} Contact sheet skipped: ${normalizeErrorMessage(err)}. Individual snapshot PNGs are still available.`
|
|
1027
1374
|
);
|
|
1028
1375
|
}
|
|
1376
|
+
let describedPath;
|
|
1029
1377
|
if (describeArg !== null) {
|
|
1030
1378
|
try {
|
|
1031
1379
|
const geminiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
1032
1380
|
if (!geminiKey) {
|
|
1033
1381
|
if (args.describe !== void 0)
|
|
1034
|
-
|
|
1382
|
+
log(` ${c.dim("--describe: GEMINI_API_KEY not set, skipping")}`);
|
|
1035
1383
|
} else if (paths.length > 0) {
|
|
1036
|
-
|
|
1384
|
+
log(` ${c.dim("Describing frames with Gemini vision...")}`);
|
|
1037
1385
|
const { GoogleGenAI } = await loadOptionalPackage("@google/genai", "--describe");
|
|
1038
1386
|
const ai = new GoogleGenAI({ apiKey: geminiKey });
|
|
1039
1387
|
const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
|
|
@@ -1101,17 +1449,28 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${snapshotDir}`);
|
|
|
1101
1449
|
}
|
|
1102
1450
|
const descPath = join(snapshotDir, "descriptions.md");
|
|
1103
1451
|
writeFileSync(descPath, descriptions.join("\n"));
|
|
1104
|
-
|
|
1452
|
+
describedPath = descPath;
|
|
1453
|
+
log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
|
|
1105
1454
|
}
|
|
1106
1455
|
} catch (descErr) {
|
|
1107
1456
|
const msg = normalizeErrorMessage(descErr);
|
|
1108
|
-
|
|
1457
|
+
log(` ${c.dim(`--describe failed: ${msg}`)}`);
|
|
1109
1458
|
}
|
|
1110
1459
|
}
|
|
1460
|
+
if (asJson) {
|
|
1461
|
+
const envelope = snapshotEnvelope(project.dir, snapshotDir, captured, {
|
|
1462
|
+
contactSheets,
|
|
1463
|
+
reviewSheets,
|
|
1464
|
+
describedPath
|
|
1465
|
+
});
|
|
1466
|
+
console.log(JSON.stringify(withMeta(envelope), null, 2));
|
|
1467
|
+
}
|
|
1111
1468
|
});
|
|
1112
1469
|
} catch (err) {
|
|
1470
|
+
if (err instanceof CliRuntimeError && err.result.presented) throw err;
|
|
1113
1471
|
const msg = normalizeErrorMessage(err);
|
|
1114
|
-
console.error
|
|
1472
|
+
if (asJson) console.log(JSON.stringify(withMeta({ ok: false, error: msg }), null, 2));
|
|
1473
|
+
else console.error(`
|
|
1115
1474
|
${c.error("\u2717")} Snapshot failed: ${msg}`);
|
|
1116
1475
|
failCommand();
|
|
1117
1476
|
} finally {
|