hyperframes 0.8.184 → 0.8.186
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-UGK7AZI6.js} +14 -14
- package/dist/{agentPromptGenerator-VIIPZCJ3.js → agentPromptGenerator-KYO5MKTW.js} +1 -1
- package/dist/{animatedGifPrep-AGASIWVA.js → animatedGifPrep-HPZPSB43.js} +9 -9
- package/dist/api.js +18 -18
- package/dist/{asset-LSTEMPIB.js → asset-X2GTFWOY.js} +2 -2
- package/dist/{assetCataloger-BKBMNL3A.js → assetCataloger-5NWEG4IU.js} +9 -9
- package/dist/audio-7PBM5F3H.js +2317 -0
- package/dist/{auth-MJWKYK77.js → auth-WABSMO46.js} +1 -1
- package/dist/{autoUpdate-2GGDKYR2.js → autoUpdate-6SCMLTSC.js} +2 -2
- package/dist/{backgroundChecks-7GRX5VQY.js → backgroundChecks-XOGPAAR3.js} +3 -3
- package/dist/backgroundChecksWorker.js +3 -3
- package/dist/{batchRender-BCV2LELR.js → batchRender-VR6IA77K.js} +5 -5
- package/dist/{beats-7BCFRBAL.js → beats-3IWXLMSC.js} +7 -7
- package/dist/{benchmark-2R6CN5MQ.js → benchmark-2SSYATCX.js} +10 -10
- package/dist/{browser-6AFGOI7G.js → browser-PMRN345D.js} +3 -3
- package/dist/{bundleWithLocalizedFonts-2EGPA5ZO.js → bundleWithLocalizedFonts-TT32MZBO.js} +2 -2
- package/dist/{capture-HOIAW6MO.js → capture-4VD6AKUJ.js} +13 -13
- package/dist/{capture-HA2UHLIU.js → capture-BDGYTE57.js} +2 -2
- package/dist/{captureCompositionFrame-4236FVWJ.js → captureCompositionFrame-5FVLAETA.js} +17 -13
- package/dist/{catalog-A6CZAWW4.js → catalog-HUYZO5D7.js} +14 -14
- package/dist/{catch-up-TNA4DJOA.js → catch-up-SSGTR2ZT.js} +4 -4
- package/dist/{check-5E5U2EQZ.js → check-JWUWHGM2.js} +34 -34
- package/dist/{checkBrowser-FNINXBMZ.js → checkBrowser-X7G6YNR7.js} +31 -31
- package/dist/{chunk-UJKUB2LH.js → chunk-22QKQDEE.js} +11 -11
- package/dist/{chunk-2PVE4WS2.js → chunk-27H2363S.js} +33 -6
- package/dist/{chunk-2ULXZ4PG.js → chunk-2II34JPM.js} +154 -21
- package/dist/{chunk-3QVMJ7GX.js → chunk-2PZZMAME.js} +11 -10
- package/dist/{chunk-X3CG5YQA.js → chunk-3YHGQJI6.js} +3 -3
- package/dist/{chunk-EEP5Y5IE.js → chunk-46HEFGXJ.js} +1 -1
- package/dist/{chunk-DWUGKEHR.js → chunk-4AFNEKU7.js} +1 -1
- package/dist/{chunk-R2BFTECP.js → chunk-4NTW45W5.js} +3 -3
- package/dist/{chunk-7HJALUIO.js → chunk-4XFFJAWS.js} +1 -1
- package/dist/{chunk-SN7KI5JA.js → chunk-5ZMIVTHN.js} +2 -2
- package/dist/{chunk-QL2PNIXC.js → chunk-5ZMXGNGC.js} +24 -16
- package/dist/{chunk-UKOTVJFV.js → chunk-6IOBAOU7.js} +1 -1
- package/dist/{chunk-JIUTXKWA.js → chunk-77QM6YRQ.js} +2 -1
- package/dist/{chunk-ES426XRJ.js → chunk-7AUMTARQ.js} +3 -3
- package/dist/{chunk-5CS4T6C6.js → chunk-7L37AB57.js} +1 -1
- package/dist/{chunk-RGXVEYHI.js → chunk-7M7TMM4S.js} +81 -10
- package/dist/{chunk-3TXNNBI2.js → chunk-7MLFYMFB.js} +2 -2
- package/dist/{chunk-MFAETWIF.js → chunk-7MVODWQF.js} +1 -1
- package/dist/{chunk-WHPN2TIT.js → chunk-ACLABKEF.js} +6 -6
- package/dist/{chunk-YMS5FOMC.js → chunk-B2A56S5C.js} +1 -1
- package/dist/{chunk-YALM6XN4.js → chunk-BRTDLVK3.js} +3 -3
- package/dist/{chunk-VDM3FEDP.js → chunk-DQZMJS2P.js} +1 -1
- package/dist/{chunk-PSKEKWVU.js → chunk-DTXDQ6OP.js} +1 -1
- package/dist/{chunk-Q33P4EAC.js → chunk-EZINX6HH.js} +3 -3
- package/dist/{chunk-3MDJIWOV.js → chunk-FCWFV4P7.js} +75 -35
- package/dist/{chunk-ABZYYUUH.js → chunk-FRLTKTOR.js} +1 -1
- package/dist/{chunk-E32ZQ2WO.js → chunk-GTMBII7X.js} +1 -1
- package/dist/{chunk-YOZPQCSR.js → chunk-HOFX63F2.js} +3 -3
- package/dist/{chunk-LRGYPXHF.js → chunk-HZ7M2MZA.js} +1 -1
- package/dist/{chunk-TYXH3EKP.js → chunk-I5JRXMCV.js} +16 -1
- package/dist/{chunk-LLC4CS6I.js → chunk-ID5AJ4L3.js} +3 -3
- package/dist/{chunk-FGJEUV4S.js → chunk-K6KBOORN.js} +48 -4
- package/dist/{chunk-EM7C7H7S.js → chunk-KNLSYCI5.js} +7 -7
- package/dist/{chunk-4N4P3ZWL.js → chunk-LDW3KVGK.js} +2 -2
- package/dist/{chunk-OLZENUPI.js → chunk-LLFQA7XF.js} +1 -1
- package/dist/chunk-LLMSX6V6.js +17 -0
- package/dist/{chunk-5UDRPPN2.js → chunk-MY6CVBDD.js} +7 -4
- package/dist/{chunk-7NRI7HYX.js → chunk-NPDPDEPP.js} +1 -1
- package/dist/{chunk-BCHSTE7U.js → chunk-PEIV2SOG.js} +1 -1
- package/dist/{chunk-ADDHW2FS.js → chunk-Q447CX26.js} +82 -12
- package/dist/{chunk-YWNJTZGN.js → chunk-R6IGQ5NO.js} +2 -2
- package/dist/{chunk-YWHCXIMD.js → chunk-RFJ6SX4U.js} +5 -5
- package/dist/{chunk-J3QM7AHP.js → chunk-RNZEQTWZ.js} +2 -2
- package/dist/{chunk-SAX7HQ5E.js → chunk-ROWEDRVX.js} +1 -1
- package/dist/{chunk-PFYWVUHA.js → chunk-RPUIMFHF.js} +1 -1
- package/dist/{chunk-OYLO6TYK.js → chunk-RUOG4VB7.js} +1 -1
- package/dist/{chunk-UNNXFKVG.js → chunk-RVZNSKRH.js} +2 -2
- package/dist/{chunk-VNVQGDPC.js → chunk-T4RP55P2.js} +1 -1
- package/dist/{chunk-GDEV42FA.js → chunk-TH7J3JZ5.js} +524 -42
- package/dist/{chunk-VHZ6DL3M.js → chunk-TMK4Q7JA.js} +10 -7
- package/dist/{chunk-74JMKLVU.js → chunk-TQ2RRB5V.js} +1 -1
- package/dist/{chunk-ICJEAFPD.js → chunk-U4BMRIE6.js} +16 -7
- package/dist/{chunk-HR23IKLZ.js → chunk-U7QTMRLW.js} +2 -2
- package/dist/{chunk-KN46TGHV.js → chunk-UAJCTEK2.js} +1 -1
- package/dist/{chunk-CXABAXB3.js → chunk-UJZT6HNN.js} +1 -1
- package/dist/chunk-UOZX5W5T.js +3852 -0
- package/dist/{chunk-FFJ5TDRD.js → chunk-VHBBV5DH.js} +10 -3
- package/dist/{chunk-ZRHO6YMM.js → chunk-WHMFW5ET.js} +4 -4
- package/dist/{chunk-WTFUDNW2.js → chunk-WLHNIIXU.js} +3 -3
- package/dist/{chunk-ZOCHDXDG.js → chunk-Y2M6XSNK.js} +1 -1
- package/dist/{chunk-2XA7KXQO.js → chunk-YNH6ERDL.js} +2 -2
- package/dist/{chunk-JB6ARMQS.js → chunk-YQICCAVA.js} +1 -1
- package/dist/{chunk-7MB2ZAQF.js → chunk-YRAJDFIN.js} +1 -1
- package/dist/{chunk-IWTNTUPQ.js → chunk-Z5233OAN.js} +11 -13
- package/dist/{chunk-TE427YID.js → chunk-ZKBW7NU2.js} +2 -2
- package/dist/{chunk-4KKKBEP3.js → chunk-ZVBEGBII.js} +3 -3
- package/dist/{clean-HGASSMWI.js → clean-IM2JIAUT.js} +18 -18
- package/dist/cli.js +53 -53
- package/dist/{cloud-JPDVNXHN.js → cloud-6IPBCJSX.js} +4 -4
- package/dist/{cloudrun-AMMGSDRP.js → cloudrun-MWZ6S2I2.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-WD7A2TV5.js} +28 -28
- package/dist/{compiler-Q3N6QXMT.js → compiler-2EKSMC3I.js} +6 -6
- package/dist/{component-D72J32Q7.js → component-JKALWH36.js} +3 -3
- package/dist/{compositions-UQRJ5ROG.js → compositions-643NAG4A.js} +13 -13
- package/dist/{delete-P42VIDDA.js → delete-EASPXKHQ.js} +2 -2
- package/dist/{deploy-WZTH57O4.js → deploy-CDKCQ5MX.js} +1 -1
- package/dist/{deterministicFonts-VQ5UBMXY.js → deterministicFonts-EGAAE7QL.js} +3 -3
- package/dist/{dist-DYS24AMA.js → dist-F6FOKRSU.js} +10 -4
- package/dist/{dist-SENYPQGW.js → dist-LM7AVHOU.js} +3 -3
- package/dist/docs/data-attributes.md +1 -1
- package/dist/{doctor-KEJIG2SK.js → doctor-7XUVYDJQ.js} +13 -13
- package/dist/{events-CYKSNR7N.js → events-5TTPYBKG.js} +3 -3
- package/dist/{events-UZXFQPMT.js → events-TULV6D3G.js} +3 -3
- package/dist/{feedback-LXNQF7CA.js → feedback-4FTPWM6P.js} +8 -8
- package/dist/{ffmpeg-BYHON577.js → ffmpeg-MP7ZVYLZ.js} +9 -9
- package/dist/{figma-EIQ35PS6.js → figma-B7LFWYKO.js} +3 -3
- package/dist/fontLocalizeCli.js +12 -12
- package/dist/{get-CC2YL7QO.js → get-F7W4AQ2V.js} +2 -2
- package/dist/{gpuPolicy-VFSACUQV.js → gpuPolicy-NSNVDFXC.js} +9 -9
- package/dist/{grade-compare-TUQL7IV2.js → grade-compare-6QXDTLS2.js} +29 -29
- package/dist/{gsapParserAcorn-7NCK2LVT.js → gsapParserAcorn-SKODXC2N.js} +2 -2
- package/dist/{help-ROROO5K6.js → help-RJAA4O74.js} +1 -1
- package/dist/{history-PNELYLXX.js → history-OOQBDVV5.js} +6 -6
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +67 -67
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/{info-4FZTH6AS.js → info-5OGGYYLO.js} +9 -9
- package/dist/{init-I43GHHVP.js → init-DM3TJKW2.js} +68 -50
- package/dist/{inspect-IT4TYIZ3.js → inspect-FECQCLS5.js} +29 -29
- package/dist/{installer-CWOJVK5K.js → installer-WOG4VORV.js} +7 -7
- package/dist/{keyframes-3FBOGVD4.js → keyframes-SZHWUF5Y.js} +7 -7
- package/dist/{lambda-H3V32I7M.js → lambda-JG2ZRGMC.js} +9 -9
- package/dist/{layout-BZ5LYJ5C.js → layout-7ACF7ZKC.js} +29 -29
- package/dist/{lint-ZTNSGP2S.js → lint-ZCQGMILV.js} +9 -9
- package/dist/{lintProject-C2ONSH2U.js → lintProject-JATQKR64.js} +3 -3
- package/dist/{list-XM4GWJYY.js → list-MH2X3Y2T.js} +2 -2
- package/dist/{login-H6HYKMWX.js → login-CK46WX5U.js} +4 -4
- package/dist/{manager-TWVDSJXO.js → manager-GXTPNJVW.js} +10 -10
- package/dist/{media-treatment-N7MY5NXB.js → media-treatment-EH2AT34Z.js} +15 -15
- package/dist/{models-WEMIMYBD.js → models-D5XP2UK6.js} +13 -13
- package/dist/{motionShot-RHICTVPU.js → motionShot-UR7D3SRQ.js} +16 -16
- package/dist/{normalize-4UDISLPL.js → normalize-3AYFSN2F.js} +1 -1
- package/dist/{normalize-audio-ZFUZCJE3.js → normalize-audio-635JOR5W.js} +4 -4
- package/dist/{open-IBJ4FL3G.js → open-6WE5WFVM.js} +14 -14
- package/dist/{parakeetRunner-XXO4WSLR.js → parakeetRunner-STHZPG32.js} +14 -14
- package/dist/{pipeline-6ML3LUVK.js → pipeline-LVEKRETU.js} +10 -10
- package/dist/{play-RV4NAVF5.js → play-W6TDW4FE.js} +21 -21
- package/dist/{preflight-R3DEFMLA.js → preflight-LIMQXLR7.js} +10 -10
- package/dist/{present-5TBJGE6B.js → present-RX5QX6UR.js} +17 -17
- package/dist/{preview-FLKZ5CXJ.js → preview-KIWTWK63.js} +20 -20
- package/dist/{producer-7XYSPVKH.js → producer-TSNKSCUM.js} +1 -1
- package/dist/{projectConfig-TBU2VWZX.js → projectConfig-NCP7JRH4.js} +9 -9
- package/dist/{publication-CWWUJYJ5.js → publication-5W5UZWGC.js} +4 -4
- package/dist/{publish-FSNE4FEB.js → publish-7WR4XJ6I.js} +11 -11
- package/dist/{remove-background-MDFWRWCT.js → remove-background-43JGBRWQ.js} +11 -11
- package/dist/{render-F4JQ553X.js → render-456HCO6O.js} +31 -31
- package/dist/{render-LWZKXCLY.js → render-7T44HIM6.js} +5 -5
- package/dist/{render-DBGQZAZT.js → render-WHMLYIOI.js} +18 -30
- package/dist/{render-batch-PU7NMLIJ.js → render-batch-LURBJTBV.js} +5 -5
- package/dist/renderSetupWorker.js +3 -3
- package/dist/{resolver-RUBGFXPC.js → resolver-MBIW4VC4.js} +6 -6
- package/dist/{sherpa-X2TBNO6P.js → sherpa-5J2AALED.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-UHOXOGGF.js} +20 -13
- package/dist/{skillsUpdateCheck-XQGZGJJG.js → skillsUpdateCheck-PDZIFUJE.js} +3 -3
- package/dist/{snapshot-M4NUUSNU.js → snapshot-PFV7ALLH.js} +462 -100
- package/dist/{src-4UYM2K3S.js → src-DCVSEODX.js} +8 -8
- package/dist/{src-6MSC62U2.js → src-XK5YIR6L.js} +11 -11
- package/dist/{staticProjectServer-ERDTFP45.js → staticProjectServer-4IE4G4JO.js} +17 -17
- package/dist/studio/assets/{hyperframes-player-DEncBxR7.js → hyperframes-player-B_skzvYC.js} +1 -1
- package/dist/studio/assets/{index-Cc22mgvY.js → index-CgLbvCUo.js} +1 -1
- package/dist/studio/assets/{index-BABXr78Q.js → index-Dn5FAk2e.js} +99 -99
- package/dist/studio/index.html +1 -1
- package/dist/{studio-api-SAKD3VKC.js → studio-api-JMWYU7KF.js} +11 -11
- package/dist/{studioServer-IRI7EVOM.js → studioServer-BWLSTGIG.js} +50 -49
- package/dist/{telemetry-F4XADVAF.js → telemetry-JCU3AV7W.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-BCIFQYOM.js} +20 -19
- package/dist/{tokens-LRRYM35A.js → tokens-7IXKALMQ.js} +2 -2
- package/dist/{transcribe-44XDFNVU.js → transcribe-HW7HGJ4V.js} +19 -19
- package/dist/{transcribe-WHYHWAB2.js → transcribe-ZUQD3B32.js} +12 -12
- package/dist/{updateCheck-7CPH3CAZ.js → updateCheck-Z6LNEK7B.js} +2 -2
- package/dist/{upgrade-WW4GQ2RI.js → upgrade-JYH72JGL.js} +2 -2
- package/dist/{urlDownloader-OHLLP45A.js → urlDownloader-WKLFHSUH.js} +8 -8
- package/dist/{validate-VNCDH2LW.js → validate-QCC27YYI.js} +23 -23
- package/dist/{video-5OHTLL2D.js → video-EZ7ONY6L.js} +9 -9
- package/dist/warmCheck.js +36 -36
- package/package.json +1 -1
- package/dist/audio-KGK44XE4.js +0 -1153
- 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-4XFFJAWS.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-DQZMJS2P.js";
|
|
37
|
+
import "./chunk-K6KBOORN.js";
|
|
35
38
|
import "./chunk-X7MTZ4T2.js";
|
|
36
39
|
import {
|
|
37
40
|
resolveProject
|
|
38
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-HZ7M2MZA.js";
|
|
39
42
|
import {
|
|
40
43
|
serveStaticProjectHtml
|
|
41
|
-
} from "./chunk-
|
|
42
|
-
import "./chunk-
|
|
44
|
+
} from "./chunk-ZVBEGBII.js";
|
|
45
|
+
import "./chunk-R6IGQ5NO.js";
|
|
43
46
|
import "./chunk-X7MTZ4T2.js";
|
|
44
47
|
import "./chunk-XUHOIDKG.js";
|
|
45
|
-
import "./chunk-
|
|
46
|
-
import "./chunk-
|
|
48
|
+
import "./chunk-2PZZMAME.js";
|
|
49
|
+
import "./chunk-WHMFW5ET.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-5ZMIVTHN.js";
|
|
57
60
|
import "./chunk-ALVXFXUG.js";
|
|
58
61
|
import {
|
|
59
62
|
DEFAULT_ZOOM_SCALE,
|
|
@@ -62,44 +65,46 @@ import {
|
|
|
62
65
|
parseZoomTarget,
|
|
63
66
|
resolveCropRegion,
|
|
64
67
|
runFfmpegOnce,
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
seekCompositionTimelineOnly,
|
|
69
|
+
settleCompositionSeek
|
|
70
|
+
} from "./chunk-U4BMRIE6.js";
|
|
67
71
|
import "./chunk-FH7WODJH.js";
|
|
68
|
-
import "./chunk-
|
|
72
|
+
import "./chunk-UAJCTEK2.js";
|
|
69
73
|
import "./chunk-MOEGCMKI.js";
|
|
70
|
-
import "./chunk-
|
|
74
|
+
import "./chunk-7AUMTARQ.js";
|
|
71
75
|
import "./chunk-DKPNNYBZ.js";
|
|
72
|
-
import "./chunk-
|
|
76
|
+
import "./chunk-DTXDQ6OP.js";
|
|
73
77
|
import "./chunk-K2FLNJVB.js";
|
|
74
78
|
import "./chunk-442JNXRM.js";
|
|
75
79
|
import "./chunk-EHSBBBR2.js";
|
|
76
80
|
import "./chunk-DQBY7FRR.js";
|
|
77
81
|
import {
|
|
78
82
|
resolveLocalBrowserGpuMode
|
|
79
|
-
} from "./chunk-
|
|
80
|
-
import "./chunk-
|
|
83
|
+
} from "./chunk-RVZNSKRH.js";
|
|
84
|
+
import "./chunk-RPUIMFHF.js";
|
|
81
85
|
import "./chunk-XT7X6QCP.js";
|
|
82
86
|
import "./chunk-4YYJOFKS.js";
|
|
83
87
|
import "./chunk-HVW7ABXD.js";
|
|
84
|
-
import "./chunk-
|
|
88
|
+
import "./chunk-Y2M6XSNK.js";
|
|
85
89
|
import {
|
|
86
90
|
runWithConcurrencyLimit
|
|
87
91
|
} from "./chunk-JHOCK3DG.js";
|
|
88
|
-
import "./chunk-
|
|
89
|
-
import "./chunk-
|
|
92
|
+
import "./chunk-ID5AJ4L3.js";
|
|
93
|
+
import "./chunk-YRAJDFIN.js";
|
|
90
94
|
import "./chunk-AWDFDFI3.js";
|
|
91
95
|
import "./chunk-P6LJ4Y32.js";
|
|
92
96
|
import "./chunk-GMECXFAN.js";
|
|
93
|
-
import "./chunk-
|
|
97
|
+
import "./chunk-7L37AB57.js";
|
|
94
98
|
import "./chunk-EOVYQ3IG.js";
|
|
95
|
-
import "./chunk-
|
|
96
|
-
import "./chunk-
|
|
99
|
+
import "./chunk-77QM6YRQ.js";
|
|
100
|
+
import "./chunk-6IOBAOU7.js";
|
|
97
101
|
import "./chunk-VWG7OQKU.js";
|
|
98
102
|
import {
|
|
99
103
|
defineCommand
|
|
100
104
|
} from "./chunk-S3S4TGEH.js";
|
|
101
105
|
import "./chunk-54HJ63Q2.js";
|
|
102
106
|
import {
|
|
107
|
+
CliRuntimeError,
|
|
103
108
|
failCommand
|
|
104
109
|
} from "./chunk-JVBRJMOP.js";
|
|
105
110
|
import {
|
|
@@ -108,23 +113,26 @@ import {
|
|
|
108
113
|
import "./chunk-KLIKCX6Q.js";
|
|
109
114
|
import "./chunk-EVMY7IPL.js";
|
|
110
115
|
import "./chunk-7FMUTGOH.js";
|
|
111
|
-
import "./chunk-
|
|
116
|
+
import "./chunk-7M7TMM4S.js";
|
|
112
117
|
import "./chunk-IZCW2NKT.js";
|
|
113
118
|
import {
|
|
114
119
|
createRuntimeStartTimeResolver,
|
|
115
120
|
isClipVisibleAt,
|
|
116
121
|
isInClipWindow
|
|
117
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-RNZEQTWZ.js";
|
|
118
123
|
import "./chunk-RQVDTPGD.js";
|
|
119
|
-
import "./chunk-
|
|
124
|
+
import "./chunk-BRTDLVK3.js";
|
|
120
125
|
import {
|
|
121
126
|
readElementRateSpec,
|
|
122
127
|
sourceTimeAt,
|
|
123
128
|
timeAtSourceTime
|
|
124
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-UOZX5W5T.js";
|
|
125
130
|
import "./chunk-VC76R6W2.js";
|
|
126
131
|
import "./chunk-UJKQWGFF.js";
|
|
127
|
-
import
|
|
132
|
+
import {
|
|
133
|
+
topLevelElements,
|
|
134
|
+
trackKindOf
|
|
135
|
+
} from "./chunk-B2A56S5C.js";
|
|
128
136
|
import "./chunk-OFQWTKPW.js";
|
|
129
137
|
import "./chunk-DPVXBVLL.js";
|
|
130
138
|
import "./chunk-3GXQPCJC.js";
|
|
@@ -142,23 +150,26 @@ import "./chunk-XT6MXC7A.js";
|
|
|
142
150
|
import "./chunk-4UMPIPCQ.js";
|
|
143
151
|
import {
|
|
144
152
|
lintProject
|
|
145
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-Q447CX26.js";
|
|
146
154
|
import "./chunk-VAS6HQX3.js";
|
|
147
155
|
import "./chunk-6BNTGNGD.js";
|
|
148
|
-
import "./chunk-
|
|
156
|
+
import "./chunk-RUOG4VB7.js";
|
|
149
157
|
import "./chunk-MMQ52NIZ.js";
|
|
150
158
|
import "./chunk-BSQ7XANM.js";
|
|
151
159
|
import {
|
|
152
160
|
parseHTML
|
|
153
161
|
} from "./chunk-SDYDNHEE.js";
|
|
154
162
|
import "./chunk-IXLUTE6N.js";
|
|
155
|
-
import "./chunk-
|
|
163
|
+
import "./chunk-I5JRXMCV.js";
|
|
156
164
|
import "./chunk-W2LGJSEN.js";
|
|
165
|
+
import {
|
|
166
|
+
withMeta
|
|
167
|
+
} from "./chunk-FRLTKTOR.js";
|
|
157
168
|
import "./chunk-K4WIOZFP.js";
|
|
158
169
|
import "./chunk-XUXGIA7H.js";
|
|
159
170
|
import "./chunk-WERLJGIC.js";
|
|
160
171
|
import "./chunk-ISN5GRYI.js";
|
|
161
|
-
import "./chunk-
|
|
172
|
+
import "./chunk-LDW3KVGK.js";
|
|
162
173
|
import {
|
|
163
174
|
normalizeErrorMessage
|
|
164
175
|
} from "./chunk-KNU5COPB.js";
|
|
@@ -182,6 +193,15 @@ function sampleSnapshotRange([start, end], frames, duration, exclusiveEnd = fals
|
|
|
182
193
|
const last = exclusiveEnd || end === duration ? end - Math.min(1e-3, (end - start) / (frames * 2)) : end;
|
|
183
194
|
return Array.from({ length: frames }, (_, i) => start + (last - start) * i / (frames - 1));
|
|
184
195
|
}
|
|
196
|
+
function snapshotStartResolver(document2, durations) {
|
|
197
|
+
return createRuntimeStartTimeResolver({
|
|
198
|
+
documentRef: document2,
|
|
199
|
+
timelineRegistry: Object.fromEntries(
|
|
200
|
+
Object.entries(durations).map(([key, value]) => [key, { duration: () => value }])
|
|
201
|
+
),
|
|
202
|
+
includeAuthoredTimingAttrs: true
|
|
203
|
+
});
|
|
204
|
+
}
|
|
185
205
|
function resolveSnapshotCompositionRange(html, durations, id, duration) {
|
|
186
206
|
const { document: document2 } = parseHTML(html);
|
|
187
207
|
const matches = Array.from(document2.querySelectorAll("[data-composition-id]")).filter(
|
|
@@ -191,14 +211,7 @@ function resolveSnapshotCompositionRange(html, durations, id, duration) {
|
|
|
191
211
|
throw new Error(
|
|
192
212
|
`Composition ID ${JSON.stringify(id)} matched ${matches.length} elements; expected exactly one`
|
|
193
213
|
);
|
|
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
|
-
});
|
|
214
|
+
const resolver = snapshotStartResolver(document2, durations);
|
|
202
215
|
let start = 0, end = duration;
|
|
203
216
|
for (let el = matches[0]; el; el = el.parentElement) {
|
|
204
217
|
if (!el.hasAttribute("data-composition-id") && !el.hasAttribute("data-start")) continue;
|
|
@@ -219,6 +232,208 @@ import { randomUUID } from "crypto";
|
|
|
219
232
|
import { existsSync, mkdtempSync, readFileSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
220
233
|
import { tmpdir } from "os";
|
|
221
234
|
import { resolve, join, relative, isAbsolute, basename, posix } from "path";
|
|
235
|
+
|
|
236
|
+
// src/commands/snapshotReview.ts
|
|
237
|
+
var REVIEW_SETTLE_SEC = 0.3;
|
|
238
|
+
var REVIEW_MID_GAP_SEC = 0.5;
|
|
239
|
+
var REVIEW_SEAM_OFFSETS = [-0.2, -0.1, 0, 0.1, 0.2];
|
|
240
|
+
var REVIEW_PHONE_WIDTH = 360;
|
|
241
|
+
var SAME_TIME_SEC = 0.05;
|
|
242
|
+
var EVEN_BEATS = 5;
|
|
243
|
+
function roundMs(value) {
|
|
244
|
+
return Math.round(value * 1e3) / 1e3;
|
|
245
|
+
}
|
|
246
|
+
function sceneId(el, index) {
|
|
247
|
+
return el.id || el.getAttribute("data-composition-id") || el.getAttribute("data-layout-name") || `${el.tagName.toLowerCase()}-${index + 1}`;
|
|
248
|
+
}
|
|
249
|
+
function resolveReviewTimeline(html, durations, duration, compositionId) {
|
|
250
|
+
const bounds = compositionId ? resolveSnapshotCompositionRange(html, durations, compositionId, duration) : [0, duration];
|
|
251
|
+
const { document: document2 } = parseHTML(html);
|
|
252
|
+
const target = compositionId ? Array.from(document2.querySelectorAll("[data-composition-id]")).find(
|
|
253
|
+
(el) => el.getAttribute("data-composition-id") === compositionId
|
|
254
|
+
) : document2.querySelector("[data-composition-id]");
|
|
255
|
+
if (!target) {
|
|
256
|
+
return { window: bounds, scenes: [], beats: [], notes: ["No composition root found."] };
|
|
257
|
+
}
|
|
258
|
+
const resolver = snapshotStartResolver(document2, durations);
|
|
259
|
+
const span = (el) => {
|
|
260
|
+
const start = resolver.resolveStartForElement(el, 0);
|
|
261
|
+
if (!Number.isFinite(start)) return null;
|
|
262
|
+
const length = resolver.resolveDurationForElement(el);
|
|
263
|
+
const from = Math.max(bounds[0], start);
|
|
264
|
+
const to = Math.min(bounds[1], length != null ? start + length : bounds[1]);
|
|
265
|
+
return to > from ? [roundMs(from), roundMs(to)] : null;
|
|
266
|
+
};
|
|
267
|
+
const scenes = [];
|
|
268
|
+
const rows = topLevelElements(toDomNode(target)).filter((node) => {
|
|
269
|
+
const kind = trackKindOf(node).kind;
|
|
270
|
+
return kind === "video" || kind === "graphics";
|
|
271
|
+
});
|
|
272
|
+
rows.forEach((node, index) => {
|
|
273
|
+
const interval = span(node.el);
|
|
274
|
+
if (interval)
|
|
275
|
+
scenes.push({ id: sceneId(node.el, index), start: interval[0], end: interval[1] });
|
|
276
|
+
});
|
|
277
|
+
const beats = [];
|
|
278
|
+
const notes = [];
|
|
279
|
+
for (const el of Array.from(target.querySelectorAll("[data-beat]"))) {
|
|
280
|
+
const name = el.getAttribute("data-beat")?.trim() || sceneId(el, beats.length);
|
|
281
|
+
const timed = el.hasAttribute("data-start") || el.hasAttribute("data-composition-id");
|
|
282
|
+
const interval = timed ? span(el) : null;
|
|
283
|
+
if (!interval) {
|
|
284
|
+
notes.push(`data-beat="${name}" was skipped: give it a data-start so the beat has a time.`);
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
beats.push({ time: settledTime(interval[0], interval[1]), label: `beat:${name}` });
|
|
288
|
+
}
|
|
289
|
+
scenes.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
290
|
+
return { window: bounds, scenes, beats, notes };
|
|
291
|
+
}
|
|
292
|
+
function sceneBeats(scene) {
|
|
293
|
+
const settled = settledTime(scene.start, scene.end);
|
|
294
|
+
const middle = roundMs((scene.start + scene.end) / 2);
|
|
295
|
+
const beats = [{ time: settled, label: scene.id }];
|
|
296
|
+
return middle - settled >= REVIEW_MID_GAP_SEC ? [...beats, { time: middle, label: `${scene.id} mid` }] : beats;
|
|
297
|
+
}
|
|
298
|
+
function settledTime(start, end) {
|
|
299
|
+
return roundMs(Math.min(start + REVIEW_SETTLE_SEC, (start + end) / 2));
|
|
300
|
+
}
|
|
301
|
+
function planReview(timeline, lastFrame) {
|
|
302
|
+
const { window: bounds, scenes } = timeline;
|
|
303
|
+
const notes = [...timeline.notes];
|
|
304
|
+
const clamp = (time) => roundMs(Math.min(Math.max(time, bounds[0]), lastFrame));
|
|
305
|
+
const distinctStarts = mergeBeats(
|
|
306
|
+
scenes.map((scene) => ({ time: scene.start, label: scene.id }))
|
|
307
|
+
);
|
|
308
|
+
const beats = mergeBeats([
|
|
309
|
+
...distinctStarts.length >= 2 ? scenes.flatMap(sceneBeats) : evenBeats(bounds, notes),
|
|
310
|
+
...timeline.beats
|
|
311
|
+
]).map((beat) => ({ ...beat, time: clamp(beat.time) }));
|
|
312
|
+
const seams = seamTimes(scenes, bounds).map((time) => ({
|
|
313
|
+
time,
|
|
314
|
+
...seamSides(scenes, time),
|
|
315
|
+
times: REVIEW_SEAM_OFFSETS.map((offset) => clamp(time + offset))
|
|
316
|
+
}));
|
|
317
|
+
return { window: bounds, scenes, beats, seams, notes };
|
|
318
|
+
}
|
|
319
|
+
function evenBeats(bounds, notes) {
|
|
320
|
+
notes.push(
|
|
321
|
+
`Fewer than two scene starts; ${EVEN_BEATS} beats are spread evenly instead. Time scenes as sub-composition hosts or clips to review each one.`
|
|
322
|
+
);
|
|
323
|
+
const [start, end] = bounds;
|
|
324
|
+
return Array.from({ length: EVEN_BEATS }, (_, index) => {
|
|
325
|
+
const time = roundMs(start + (index + 0.5) / EVEN_BEATS * (end - start));
|
|
326
|
+
return { time, label: `t=${time}` };
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
function mergeBeats(beats) {
|
|
330
|
+
const merged = [];
|
|
331
|
+
for (const beat of [...beats].sort((a, b) => a.time - b.time)) {
|
|
332
|
+
const same = merged.find((entry) => Math.abs(entry.time - beat.time) < SAME_TIME_SEC);
|
|
333
|
+
if (same) same.label = `${same.label} + ${beat.label}`;
|
|
334
|
+
else merged.push({ ...beat });
|
|
335
|
+
}
|
|
336
|
+
return merged;
|
|
337
|
+
}
|
|
338
|
+
function seamTimes(scenes, bounds) {
|
|
339
|
+
const inside = (time) => time > bounds[0] + SAME_TIME_SEC && time < bounds[1] - SAME_TIME_SEC;
|
|
340
|
+
const starts = scenes.map((scene) => scene.start).filter(inside);
|
|
341
|
+
const ends = scenes.map((scene) => scene.end).filter(inside).filter((end) => !starts.some((start) => Math.abs(start - end) < SAME_TIME_SEC));
|
|
342
|
+
const seams = [];
|
|
343
|
+
for (const time of [...starts, ...ends].sort((a, b) => a - b)) {
|
|
344
|
+
if (!seams.some((seam) => Math.abs(seam - time) < SAME_TIME_SEC)) seams.push(time);
|
|
345
|
+
}
|
|
346
|
+
return seams;
|
|
347
|
+
}
|
|
348
|
+
function seamSides(scenes, time) {
|
|
349
|
+
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];
|
|
350
|
+
const after = scenes.filter((scene) => Math.abs(scene.start - time) < SAME_TIME_SEC).sort((a, b) => a.end - b.end)[0];
|
|
351
|
+
const next = after ?? scenes.find((scene) => scene.start > time);
|
|
352
|
+
return { from: before?.id ?? null, to: next?.id ?? null };
|
|
353
|
+
}
|
|
354
|
+
function pad(index) {
|
|
355
|
+
return String(index).padStart(2, "0");
|
|
356
|
+
}
|
|
357
|
+
function stamp(time) {
|
|
358
|
+
return `${Number(time.toFixed(3))}s`;
|
|
359
|
+
}
|
|
360
|
+
var SEAM_TILE_LABELS = ["cut -0.2", "-0.1", "cut", "+0.1", "+0.2"];
|
|
361
|
+
function reviewFrames(plan) {
|
|
362
|
+
const beats = plan.beats.map((beat, index) => ({
|
|
363
|
+
role: "beat",
|
|
364
|
+
index: index + 1,
|
|
365
|
+
time: beat.time,
|
|
366
|
+
label: beat.label,
|
|
367
|
+
file: `beat-${pad(index + 1)}-at-${stamp(beat.time)}.png`
|
|
368
|
+
}));
|
|
369
|
+
const seams = plan.seams.flatMap(
|
|
370
|
+
(seam, index) => seam.times.map((time, slot) => ({
|
|
371
|
+
role: "seam",
|
|
372
|
+
index: index + 1,
|
|
373
|
+
time,
|
|
374
|
+
label: slot === 2 ? `cut ${seam.from ?? "start"} -> ${seam.to ?? "end"}` : SEAM_TILE_LABELS[slot] ?? "",
|
|
375
|
+
file: `seam-${pad(index + 1)}-${slot + 1}-at-${stamp(time)}.png`
|
|
376
|
+
}))
|
|
377
|
+
);
|
|
378
|
+
return [...beats, ...seams];
|
|
379
|
+
}
|
|
380
|
+
var BEAT_SHEET_PAGE = 16;
|
|
381
|
+
async function writeReviewSheets(dir, frames, written) {
|
|
382
|
+
const { createContactSheet } = await import("./contactSheet-CAGMKI3E.js");
|
|
383
|
+
const { join: join2 } = await import("path");
|
|
384
|
+
const captured = frames.flatMap((frame) => {
|
|
385
|
+
const path = written(frame);
|
|
386
|
+
return path ? [{ frame, path }] : [];
|
|
387
|
+
});
|
|
388
|
+
const beats = captured.filter((entry) => entry.frame.role === "beat");
|
|
389
|
+
const beatLabel = ({ frame }) => `${stamp(frame.time)} ${frame.label}`;
|
|
390
|
+
const pages = async (name, cellWidth, colsFor) => {
|
|
391
|
+
const sheets = [];
|
|
392
|
+
for (let start = 0; start < beats.length; start += BEAT_SHEET_PAGE) {
|
|
393
|
+
const page = beats.slice(start, start + BEAT_SHEET_PAGE);
|
|
394
|
+
const suffix = beats.length > BEAT_SHEET_PAGE ? `-${start / BEAT_SHEET_PAGE + 1}` : "";
|
|
395
|
+
const sheet = await createContactSheet(
|
|
396
|
+
page.map((entry) => entry.path),
|
|
397
|
+
join2(dir, `${name}${suffix}.jpg`),
|
|
398
|
+
{
|
|
399
|
+
cols: colsFor(page.length),
|
|
400
|
+
maxImages: page.length,
|
|
401
|
+
cellWidth,
|
|
402
|
+
labelMode: "custom",
|
|
403
|
+
labels: page.map(beatLabel)
|
|
404
|
+
}
|
|
405
|
+
);
|
|
406
|
+
if (sheet) sheets.push(sheet);
|
|
407
|
+
}
|
|
408
|
+
return sheets;
|
|
409
|
+
};
|
|
410
|
+
const seams = [];
|
|
411
|
+
const seamNumbers = [
|
|
412
|
+
...new Set(captured.filter((e) => e.frame.role === "seam").map((e) => e.frame.index))
|
|
413
|
+
];
|
|
414
|
+
for (const index of seamNumbers) {
|
|
415
|
+
const strip = captured.filter((e) => e.frame.role === "seam" && e.frame.index === index);
|
|
416
|
+
const sheet = await createContactSheet(
|
|
417
|
+
strip.map((entry) => entry.path),
|
|
418
|
+
join2(dir, `review-seam-${pad(index)}.jpg`),
|
|
419
|
+
{
|
|
420
|
+
cols: strip.length,
|
|
421
|
+
maxImages: strip.length,
|
|
422
|
+
cellWidth: 384,
|
|
423
|
+
labelMode: "custom",
|
|
424
|
+
labels: strip.map(({ frame }) => `${stamp(frame.time)} ${frame.label}`)
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
if (sheet) seams.push(sheet);
|
|
428
|
+
}
|
|
429
|
+
return {
|
|
430
|
+
beats: await pages("review-beats", 480, (count) => count <= 3 ? count : count <= 9 ? 3 : 4),
|
|
431
|
+
seams,
|
|
432
|
+
phone: await pages("review-phone", REVIEW_PHONE_WIDTH, (count) => Math.min(4, count))
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/commands/snapshot.ts
|
|
222
437
|
function orbitStageSource() {
|
|
223
438
|
return `function(cam) {
|
|
224
439
|
var root = document.querySelector("[data-composition-id]")
|
|
@@ -479,7 +694,8 @@ function serveCapturePage(projectDir, html, proxy) {
|
|
|
479
694
|
return serveStaticProjectHtml(projectDir, html, void 0, [], proxy === true);
|
|
480
695
|
}
|
|
481
696
|
async function captureSnapshots(projectDir, opts) {
|
|
482
|
-
const
|
|
697
|
+
const log = opts.log ?? ((message) => console.log(message));
|
|
698
|
+
const { bundleWithLocalizedFonts } = await import("./bundleWithLocalizedFonts-TT32MZBO.js");
|
|
483
699
|
const capture = await captureArtifactRevision(projectDir).catch(warnSnapshotsNotRecorded);
|
|
484
700
|
const invocation = randomUUID();
|
|
485
701
|
const artifacts = [];
|
|
@@ -487,6 +703,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
487
703
|
const warnings = [];
|
|
488
704
|
let completed = false;
|
|
489
705
|
const numFrames = opts.frames ?? 5;
|
|
706
|
+
let review;
|
|
707
|
+
let reviewList;
|
|
708
|
+
const reviewPaths = /* @__PURE__ */ new Map();
|
|
490
709
|
const html = await bundleWithLocalizedFonts(projectDir);
|
|
491
710
|
const server = await serveCapturePage(projectDir, html, opts.autoProxy);
|
|
492
711
|
const savedPaths = [];
|
|
@@ -518,10 +737,10 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
518
737
|
const parts = [`${fontReport.loaded.length} loaded`];
|
|
519
738
|
if (fontReport.errored.length > 0) parts.push(`${fontReport.errored.length} failed`);
|
|
520
739
|
if (fontReport.unused.length > 0) parts.push(`${fontReport.unused.length} unused`);
|
|
521
|
-
|
|
740
|
+
log(`
|
|
522
741
|
${c.dim("Fonts:")} ${parts.join(", ")}`);
|
|
523
742
|
if (fontReport.errored.length > 0) {
|
|
524
|
-
|
|
743
|
+
log(` ${c.error("Fonts FAILED:")} ${fontReport.errored.join(", ")}`);
|
|
525
744
|
}
|
|
526
745
|
}
|
|
527
746
|
if (fontReport.errored.length)
|
|
@@ -537,19 +756,20 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
537
756
|
return 0;
|
|
538
757
|
});
|
|
539
758
|
if (duration <= 0 && !opts.at?.length) {
|
|
540
|
-
return [];
|
|
759
|
+
return { paths: [] };
|
|
541
760
|
}
|
|
761
|
+
const readTiming = () => page.evaluate(() => ({
|
|
762
|
+
html: document.documentElement.outerHTML,
|
|
763
|
+
durations: Object.fromEntries(
|
|
764
|
+
Object.entries(window.__timelines ?? {}).map(([id, timeline]) => [
|
|
765
|
+
id,
|
|
766
|
+
Number(timeline.duration?.())
|
|
767
|
+
])
|
|
768
|
+
)
|
|
769
|
+
}));
|
|
542
770
|
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
|
-
}));
|
|
771
|
+
if (opts.composition && !opts.review) {
|
|
772
|
+
const timing = await readTiming();
|
|
553
773
|
range = resolveSnapshotCompositionRange(
|
|
554
774
|
timing.html,
|
|
555
775
|
timing.durations,
|
|
@@ -557,7 +777,18 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
557
777
|
duration
|
|
558
778
|
);
|
|
559
779
|
}
|
|
560
|
-
|
|
780
|
+
if (opts.review) {
|
|
781
|
+
const timing = await readTiming();
|
|
782
|
+
const timeline = resolveReviewTimeline(
|
|
783
|
+
timing.html,
|
|
784
|
+
timing.durations,
|
|
785
|
+
duration,
|
|
786
|
+
opts.composition
|
|
787
|
+
);
|
|
788
|
+
review = planReview(timeline, Math.min(timeline.window[1], duration) - 1 / 30);
|
|
789
|
+
reviewList = reviewFrames(review);
|
|
790
|
+
}
|
|
791
|
+
const { times: positions, appendedTail } = reviewList ? { times: reviewList.map((frame) => frame.time), appendedTail: false } : range ? {
|
|
561
792
|
times: sampleSnapshotRange(range, numFrames, duration, !!opts.composition),
|
|
562
793
|
appendedTail: false
|
|
563
794
|
} : computeSnapshotTimes(duration, {
|
|
@@ -566,11 +797,15 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
566
797
|
includeEnd: opts.includeEnd
|
|
567
798
|
});
|
|
568
799
|
if (range)
|
|
569
|
-
|
|
800
|
+
log(
|
|
570
801
|
` Sampling ${positions.length} frames within ${range[0]}\u2013${range[1]}s${opts.composition ? ` (composition ${opts.composition})` : ""}`
|
|
571
802
|
);
|
|
803
|
+
if (review)
|
|
804
|
+
log(
|
|
805
|
+
` 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})` : ""}`
|
|
806
|
+
);
|
|
572
807
|
if (appendedTail) {
|
|
573
|
-
|
|
808
|
+
log(
|
|
574
809
|
` ${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
810
|
);
|
|
576
811
|
}
|
|
@@ -592,7 +827,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
592
827
|
let syncVideoFrameVisibility = null;
|
|
593
828
|
let extractMediaMetadata = null;
|
|
594
829
|
try {
|
|
595
|
-
const engine = await import("./src-
|
|
830
|
+
const engine = await import("./src-DCVSEODX.js");
|
|
596
831
|
injectVideoFramesBatch = engine.injectVideoFramesBatch;
|
|
597
832
|
syncVideoFrameVisibility = engine.syncVideoFrameVisibility;
|
|
598
833
|
extractMediaMetadata = engine.extractMediaMetadata;
|
|
@@ -617,7 +852,8 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
617
852
|
}
|
|
618
853
|
for (let i = 0; i < positions.length; i++) {
|
|
619
854
|
const time = positions[i];
|
|
620
|
-
|
|
855
|
+
const seekOptions = { exactTime: true };
|
|
856
|
+
await seekCompositionTimelineOnly(page, time, seekOptions);
|
|
621
857
|
if (cameraExpr) await page.evaluate(cameraExpr);
|
|
622
858
|
if (injectVideoFramesBatch && syncVideoFrameVisibility) {
|
|
623
859
|
const candidates = await page.evaluate(() => {
|
|
@@ -727,10 +963,12 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
727
963
|
);
|
|
728
964
|
}
|
|
729
965
|
}
|
|
966
|
+
await settleCompositionSeek(page, seekOptions);
|
|
730
967
|
await recaptureSnapshotComposite(page);
|
|
731
968
|
const timeLabel = formatSnapshotTimestamp(time);
|
|
732
969
|
const slot = opts.keep ? `at-${timeLabel}` : `${String(i).padStart(2, "0")}-at-${timeLabel}`;
|
|
733
|
-
const
|
|
970
|
+
const reviewFrame = reviewList?.[i];
|
|
971
|
+
const filename = reviewFrame ? reviewFrame.file : opts.keep ? `${slot}.png` : `frame-${slot}.png`;
|
|
734
972
|
const framePath = join(snapshotDir, filename);
|
|
735
973
|
let crop;
|
|
736
974
|
if (opts.zoom) {
|
|
@@ -769,9 +1007,11 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
769
1007
|
zoom: opts.zoom,
|
|
770
1008
|
zoomScale: opts.zoom ? opts.zoomScale ?? DEFAULT_ZOOM_SCALE : 1,
|
|
771
1009
|
angle: opts.angle,
|
|
772
|
-
browserGpuMode: opts.browserGpuMode
|
|
1010
|
+
browserGpuMode: opts.browserGpuMode,
|
|
1011
|
+
...reviewFrame ? { review: { role: reviewFrame.role, label: reviewFrame.label } } : {}
|
|
773
1012
|
}
|
|
774
1013
|
});
|
|
1014
|
+
if (reviewFrame) reviewPaths.set(reviewFrame, framePath);
|
|
775
1015
|
if (opts.against) {
|
|
776
1016
|
const refPng = await extractVideoFrameToBuffer(opts.against, time);
|
|
777
1017
|
if (!refPng) {
|
|
@@ -807,20 +1047,32 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
807
1047
|
artifacts,
|
|
808
1048
|
opts.zoom,
|
|
809
1049
|
warnings,
|
|
810
|
-
completed
|
|
1050
|
+
completed,
|
|
1051
|
+
log
|
|
811
1052
|
) : false;
|
|
812
1053
|
if (!recorded) {
|
|
813
1054
|
const paths = [...replaced, ...artifacts.map((artifact) => artifact.image)];
|
|
814
1055
|
if (paths.length > 0) await forgetRecordedArtifacts(projectDir, paths).catch(() => void 0);
|
|
815
1056
|
}
|
|
816
1057
|
}
|
|
817
|
-
return
|
|
1058
|
+
return {
|
|
1059
|
+
paths: savedPaths,
|
|
1060
|
+
...review && reviewList ? {
|
|
1061
|
+
review: {
|
|
1062
|
+
plan: review,
|
|
1063
|
+
frames: reviewList.flatMap((frame) => {
|
|
1064
|
+
const path = reviewPaths.get(frame);
|
|
1065
|
+
return path ? [{ ...frame, path }] : [];
|
|
1066
|
+
})
|
|
1067
|
+
}
|
|
1068
|
+
} : {}
|
|
1069
|
+
};
|
|
818
1070
|
}
|
|
819
1071
|
function warnSnapshotsNotRecorded(error) {
|
|
820
1072
|
console.warn(` ${c.warn("\u26A0")} Snapshots were not recorded: ${normalizeErrorMessage(error)}`);
|
|
821
1073
|
return void 0;
|
|
822
1074
|
}
|
|
823
|
-
async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, warnings, completed) {
|
|
1075
|
+
async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, warnings, completed, log) {
|
|
824
1076
|
const records = await recordArtifacts(
|
|
825
1077
|
projectDir,
|
|
826
1078
|
capture,
|
|
@@ -833,10 +1085,65 @@ async function recordSnapshotArtifacts(projectDir, capture, artifacts, zoom, war
|
|
|
833
1085
|
).catch(warnSnapshotsNotRecorded);
|
|
834
1086
|
const record = records?.[0];
|
|
835
1087
|
if (!record) return false;
|
|
836
|
-
|
|
837
|
-
|
|
1088
|
+
log(` Revision: ${record.revision ?? "none"} (${record.attribution})`);
|
|
1089
|
+
log(` State: ${join(projectDir, ".hyperframes", "video-state.json")}`);
|
|
838
1090
|
return true;
|
|
839
1091
|
}
|
|
1092
|
+
function snapshotEnvelope(projectDir, outputDir, captured, extra) {
|
|
1093
|
+
const review = captured.review;
|
|
1094
|
+
const frames = review ? review.frames.map((frame) => ({
|
|
1095
|
+
path: frame.path,
|
|
1096
|
+
time: frame.time,
|
|
1097
|
+
role: frame.role,
|
|
1098
|
+
label: frame.label
|
|
1099
|
+
})) : captured.paths.map((path) => ({ path: resolve(projectDir, path), time: timeFromName(path) }));
|
|
1100
|
+
return {
|
|
1101
|
+
ok: true,
|
|
1102
|
+
outputDir,
|
|
1103
|
+
frames,
|
|
1104
|
+
contactSheets: extra.contactSheets.map((sheet) => resolve(sheet)),
|
|
1105
|
+
...extra.describedPath ? { descriptions: extra.describedPath } : {},
|
|
1106
|
+
...review ? {
|
|
1107
|
+
review: {
|
|
1108
|
+
window: review.plan.window,
|
|
1109
|
+
scenes: review.plan.scenes,
|
|
1110
|
+
beats: review.plan.beats.map((beat, index) => ({
|
|
1111
|
+
...beat,
|
|
1112
|
+
path: review.frames.find(
|
|
1113
|
+
(frame) => frame.role === "beat" && frame.index === index + 1
|
|
1114
|
+
)?.path
|
|
1115
|
+
})),
|
|
1116
|
+
seams: review.plan.seams.map((seam, index) => ({
|
|
1117
|
+
...seam,
|
|
1118
|
+
paths: review.frames.filter((frame) => frame.role === "seam" && frame.index === index + 1).map((frame) => frame.path),
|
|
1119
|
+
sheet: extra.reviewSheets?.seams[index]
|
|
1120
|
+
})),
|
|
1121
|
+
sheets: extra.reviewSheets ?? { beats: [], seams: [], phone: [] },
|
|
1122
|
+
notes: review.plan.notes
|
|
1123
|
+
}
|
|
1124
|
+
} : {}
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
function timeFromName(path) {
|
|
1128
|
+
const match = /at-([\d.]+)s\.png$/.exec(path);
|
|
1129
|
+
return match ? Number(match[1]) : null;
|
|
1130
|
+
}
|
|
1131
|
+
function printReview(review, sheets, log) {
|
|
1132
|
+
const beats = review.plan.beats.map(
|
|
1133
|
+
(beat) => `${formatSnapshotTimestamp(beat.time)} ${beat.label}`
|
|
1134
|
+
);
|
|
1135
|
+
log(` Beat sheet (settled frame per scene): ${sheets.beats.join(", ") || "none"}`);
|
|
1136
|
+
log(` ${c.dim(beats.join(" \xB7 "))}`);
|
|
1137
|
+
review.plan.seams.forEach((seam, index) => {
|
|
1138
|
+
const sides = `${seam.from ?? "start"} -> ${seam.to ?? "end"}`;
|
|
1139
|
+
const strip = sheets.seams[index] ?? "not written";
|
|
1140
|
+
log(` Seam ${index + 1} at ${formatSnapshotTimestamp(seam.time)} (${sides}): ${strip}`);
|
|
1141
|
+
});
|
|
1142
|
+
log(
|
|
1143
|
+
` Phone sheet (beats at ${REVIEW_PHONE_WIDTH} px wide): ${sheets.phone.join(", ") || "none"}`
|
|
1144
|
+
);
|
|
1145
|
+
for (const note of review.plan.notes) log(` ${c.dim(note)}`);
|
|
1146
|
+
}
|
|
840
1147
|
var snapshot_default = defineCommand({
|
|
841
1148
|
meta: {
|
|
842
1149
|
name: "snapshot",
|
|
@@ -902,6 +1209,16 @@ var snapshot_default = defineCommand({
|
|
|
902
1209
|
type: "string",
|
|
903
1210
|
description: "Reference video (e.g. footage being rebuilt): also save its frame at each captured time and a render|reference pair sheet"
|
|
904
1211
|
},
|
|
1212
|
+
review: {
|
|
1213
|
+
type: "boolean",
|
|
1214
|
+
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.",
|
|
1215
|
+
default: false
|
|
1216
|
+
},
|
|
1217
|
+
json: {
|
|
1218
|
+
type: "boolean",
|
|
1219
|
+
description: "Print one JSON envelope (paths, times, sheets; the review plan under --review)",
|
|
1220
|
+
default: false
|
|
1221
|
+
},
|
|
905
1222
|
describe: {
|
|
906
1223
|
type: "string",
|
|
907
1224
|
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 +1235,22 @@ var snapshot_default = defineCommand({
|
|
|
918
1235
|
}
|
|
919
1236
|
},
|
|
920
1237
|
async run({ args }) {
|
|
1238
|
+
const asJson = args.json === true;
|
|
1239
|
+
const log = (message) => asJson ? console.error(message) : console.log(message);
|
|
1240
|
+
const fail = (message) => {
|
|
1241
|
+
if (asJson) console.log(JSON.stringify(withMeta({ ok: false, error: message }), null, 2));
|
|
1242
|
+
else log(message);
|
|
1243
|
+
failCommand();
|
|
1244
|
+
};
|
|
921
1245
|
if ([args.at, args.range, args.composition].filter((value) => value !== void 0).length > 1)
|
|
922
1246
|
throw new Error("Use only one of --at, --range, or --composition");
|
|
1247
|
+
const reviewMode = args.review === true;
|
|
1248
|
+
if (reviewMode) {
|
|
1249
|
+
const clash = ["at", "range", "zoom", "keep", "against"].find(
|
|
1250
|
+
(flag) => args[flag] !== void 0 && args[flag] !== false
|
|
1251
|
+
);
|
|
1252
|
+
if (clash) throw new Error(`--review picks its own frames; drop --${clash}`);
|
|
1253
|
+
}
|
|
923
1254
|
const frames = parseInt(args.frames, 10) || 5;
|
|
924
1255
|
const range = args.range === void 0 ? void 0 : parseSnapshotRange(String(args.range));
|
|
925
1256
|
const composition = args.composition === void 0 ? void 0 : String(args.composition).trim();
|
|
@@ -928,28 +1259,32 @@ var snapshot_default = defineCommand({
|
|
|
928
1259
|
const lintResult = await lintProject(project.dir);
|
|
929
1260
|
if (hasDefinitiveEntryMismatch(lintResult)) {
|
|
930
1261
|
const candidate = definitiveEntryMismatchComposition(lintResult);
|
|
931
|
-
|
|
1262
|
+
log("");
|
|
932
1263
|
for (const line of formatLintFindings(lintResult, { errorsFirst: true })) {
|
|
933
|
-
|
|
1264
|
+
log(line);
|
|
934
1265
|
}
|
|
935
|
-
|
|
936
|
-
|
|
1266
|
+
log("");
|
|
1267
|
+
log(c.error(" Aborting snapshot because the default index.html entry is blank."));
|
|
937
1268
|
if (candidate && posix.basename(candidate) === "index.html") {
|
|
938
1269
|
const candidateDir = posix.dirname(candidate);
|
|
939
1270
|
const target = `<project>/${candidateDir}`;
|
|
940
|
-
|
|
1271
|
+
log(
|
|
941
1272
|
c.dim(
|
|
942
1273
|
` 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
1274
|
)
|
|
944
1275
|
);
|
|
945
1276
|
} else if (candidate) {
|
|
946
|
-
|
|
1277
|
+
log(
|
|
947
1278
|
c.dim(
|
|
948
1279
|
` Move or mount ${candidate} as a project index.html before snapshotting; snapshot accepts project directories, not individual HTML files.`
|
|
949
1280
|
)
|
|
950
1281
|
);
|
|
951
1282
|
}
|
|
952
|
-
|
|
1283
|
+
log("");
|
|
1284
|
+
if (asJson) {
|
|
1285
|
+
const error = "The default index.html entry is blank; see the lint findings on stderr.";
|
|
1286
|
+
console.log(JSON.stringify(withMeta({ ok: false, error }), null, 2));
|
|
1287
|
+
}
|
|
953
1288
|
failCommand();
|
|
954
1289
|
}
|
|
955
1290
|
const timeout = parseInt(args.timeout, 10) || 5e3;
|
|
@@ -960,20 +1295,18 @@ var snapshot_default = defineCommand({
|
|
|
960
1295
|
const zoomTarget = args.zoom ? parseZoomTarget(String(args.zoom)) : void 0;
|
|
961
1296
|
const zoomScale = parseZoomScale(args["zoom-scale"]);
|
|
962
1297
|
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`;
|
|
1298
|
+
if (against && !existsSync(against))
|
|
1299
|
+
fail(`${c.error("\u2717")} --against video not found: ${against}`);
|
|
1300
|
+
const label = reviewMode ? "review frames (beats, seams, phone)" : atTimestamps ? `${atTimestamps.length} frames at [${atTimestamps.map(formatSnapshotTimestamp).join(", ")}]` : `${frames} frames`;
|
|
968
1301
|
const angleLabel = camera && (camera.yaw !== 0 || camera.pitch !== 0) ? ` ${c.dim(`(angle yaw ${camera.yaw}\xB0 pitch ${camera.pitch}\xB0)`)}` : "";
|
|
969
|
-
|
|
1302
|
+
log(`${c.accent("\u25C6")} Capturing ${label} from ${c.accent(project.name)}${angleLabel}`);
|
|
970
1303
|
let managedSnapshotDir;
|
|
971
1304
|
try {
|
|
972
1305
|
const snapshotDir = args.output ? resolve(String(args.output)) : artifactDirectory(project.dir, "snapshots");
|
|
973
1306
|
if (!args.output) managedSnapshotDir = snapshotDir;
|
|
974
1307
|
if (args.output) retainSnapshotOutput(project.dir, snapshotDir);
|
|
975
1308
|
await withProjectLock(project.dir, "snapshot", async () => {
|
|
976
|
-
const
|
|
1309
|
+
const captured = await captureSnapshots(project.dir, {
|
|
977
1310
|
frames,
|
|
978
1311
|
range,
|
|
979
1312
|
composition,
|
|
@@ -987,53 +1320,71 @@ var snapshot_default = defineCommand({
|
|
|
987
1320
|
autoProxy: args.proxy,
|
|
988
1321
|
browserGpuMode: resolveLocalBrowserGpuMode(args["browser-gpu"]),
|
|
989
1322
|
against,
|
|
990
|
-
keep: args.keep === true
|
|
1323
|
+
keep: args.keep === true,
|
|
1324
|
+
review: reviewMode,
|
|
1325
|
+
log
|
|
991
1326
|
});
|
|
1327
|
+
const paths = captured.paths;
|
|
992
1328
|
reportArtifacts(
|
|
993
1329
|
"snapshot",
|
|
994
1330
|
"frame",
|
|
995
1331
|
paths.map((path) => resolve(project.dir, path))
|
|
996
1332
|
);
|
|
997
1333
|
if (paths.length === 0) {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
${c.error("\u2717")} Could not determine composition duration \u2014 no frames captured`
|
|
1001
|
-
);
|
|
1002
|
-
failCommand();
|
|
1334
|
+
fail(`
|
|
1335
|
+
${c.error("\u2717")} Could not determine composition duration \u2014 no frames captured`);
|
|
1003
1336
|
}
|
|
1004
|
-
|
|
1337
|
+
log(`
|
|
1005
1338
|
${c.success("\u25C7")} ${paths.length} snapshots saved to ${snapshotDir}`);
|
|
1006
1339
|
for (const p of paths) {
|
|
1007
|
-
|
|
1340
|
+
log(` ${p}`);
|
|
1008
1341
|
}
|
|
1009
1342
|
if (against) {
|
|
1010
|
-
|
|
1343
|
+
log(
|
|
1011
1344
|
` ${c.dim("ref-*.png + pair-*.jpg")} beside each frame (reference frame, render | reference sheet)`
|
|
1012
1345
|
);
|
|
1013
1346
|
}
|
|
1347
|
+
let contactSheets = [];
|
|
1348
|
+
let reviewSheets;
|
|
1014
1349
|
try {
|
|
1015
1350
|
const { createSnapshotContactSheet } = await import("./contactSheet-CAGMKI3E.js");
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1351
|
+
if (captured.review) {
|
|
1352
|
+
const written = new Map(
|
|
1353
|
+
captured.review.frames.map((frame) => [frame.file, frame.path])
|
|
1354
|
+
);
|
|
1355
|
+
reviewSheets = await writeReviewSheets(
|
|
1356
|
+
snapshotDir,
|
|
1357
|
+
captured.review.frames,
|
|
1358
|
+
(frame) => written.get(frame.file) ?? null
|
|
1359
|
+
);
|
|
1360
|
+
contactSheets = [...reviewSheets.beats, ...reviewSheets.seams, ...reviewSheets.phone];
|
|
1361
|
+
printReview(captured.review, reviewSheets, log);
|
|
1362
|
+
} else if (args.keep !== true) {
|
|
1363
|
+
contactSheets = await createSnapshotContactSheet(
|
|
1364
|
+
snapshotDir,
|
|
1365
|
+
join(snapshotDir, "contact-sheet.jpg")
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
reportArtifacts("snapshot", "contact-sheet", contactSheets);
|
|
1369
|
+
if (!captured.review) {
|
|
1370
|
+
for (const sheet of contactSheets) {
|
|
1371
|
+
log(` ${resolve(sheet)} (grid view for AI review)`);
|
|
1372
|
+
}
|
|
1023
1373
|
}
|
|
1024
1374
|
} catch (err) {
|
|
1025
1375
|
console.warn(
|
|
1026
1376
|
` ${c.warn("\u26A0")} Contact sheet skipped: ${normalizeErrorMessage(err)}. Individual snapshot PNGs are still available.`
|
|
1027
1377
|
);
|
|
1028
1378
|
}
|
|
1379
|
+
let describedPath;
|
|
1029
1380
|
if (describeArg !== null) {
|
|
1030
1381
|
try {
|
|
1031
1382
|
const geminiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
1032
1383
|
if (!geminiKey) {
|
|
1033
1384
|
if (args.describe !== void 0)
|
|
1034
|
-
|
|
1385
|
+
log(` ${c.dim("--describe: GEMINI_API_KEY not set, skipping")}`);
|
|
1035
1386
|
} else if (paths.length > 0) {
|
|
1036
|
-
|
|
1387
|
+
log(` ${c.dim("Describing frames with Gemini vision...")}`);
|
|
1037
1388
|
const { GoogleGenAI } = await loadOptionalPackage("@google/genai", "--describe");
|
|
1038
1389
|
const ai = new GoogleGenAI({ apiKey: geminiKey });
|
|
1039
1390
|
const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
|
|
@@ -1101,17 +1452,28 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${snapshotDir}`);
|
|
|
1101
1452
|
}
|
|
1102
1453
|
const descPath = join(snapshotDir, "descriptions.md");
|
|
1103
1454
|
writeFileSync(descPath, descriptions.join("\n"));
|
|
1104
|
-
|
|
1455
|
+
describedPath = descPath;
|
|
1456
|
+
log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
|
|
1105
1457
|
}
|
|
1106
1458
|
} catch (descErr) {
|
|
1107
1459
|
const msg = normalizeErrorMessage(descErr);
|
|
1108
|
-
|
|
1460
|
+
log(` ${c.dim(`--describe failed: ${msg}`)}`);
|
|
1109
1461
|
}
|
|
1110
1462
|
}
|
|
1463
|
+
if (asJson) {
|
|
1464
|
+
const envelope = snapshotEnvelope(project.dir, snapshotDir, captured, {
|
|
1465
|
+
contactSheets,
|
|
1466
|
+
reviewSheets,
|
|
1467
|
+
describedPath
|
|
1468
|
+
});
|
|
1469
|
+
console.log(JSON.stringify(withMeta(envelope), null, 2));
|
|
1470
|
+
}
|
|
1111
1471
|
});
|
|
1112
1472
|
} catch (err) {
|
|
1473
|
+
if (err instanceof CliRuntimeError && err.result.presented) throw err;
|
|
1113
1474
|
const msg = normalizeErrorMessage(err);
|
|
1114
|
-
console.error
|
|
1475
|
+
if (asJson) console.log(JSON.stringify(withMeta({ ok: false, error: msg }), null, 2));
|
|
1476
|
+
else console.error(`
|
|
1115
1477
|
${c.error("\u2717")} Snapshot failed: ${msg}`);
|
|
1116
1478
|
failCommand();
|
|
1117
1479
|
} finally {
|