hyperframes 0.8.183 → 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-HW3ZGR36.js → add-ODTNPRGG.js} +14 -14
- package/dist/{agentPromptGenerator-VIIPZCJ3.js → agentPromptGenerator-KYO5MKTW.js} +1 -1
- package/dist/{animatedGifPrep-EPLN37ZN.js → animatedGifPrep-PEP5GWOJ.js} +10 -9
- package/dist/api.js +18 -17
- package/dist/{asset-TOASKL3Z.js → asset-EZG42XPA.js} +2 -2
- package/dist/{assetCataloger-PZN5HYG2.js → assetCataloger-OHAJFCA7.js} +10 -9
- package/dist/{audio-F5OIQVJO.js → audio-65R4T74I.js} +18 -16
- package/dist/{auth-YVQLRS3T.js → auth-VP2SIZFN.js} +1 -1
- package/dist/{autoUpdate-EG4ZFW4D.js → autoUpdate-RVSUX4SS.js} +2 -2
- package/dist/{backgroundChecks-WINNQVR2.js → backgroundChecks-LEHK74NS.js} +3 -3
- package/dist/backgroundChecksWorker.js +3 -3
- package/dist/{batchRender-PASZTMEE.js → batchRender-3X6CL7PK.js} +5 -5
- package/dist/{beats-KGIOEBLW.js → beats-66VPQLSC.js} +6 -6
- package/dist/{benchmark-ZNY2L7HN.js → benchmark-PBJVTOJP.js} +10 -10
- package/dist/{browser-REAO7RU4.js → browser-TPL5MWGC.js} +3 -3
- package/dist/{bundleWithLocalizedFonts-OAYLYC4W.js → bundleWithLocalizedFonts-67MLTHKM.js} +2 -2
- package/dist/{capture-WOSF276U.js → capture-F3GNMRZM.js} +14 -13
- package/dist/{capture-IK6GWQDD.js → capture-YYRE7EV3.js} +2 -2
- package/dist/{captureCompositionFrame-DDZNKYRE.js → captureCompositionFrame-PXV2ISHD.js} +14 -13
- package/dist/{catalog-AKTXS7OJ.js → catalog-6SDD3OHF.js} +14 -14
- package/dist/{catch-up-O3VZMPVE.js → catch-up-CWIVA5VG.js} +4 -4
- package/dist/{check-6E46NIWI.js → check-YQ6REK2S.js} +35 -34
- package/dist/{checkBrowser-UNZHQFNH.js → checkBrowser-5XZCBRXM.js} +32 -31
- package/dist/{chunk-TOHA5NAU.js → chunk-2TAS5O4P.js} +56 -11
- package/dist/{chunk-3Q47QC46.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-GAGMLVCV.js → chunk-4CTNDBE3.js} +2 -2
- package/dist/{chunk-CGK4XZ2J.js → chunk-55YELV7B.js} +1 -1
- package/dist/{chunk-TJB4GAV6.js → chunk-5GUKZRQN.js} +1 -1
- package/dist/{chunk-J4L5TPLS.js → chunk-5UDRPPN2.js} +48 -6
- package/dist/{chunk-SAQYJLI6.js → chunk-6ASIXMFP.js} +1 -1
- package/dist/{chunk-GPE3WWTO.js → chunk-6GPR3G3C.js} +14 -11
- package/dist/{chunk-MIZDJVPZ.js → chunk-6RIZY7OP.js} +1 -1
- package/dist/{chunk-5CS4T6C6.js → chunk-7L37AB57.js} +1 -1
- package/dist/{chunk-VH5KESLX.js → chunk-7PS6RVWD.js} +1 -1
- package/dist/{chunk-U5YVWG5W.js → chunk-7RAY4WZP.js} +3 -3
- package/dist/{chunk-COTLNID2.js → chunk-A6QCO474.js} +5 -5
- package/dist/{chunk-YMS5FOMC.js → chunk-B2A56S5C.js} +1 -1
- package/dist/{chunk-4FQKS7BJ.js → chunk-BH7TTIPN.js} +11 -13
- package/dist/{chunk-LBWRQ4XA.js → chunk-BRAPBUPQ.js} +1 -1
- package/dist/{chunk-IC2WYONA.js → chunk-CX3USX23.js} +3 -3
- package/dist/{chunk-ITSLKUQM.js → chunk-D42NU3DZ.js} +1 -1
- package/dist/{chunk-Q6UYKWBG.js → chunk-EMAWIZ54.js} +481 -36
- package/dist/{chunk-ZFO3A3QL.js → chunk-EMSDWBG3.js} +2 -2
- package/dist/{chunk-KRFAX5JK.js → chunk-ESBMUZXZ.js} +1 -1
- package/dist/{chunk-CAHTO62O.js → chunk-F3OPUWQX.js} +7 -7
- package/dist/{chunk-R6OV4J4K.js → chunk-FX6RUJUY.js} +3 -3
- package/dist/{chunk-F6WHPHLF.js → chunk-G2UANIDX.js} +1 -1
- package/dist/{chunk-DEORFAWP.js → chunk-H5SM5PJI.js} +1 -1
- package/dist/{chunk-5OGDBU4G.js → chunk-H6UY725W.js} +2 -2
- package/dist/{chunk-K2Z5DZBS.js → chunk-HDIRZGK4.js} +1 -1
- package/dist/{chunk-TXGZZKDF.js → chunk-HHSJJFVM.js} +2 -2
- package/dist/{chunk-VDJO4DJ7.js → chunk-HXUTX5GR.js} +3 -3
- package/dist/{chunk-73LTCCZI.js → chunk-I3IH5MV5.js} +19 -23
- package/dist/{chunk-3OLIGYWN.js → chunk-I45HL3VP.js} +3 -3
- package/dist/{chunk-TYXH3EKP.js → chunk-I5JRXMCV.js} +16 -1
- package/dist/{chunk-RZXUQR42.js → chunk-I7QMXZSB.js} +2 -2
- package/dist/{chunk-XOVHO3TT.js → chunk-IDFNKFPL.js} +7 -7
- package/dist/{chunk-QX4GGPMY.js → chunk-IDGLGXPA.js} +1 -1
- package/dist/{chunk-5MBLWFLM.js → chunk-IPDKZ5IN.js} +33 -6
- package/dist/{chunk-ANR6WOC3.js → chunk-ISTRDGIX.js} +1 -1
- package/dist/{chunk-4UFJWRHG.js → chunk-IVEFOUZI.js} +211 -83
- package/dist/chunk-IZCW2NKT.js +29 -0
- package/dist/{chunk-X3IA5RYH.js → chunk-J36JVBLR.js} +9 -2
- package/dist/{chunk-Z4R35NJS.js → chunk-J5XEZ24I.js} +3 -3
- package/dist/{chunk-OH56PXFH.js → chunk-K2ZKXTVL.js} +1 -1
- package/dist/{chunk-ATMDOUNN.js → chunk-K73RJB23.js} +2 -2
- package/dist/{chunk-NZ3BE2QE.js → chunk-KQ4JEJLF.js} +10 -10
- package/dist/{chunk-VFBAKPRC.js → chunk-KROXPHXX.js} +9 -3
- package/dist/{chunk-QGOYNPQT.js → chunk-LLFQA7XF.js} +48 -5
- package/dist/chunk-LLMSX6V6.js +17 -0
- package/dist/{chunk-XR5BSEUF.js → chunk-LYKSTRAY.js} +3 -3
- package/dist/{chunk-UNOSCGBG.js → chunk-OAG47RE6.js} +1 -1
- package/dist/{chunk-O7N3A7PE.js → chunk-PHMBMOXF.js} +1 -1
- package/dist/{chunk-BP4VNTZL.js → chunk-PMMQRJDE.js} +1 -1
- package/dist/{chunk-ADDHW2FS.js → chunk-Q447CX26.js} +82 -12
- package/dist/{chunk-WT4PYV2J.js → chunk-Q47FAYYK.js} +202 -55
- package/dist/{chunk-AKFADCMS.js → chunk-RTBSA3EA.js} +1 -1
- package/dist/{chunk-VAK7A2N6.js → chunk-RUEGYANA.js} +11 -11
- package/dist/{chunk-OYLO6TYK.js → chunk-RUOG4VB7.js} +1 -1
- package/dist/{chunk-EVAQPW6O.js → chunk-SKYPMHQC.js} +4 -4
- package/dist/{chunk-B2SZZFWW.js → chunk-SQVRXHOW.js} +3 -3
- package/dist/{chunk-CJYAJ3QM.js → chunk-TAX2ZJAP.js} +24 -16
- package/dist/{chunk-GTE5WZAM.js → chunk-TOI35GN2.js} +1 -1
- package/dist/{chunk-XJHKJXT4.js → chunk-UPR3MU6Z.js} +1 -1
- package/dist/{chunk-DLC2FICN.js → chunk-WQLKDL35.js} +2 -1
- package/dist/{chunk-3BA2GP4H.js → chunk-X6L6MD5B.js} +5 -5
- package/dist/{chunk-XAQDR5Y5.js → chunk-XGHHVYC7.js} +94 -32
- package/dist/{chunk-HLBODNGW.js → chunk-XWC7CNPY.js} +1 -1
- package/dist/{clean-WNEIVBF3.js → clean-7J6ZCCGV.js} +19 -18
- package/dist/cli.js +53 -53
- package/dist/{cloud-6GSSDCJL.js → cloud-7IJCJCDD.js} +4 -4
- package/dist/{cloudrun-4NEJRE4T.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-2JWQ5ABA.js → compare-Q7VW5JZT.js} +29 -28
- package/dist/{compiler-27KQD7KW.js → compiler-KPHYGFXL.js} +6 -6
- package/dist/{component-HCRET3MH.js → component-UUBREJKN.js} +3 -3
- package/dist/{compositions-HTSQ6SUJ.js → compositions-T4FTKIDP.js} +14 -13
- package/dist/{delete-GHQ5UYM7.js → delete-WZQF2IIA.js} +3 -3
- package/dist/{deploy-I3Z3NAVA.js → deploy-JU7A3XNC.js} +1 -1
- package/dist/{deterministicFonts-JFLSSKRB.js → deterministicFonts-EGAAE7QL.js} +3 -3
- package/dist/{dist-SENYPQGW.js → dist-LM7AVHOU.js} +3 -3
- package/dist/{dist-WRDLWRMS.js → dist-ULGTPSU4.js} +8 -4
- package/dist/docs/data-attributes.md +1 -1
- package/dist/{doctor-UGFVQZHI.js → doctor-VSNGRKXJ.js} +14 -13
- package/dist/{events-YS4OVX3I.js → events-CRW2DYUT.js} +3 -3
- package/dist/{events-BLJGWMNP.js → events-E63YBUL2.js} +3 -3
- package/dist/{feedback-AZ3SJ5HF.js → feedback-OSZWVR6N.js} +9 -9
- package/dist/{ffmpeg-2AECXG7V.js → ffmpeg-JLH3Z7G7.js} +10 -9
- package/dist/{figma-DRYIJQHV.js → figma-2BQNNR53.js} +3 -3
- package/dist/fontLocalizeCli.js +13 -12
- package/dist/{get-DDEAOFPB.js → get-P2XI53QW.js} +3 -3
- package/dist/{gpuPolicy-UDJT2MQK.js → gpuPolicy-NTKQJY75.js} +10 -9
- package/dist/{grade-compare-LJKK5NSY.js → grade-compare-OYASIHIB.js} +30 -29
- package/dist/{gsapParserAcorn-7NCK2LVT.js → gsapParserAcorn-SKODXC2N.js} +2 -2
- package/dist/{help-TQBGYOID.js → help-HK6K2N4G.js} +1 -1
- package/dist/{history-5TOOCF2Y.js → history-JMTYKLXW.js} +6 -6
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +65 -65
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/{info-ENI5MP4W.js → info-AW7CIVRE.js} +9 -9
- package/dist/{init-JXPXWV3G.js → init-6KIDG4LB.js} +31 -30
- package/dist/{inspect-WZNYQ5AB.js → inspect-B7BLYMRZ.js} +30 -29
- package/dist/{installer-3SGRBLJW.js → installer-ZP2LQZUQ.js} +7 -7
- package/dist/{keyframes-HEOC4CT4.js → keyframes-EQ36A5JE.js} +7 -7
- package/dist/{lambda-2VHQ4AL2.js → lambda-E6VURLIS.js} +9 -9
- package/dist/{layout-7WEUNO6T.js → layout-XYC64QQQ.js} +30 -29
- package/dist/{lint-5YMAF3L7.js → lint-V5DJYWBX.js} +9 -9
- package/dist/{lintProject-C2ONSH2U.js → lintProject-JATQKR64.js} +3 -3
- package/dist/{list-BIE3X7CO.js → list-RUGVRTVD.js} +3 -3
- package/dist/{login-YDIGJWCG.js → login-ZTKGKXGS.js} +4 -4
- package/dist/{manager-D2UV6RDQ.js → manager-JUP7PM6N.js} +11 -10
- package/dist/{media-treatment-FSKHPMWA.js → media-treatment-VIUPK4OR.js} +16 -15
- package/dist/{models-COEK6LXG.js → models-LJS2HBOZ.js} +14 -13
- package/dist/{motionShot-HYZ2ZGJQ.js → motionShot-3UAXZ7SN.js} +17 -16
- package/dist/{normalize-audio-UXR6WQ7Q.js → normalize-audio-SBYI4YIH.js} +4 -4
- package/dist/{open-OFT2GIDG.js → open-S27TUD3A.js} +14 -14
- package/dist/{parakeetRunner-4NZ3QXS3.js → parakeetRunner-ETLMLJ4L.js} +15 -14
- package/dist/{pipeline-ZKE54JMG.js → pipeline-I2M22M24.js} +11 -10
- package/dist/{play-2VG77FT6.js → play-COJU6VJK.js} +22 -21
- package/dist/{preflight-QTWDIM5C.js → preflight-FZ24NCHH.js} +11 -10
- package/dist/{present-OONXQLJG.js → present-YAHKLC5D.js} +18 -17
- package/dist/{preview-6RZJFU76.js → preview-KQOEU5YE.js} +27 -26
- package/dist/{producer-6YM3UH3B.js → producer-DTNNG4T6.js} +1 -1
- package/dist/{projectConfig-YMW4P2X6.js → projectConfig-4A76VYUP.js} +9 -9
- package/dist/{publication-SEINUAPZ.js → publication-SQPMC2W3.js} +4 -4
- package/dist/{publish-KZBTBWFO.js → publish-QUEJBGGT.js} +13 -12
- package/dist/{remove-background-BIQNMIR7.js → remove-background-FP2ETAQH.js} +12 -11
- package/dist/{render-FIH37HJA.js → render-BIFIL4U6.js} +32 -31
- package/dist/render-GQFXJWLV.js +1504 -0
- package/dist/{render-LW76HOMJ.js → render-P664SMC7.js} +5 -5
- package/dist/{render-batch-POLEEYD4.js → render-batch-ZCPMYH6Z.js} +5 -5
- package/dist/renderSetupWorker.js +3 -3
- package/dist/{resolver-O2SED3XB.js → resolver-BUC2GFZQ.js} +6 -6
- package/dist/{sherpa-HTFFFTVQ.js → sherpa-HFT6XEP6.js} +14 -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-J6MBGS5O.js → skills-3WEVO3NU.js} +20 -13
- package/dist/{skillsUpdateCheck-ZAXNLBF3.js → skillsUpdateCheck-BFPWFOK5.js} +3 -3
- package/dist/{snapshot-TL7TTFS6.js → snapshot-WDQ6S7CJ.js} +458 -98
- package/dist/{src-Z5H5N5T4.js → src-NPR2JZOJ.js} +15 -11
- package/dist/{src-EL6HGIS4.js → src-RZ574OKP.js} +9 -8
- package/dist/{staticProjectServer-EO7X7RAY.js → staticProjectServer-FTGTEZI4.js} +18 -17
- package/dist/studio/assets/{hyperframes-player-hz_VqxBZ.js → hyperframes-player-CoOdf435.js} +1 -1
- package/dist/studio/assets/{index-CV_ojgp5.js → index-CR85xg2x.js} +1 -1
- package/dist/studio/assets/{index-S1ceEagc.js → index-C_6rTpaB.js} +5 -5
- package/dist/studio/index.html +1 -1
- package/dist/{studio-api-CUZDC5B3.js → studio-api-TAWB7B23.js} +12 -11
- package/dist/{studioServer-EZPRV43Y.js → studioServer-HRQGJTBU.js} +49 -48
- package/dist/{telemetry-LFUVHARP.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-GSH743JE.js → timeline-IKUEW42T.js} +21 -19
- package/dist/{tokens-3ZMPSH7B.js → tokens-AUGUEWHS.js} +2 -2
- package/dist/{transcribe-4SHNDPWW.js → transcribe-7734CG3N.js} +19 -18
- package/dist/{transcribe-TV7JBZQS.js → transcribe-FWU6EMEO.js} +13 -12
- package/dist/{updateCheck-W7FTFOQF.js → updateCheck-VIPQ3FPW.js} +2 -2
- package/dist/{upgrade-7YYYNAPF.js → upgrade-4VNDQTVO.js} +2 -2
- package/dist/{urlDownloader-PQSUS2CP.js → urlDownloader-6CXL4CL7.js} +9 -8
- package/dist/{validate-GCHAEVXM.js → validate-QWCMVWID.js} +24 -23
- package/dist/{video-KGN7NJS5.js → video-245Q5WN4.js} +10 -9
- package/dist/warmCheck.js +37 -36
- package/package.json +1 -1
- package/dist/chunk-GMNHAOMJ.js +0 -3805
- package/dist/render-65K3K6SD.js +0 -719
- 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,22 +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";
|
|
116
|
+
import "./chunk-IZCW2NKT.js";
|
|
112
117
|
import {
|
|
113
118
|
createRuntimeStartTimeResolver,
|
|
114
119
|
isClipVisibleAt,
|
|
115
120
|
isInClipWindow
|
|
116
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-KROXPHXX.js";
|
|
117
122
|
import "./chunk-RQVDTPGD.js";
|
|
118
|
-
import "./chunk-
|
|
123
|
+
import "./chunk-Q47FAYYK.js";
|
|
119
124
|
import {
|
|
120
125
|
readElementRateSpec,
|
|
121
126
|
sourceTimeAt,
|
|
122
127
|
timeAtSourceTime
|
|
123
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-3NPOFC43.js";
|
|
124
129
|
import "./chunk-VC76R6W2.js";
|
|
125
130
|
import "./chunk-UJKQWGFF.js";
|
|
126
|
-
import
|
|
131
|
+
import {
|
|
132
|
+
topLevelElements,
|
|
133
|
+
trackKindOf
|
|
134
|
+
} from "./chunk-B2A56S5C.js";
|
|
127
135
|
import "./chunk-OFQWTKPW.js";
|
|
128
136
|
import "./chunk-DPVXBVLL.js";
|
|
129
137
|
import "./chunk-3GXQPCJC.js";
|
|
@@ -141,23 +149,26 @@ import "./chunk-XT6MXC7A.js";
|
|
|
141
149
|
import "./chunk-4UMPIPCQ.js";
|
|
142
150
|
import {
|
|
143
151
|
lintProject
|
|
144
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-Q447CX26.js";
|
|
145
153
|
import "./chunk-VAS6HQX3.js";
|
|
146
154
|
import "./chunk-6BNTGNGD.js";
|
|
147
|
-
import "./chunk-
|
|
155
|
+
import "./chunk-RUOG4VB7.js";
|
|
148
156
|
import "./chunk-MMQ52NIZ.js";
|
|
149
157
|
import "./chunk-BSQ7XANM.js";
|
|
150
158
|
import {
|
|
151
159
|
parseHTML
|
|
152
160
|
} from "./chunk-SDYDNHEE.js";
|
|
153
161
|
import "./chunk-IXLUTE6N.js";
|
|
154
|
-
import "./chunk-
|
|
162
|
+
import "./chunk-I5JRXMCV.js";
|
|
155
163
|
import "./chunk-W2LGJSEN.js";
|
|
164
|
+
import {
|
|
165
|
+
withMeta
|
|
166
|
+
} from "./chunk-ISTRDGIX.js";
|
|
156
167
|
import "./chunk-K4WIOZFP.js";
|
|
157
168
|
import "./chunk-XUXGIA7H.js";
|
|
158
169
|
import "./chunk-WERLJGIC.js";
|
|
159
170
|
import "./chunk-ISN5GRYI.js";
|
|
160
|
-
import "./chunk-
|
|
171
|
+
import "./chunk-I7QMXZSB.js";
|
|
161
172
|
import {
|
|
162
173
|
normalizeErrorMessage
|
|
163
174
|
} from "./chunk-KNU5COPB.js";
|
|
@@ -181,6 +192,15 @@ function sampleSnapshotRange([start, end], frames, duration, exclusiveEnd = fals
|
|
|
181
192
|
const last = exclusiveEnd || end === duration ? end - Math.min(1e-3, (end - start) / (frames * 2)) : end;
|
|
182
193
|
return Array.from({ length: frames }, (_, i) => start + (last - start) * i / (frames - 1));
|
|
183
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
|
+
}
|
|
184
204
|
function resolveSnapshotCompositionRange(html, durations, id, duration) {
|
|
185
205
|
const { document: document2 } = parseHTML(html);
|
|
186
206
|
const matches = Array.from(document2.querySelectorAll("[data-composition-id]")).filter(
|
|
@@ -190,14 +210,7 @@ function resolveSnapshotCompositionRange(html, durations, id, duration) {
|
|
|
190
210
|
throw new Error(
|
|
191
211
|
`Composition ID ${JSON.stringify(id)} matched ${matches.length} elements; expected exactly one`
|
|
192
212
|
);
|
|
193
|
-
const
|
|
194
|
-
Object.entries(durations).map(([key, value]) => [key, { duration: () => value }])
|
|
195
|
-
);
|
|
196
|
-
const resolver = createRuntimeStartTimeResolver({
|
|
197
|
-
documentRef: document2,
|
|
198
|
-
timelineRegistry: registry,
|
|
199
|
-
includeAuthoredTimingAttrs: true
|
|
200
|
-
});
|
|
213
|
+
const resolver = snapshotStartResolver(document2, durations);
|
|
201
214
|
let start = 0, end = duration;
|
|
202
215
|
for (let el = matches[0]; el; el = el.parentElement) {
|
|
203
216
|
if (!el.hasAttribute("data-composition-id") && !el.hasAttribute("data-start")) continue;
|
|
@@ -218,6 +231,208 @@ import { randomUUID } from "crypto";
|
|
|
218
231
|
import { existsSync, mkdtempSync, readFileSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
219
232
|
import { tmpdir } from "os";
|
|
220
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
|
|
221
436
|
function orbitStageSource() {
|
|
222
437
|
return `function(cam) {
|
|
223
438
|
var root = document.querySelector("[data-composition-id]")
|
|
@@ -478,7 +693,8 @@ function serveCapturePage(projectDir, html, proxy) {
|
|
|
478
693
|
return serveStaticProjectHtml(projectDir, html, void 0, [], proxy === true);
|
|
479
694
|
}
|
|
480
695
|
async function captureSnapshots(projectDir, opts) {
|
|
481
|
-
const
|
|
696
|
+
const log = opts.log ?? ((message) => console.log(message));
|
|
697
|
+
const { bundleWithLocalizedFonts } = await import("./bundleWithLocalizedFonts-67MLTHKM.js");
|
|
482
698
|
const capture = await captureArtifactRevision(projectDir).catch(warnSnapshotsNotRecorded);
|
|
483
699
|
const invocation = randomUUID();
|
|
484
700
|
const artifacts = [];
|
|
@@ -486,6 +702,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
486
702
|
const warnings = [];
|
|
487
703
|
let completed = false;
|
|
488
704
|
const numFrames = opts.frames ?? 5;
|
|
705
|
+
let review;
|
|
706
|
+
let reviewList;
|
|
707
|
+
const reviewPaths = /* @__PURE__ */ new Map();
|
|
489
708
|
const html = await bundleWithLocalizedFonts(projectDir);
|
|
490
709
|
const server = await serveCapturePage(projectDir, html, opts.autoProxy);
|
|
491
710
|
const savedPaths = [];
|
|
@@ -517,10 +736,10 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
517
736
|
const parts = [`${fontReport.loaded.length} loaded`];
|
|
518
737
|
if (fontReport.errored.length > 0) parts.push(`${fontReport.errored.length} failed`);
|
|
519
738
|
if (fontReport.unused.length > 0) parts.push(`${fontReport.unused.length} unused`);
|
|
520
|
-
|
|
739
|
+
log(`
|
|
521
740
|
${c.dim("Fonts:")} ${parts.join(", ")}`);
|
|
522
741
|
if (fontReport.errored.length > 0) {
|
|
523
|
-
|
|
742
|
+
log(` ${c.error("Fonts FAILED:")} ${fontReport.errored.join(", ")}`);
|
|
524
743
|
}
|
|
525
744
|
}
|
|
526
745
|
if (fontReport.errored.length)
|
|
@@ -536,19 +755,20 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
536
755
|
return 0;
|
|
537
756
|
});
|
|
538
757
|
if (duration <= 0 && !opts.at?.length) {
|
|
539
|
-
return [];
|
|
758
|
+
return { paths: [] };
|
|
540
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
|
+
}));
|
|
541
769
|
let range = opts.range;
|
|
542
|
-
if (opts.composition) {
|
|
543
|
-
const timing = await
|
|
544
|
-
html: document.documentElement.outerHTML,
|
|
545
|
-
durations: Object.fromEntries(
|
|
546
|
-
Object.entries(window.__timelines ?? {}).map(([id, timeline]) => [
|
|
547
|
-
id,
|
|
548
|
-
Number(timeline.duration?.())
|
|
549
|
-
])
|
|
550
|
-
)
|
|
551
|
-
}));
|
|
770
|
+
if (opts.composition && !opts.review) {
|
|
771
|
+
const timing = await readTiming();
|
|
552
772
|
range = resolveSnapshotCompositionRange(
|
|
553
773
|
timing.html,
|
|
554
774
|
timing.durations,
|
|
@@ -556,7 +776,18 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
556
776
|
duration
|
|
557
777
|
);
|
|
558
778
|
}
|
|
559
|
-
|
|
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 ? {
|
|
560
791
|
times: sampleSnapshotRange(range, numFrames, duration, !!opts.composition),
|
|
561
792
|
appendedTail: false
|
|
562
793
|
} : computeSnapshotTimes(duration, {
|
|
@@ -565,11 +796,15 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
565
796
|
includeEnd: opts.includeEnd
|
|
566
797
|
});
|
|
567
798
|
if (range)
|
|
568
|
-
|
|
799
|
+
log(
|
|
569
800
|
` Sampling ${positions.length} frames within ${range[0]}\u2013${range[1]}s${opts.composition ? ` (composition ${opts.composition})` : ""}`
|
|
570
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
|
+
);
|
|
571
806
|
if (appendedTail) {
|
|
572
|
-
|
|
807
|
+
log(
|
|
573
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.`)}`
|
|
574
809
|
);
|
|
575
810
|
}
|
|
@@ -591,7 +826,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
591
826
|
let syncVideoFrameVisibility = null;
|
|
592
827
|
let extractMediaMetadata = null;
|
|
593
828
|
try {
|
|
594
|
-
const engine = await import("./src-
|
|
829
|
+
const engine = await import("./src-RZ574OKP.js");
|
|
595
830
|
injectVideoFramesBatch = engine.injectVideoFramesBatch;
|
|
596
831
|
syncVideoFrameVisibility = engine.syncVideoFrameVisibility;
|
|
597
832
|
extractMediaMetadata = engine.extractMediaMetadata;
|
|
@@ -729,7 +964,8 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
729
964
|
await recaptureSnapshotComposite(page);
|
|
730
965
|
const timeLabel = formatSnapshotTimestamp(time);
|
|
731
966
|
const slot = opts.keep ? `at-${timeLabel}` : `${String(i).padStart(2, "0")}-at-${timeLabel}`;
|
|
732
|
-
const
|
|
967
|
+
const reviewFrame = reviewList?.[i];
|
|
968
|
+
const filename = reviewFrame ? reviewFrame.file : opts.keep ? `${slot}.png` : `frame-${slot}.png`;
|
|
733
969
|
const framePath = join(snapshotDir, filename);
|
|
734
970
|
let crop;
|
|
735
971
|
if (opts.zoom) {
|
|
@@ -768,9 +1004,11 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
768
1004
|
zoom: opts.zoom,
|
|
769
1005
|
zoomScale: opts.zoom ? opts.zoomScale ?? DEFAULT_ZOOM_SCALE : 1,
|
|
770
1006
|
angle: opts.angle,
|
|
771
|
-
browserGpuMode: opts.browserGpuMode
|
|
1007
|
+
browserGpuMode: opts.browserGpuMode,
|
|
1008
|
+
...reviewFrame ? { review: { role: reviewFrame.role, label: reviewFrame.label } } : {}
|
|
772
1009
|
}
|
|
773
1010
|
});
|
|
1011
|
+
if (reviewFrame) reviewPaths.set(reviewFrame, framePath);
|
|
774
1012
|
if (opts.against) {
|
|
775
1013
|
const refPng = await extractVideoFrameToBuffer(opts.against, time);
|
|
776
1014
|
if (!refPng) {
|
|
@@ -806,20 +1044,32 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
806
1044
|
artifacts,
|
|
807
1045
|
opts.zoom,
|
|
808
1046
|
warnings,
|
|
809
|
-
completed
|
|
1047
|
+
completed,
|
|
1048
|
+
log
|
|
810
1049
|
) : false;
|
|
811
1050
|
if (!recorded) {
|
|
812
1051
|
const paths = [...replaced, ...artifacts.map((artifact) => artifact.image)];
|
|
813
1052
|
if (paths.length > 0) await forgetRecordedArtifacts(projectDir, paths).catch(() => void 0);
|
|
814
1053
|
}
|
|
815
1054
|
}
|
|
816
|
-
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
|
+
};
|
|
817
1067
|
}
|
|
818
1068
|
function warnSnapshotsNotRecorded(error) {
|
|
819
1069
|
console.warn(` ${c.warn("\u26A0")} Snapshots were not recorded: ${normalizeErrorMessage(error)}`);
|
|
820
1070
|
return void 0;
|
|
821
1071
|
}
|
|
822
|
-
async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, warnings, completed) {
|
|
1072
|
+
async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, warnings, completed, log) {
|
|
823
1073
|
const records = await recordArtifacts(
|
|
824
1074
|
projectDir,
|
|
825
1075
|
capture,
|
|
@@ -832,10 +1082,65 @@ async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, war
|
|
|
832
1082
|
).catch(warnSnapshotsNotRecorded);
|
|
833
1083
|
const record = records?.[0];
|
|
834
1084
|
if (!record) return false;
|
|
835
|
-
|
|
836
|
-
|
|
1085
|
+
log(` Revision: ${record.revision ?? "none"} (${record.attribution})`);
|
|
1086
|
+
log(` State: ${join(projectDir, ".hyperframes", "video-state.json")}`);
|
|
837
1087
|
return true;
|
|
838
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
|
+
}
|
|
839
1144
|
var snapshot_default = defineCommand({
|
|
840
1145
|
meta: {
|
|
841
1146
|
name: "snapshot",
|
|
@@ -901,6 +1206,16 @@ var snapshot_default = defineCommand({
|
|
|
901
1206
|
type: "string",
|
|
902
1207
|
description: "Reference video (e.g. footage being rebuilt): also save its frame at each captured time and a render|reference pair sheet"
|
|
903
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
|
+
},
|
|
904
1219
|
describe: {
|
|
905
1220
|
type: "string",
|
|
906
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."
|
|
@@ -917,8 +1232,22 @@ var snapshot_default = defineCommand({
|
|
|
917
1232
|
}
|
|
918
1233
|
},
|
|
919
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
|
+
};
|
|
920
1242
|
if ([args.at, args.range, args.composition].filter((value) => value !== void 0).length > 1)
|
|
921
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
|
+
}
|
|
922
1251
|
const frames = parseInt(args.frames, 10) || 5;
|
|
923
1252
|
const range = args.range === void 0 ? void 0 : parseSnapshotRange(String(args.range));
|
|
924
1253
|
const composition = args.composition === void 0 ? void 0 : String(args.composition).trim();
|
|
@@ -927,28 +1256,32 @@ var snapshot_default = defineCommand({
|
|
|
927
1256
|
const lintResult = await lintProject(project.dir);
|
|
928
1257
|
if (hasDefinitiveEntryMismatch(lintResult)) {
|
|
929
1258
|
const candidate = definitiveEntryMismatchComposition(lintResult);
|
|
930
|
-
|
|
1259
|
+
log("");
|
|
931
1260
|
for (const line of formatLintFindings(lintResult, { errorsFirst: true })) {
|
|
932
|
-
|
|
1261
|
+
log(line);
|
|
933
1262
|
}
|
|
934
|
-
|
|
935
|
-
|
|
1263
|
+
log("");
|
|
1264
|
+
log(c.error(" Aborting snapshot because the default index.html entry is blank."));
|
|
936
1265
|
if (candidate && posix.basename(candidate) === "index.html") {
|
|
937
1266
|
const candidateDir = posix.dirname(candidate);
|
|
938
1267
|
const target = `<project>/${candidateDir}`;
|
|
939
|
-
|
|
1268
|
+
log(
|
|
940
1269
|
c.dim(
|
|
941
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.`
|
|
942
1271
|
)
|
|
943
1272
|
);
|
|
944
1273
|
} else if (candidate) {
|
|
945
|
-
|
|
1274
|
+
log(
|
|
946
1275
|
c.dim(
|
|
947
1276
|
` Move or mount ${candidate} as a project index.html before snapshotting; snapshot accepts project directories, not individual HTML files.`
|
|
948
1277
|
)
|
|
949
1278
|
);
|
|
950
1279
|
}
|
|
951
|
-
|
|
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
|
+
}
|
|
952
1285
|
failCommand();
|
|
953
1286
|
}
|
|
954
1287
|
const timeout = parseInt(args.timeout, 10) || 5e3;
|
|
@@ -959,20 +1292,18 @@ var snapshot_default = defineCommand({
|
|
|
959
1292
|
const zoomTarget = args.zoom ? parseZoomTarget(String(args.zoom)) : void 0;
|
|
960
1293
|
const zoomScale = parseZoomScale(args["zoom-scale"]);
|
|
961
1294
|
const against = args.against ? resolve(String(args.against)) : void 0;
|
|
962
|
-
if (against && !existsSync(against))
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
}
|
|
966
|
-
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`;
|
|
967
1298
|
const angleLabel = camera && (camera.yaw !== 0 || camera.pitch !== 0) ? ` ${c.dim(`(angle yaw ${camera.yaw}\xB0 pitch ${camera.pitch}\xB0)`)}` : "";
|
|
968
|
-
|
|
1299
|
+
log(`${c.accent("\u25C6")} Capturing ${label} from ${c.accent(project.name)}${angleLabel}`);
|
|
969
1300
|
let managedSnapshotDir;
|
|
970
1301
|
try {
|
|
971
1302
|
const snapshotDir = args.output ? resolve(String(args.output)) : artifactDirectory(project.dir, "snapshots");
|
|
972
1303
|
if (!args.output) managedSnapshotDir = snapshotDir;
|
|
973
1304
|
if (args.output) retainSnapshotOutput(project.dir, snapshotDir);
|
|
974
1305
|
await withProjectLock(project.dir, "snapshot", async () => {
|
|
975
|
-
const
|
|
1306
|
+
const captured = await captureSnapshots(project.dir, {
|
|
976
1307
|
frames,
|
|
977
1308
|
range,
|
|
978
1309
|
composition,
|
|
@@ -986,53 +1317,71 @@ var snapshot_default = defineCommand({
|
|
|
986
1317
|
autoProxy: args.proxy,
|
|
987
1318
|
browserGpuMode: resolveLocalBrowserGpuMode(args["browser-gpu"]),
|
|
988
1319
|
against,
|
|
989
|
-
keep: args.keep === true
|
|
1320
|
+
keep: args.keep === true,
|
|
1321
|
+
review: reviewMode,
|
|
1322
|
+
log
|
|
990
1323
|
});
|
|
1324
|
+
const paths = captured.paths;
|
|
991
1325
|
reportArtifacts(
|
|
992
1326
|
"snapshot",
|
|
993
1327
|
"frame",
|
|
994
1328
|
paths.map((path) => resolve(project.dir, path))
|
|
995
1329
|
);
|
|
996
1330
|
if (paths.length === 0) {
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
${c.error("\u2717")} Could not determine composition duration \u2014 no frames captured`
|
|
1000
|
-
);
|
|
1001
|
-
failCommand();
|
|
1331
|
+
fail(`
|
|
1332
|
+
${c.error("\u2717")} Could not determine composition duration \u2014 no frames captured`);
|
|
1002
1333
|
}
|
|
1003
|
-
|
|
1334
|
+
log(`
|
|
1004
1335
|
${c.success("\u25C7")} ${paths.length} snapshots saved to ${snapshotDir}`);
|
|
1005
1336
|
for (const p of paths) {
|
|
1006
|
-
|
|
1337
|
+
log(` ${p}`);
|
|
1007
1338
|
}
|
|
1008
1339
|
if (against) {
|
|
1009
|
-
|
|
1340
|
+
log(
|
|
1010
1341
|
` ${c.dim("ref-*.png + pair-*.jpg")} beside each frame (reference frame, render | reference sheet)`
|
|
1011
1342
|
);
|
|
1012
1343
|
}
|
|
1344
|
+
let contactSheets = [];
|
|
1345
|
+
let reviewSheets;
|
|
1013
1346
|
try {
|
|
1014
1347
|
const { createSnapshotContactSheet } = await import("./contactSheet-CAGMKI3E.js");
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
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
|
+
}
|
|
1022
1370
|
}
|
|
1023
1371
|
} catch (err) {
|
|
1024
1372
|
console.warn(
|
|
1025
1373
|
` ${c.warn("\u26A0")} Contact sheet skipped: ${normalizeErrorMessage(err)}. Individual snapshot PNGs are still available.`
|
|
1026
1374
|
);
|
|
1027
1375
|
}
|
|
1376
|
+
let describedPath;
|
|
1028
1377
|
if (describeArg !== null) {
|
|
1029
1378
|
try {
|
|
1030
1379
|
const geminiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
1031
1380
|
if (!geminiKey) {
|
|
1032
1381
|
if (args.describe !== void 0)
|
|
1033
|
-
|
|
1382
|
+
log(` ${c.dim("--describe: GEMINI_API_KEY not set, skipping")}`);
|
|
1034
1383
|
} else if (paths.length > 0) {
|
|
1035
|
-
|
|
1384
|
+
log(` ${c.dim("Describing frames with Gemini vision...")}`);
|
|
1036
1385
|
const { GoogleGenAI } = await loadOptionalPackage("@google/genai", "--describe");
|
|
1037
1386
|
const ai = new GoogleGenAI({ apiKey: geminiKey });
|
|
1038
1387
|
const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
|
|
@@ -1100,17 +1449,28 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${snapshotDir}`);
|
|
|
1100
1449
|
}
|
|
1101
1450
|
const descPath = join(snapshotDir, "descriptions.md");
|
|
1102
1451
|
writeFileSync(descPath, descriptions.join("\n"));
|
|
1103
|
-
|
|
1452
|
+
describedPath = descPath;
|
|
1453
|
+
log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
|
|
1104
1454
|
}
|
|
1105
1455
|
} catch (descErr) {
|
|
1106
1456
|
const msg = normalizeErrorMessage(descErr);
|
|
1107
|
-
|
|
1457
|
+
log(` ${c.dim(`--describe failed: ${msg}`)}`);
|
|
1108
1458
|
}
|
|
1109
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
|
+
}
|
|
1110
1468
|
});
|
|
1111
1469
|
} catch (err) {
|
|
1470
|
+
if (err instanceof CliRuntimeError && err.result.presented) throw err;
|
|
1112
1471
|
const msg = normalizeErrorMessage(err);
|
|
1113
|
-
console.error
|
|
1472
|
+
if (asJson) console.log(JSON.stringify(withMeta({ ok: false, error: msg }), null, 2));
|
|
1473
|
+
else console.error(`
|
|
1114
1474
|
${c.error("\u2717")} Snapshot failed: ${msg}`);
|
|
1115
1475
|
failCommand();
|
|
1116
1476
|
} finally {
|