dsh-hyperframes 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/README.en.md +6 -5
  2. package/README.md +7 -6
  3. package/lib/index.d.ts +1 -1
  4. package/lib/index.js +1 -0
  5. package/package.json +63 -63
  6. package/skills/embedded-captions/SKILL.md +28 -3
  7. package/skills/embedded-captions/references/aesthetic-principles.md +2 -3
  8. package/skills/embedded-captions/references/rail.md +1 -1
  9. package/skills/embedded-captions/scripts/check-occlusion.cjs +4 -1
  10. package/skills/embedded-captions/scripts/check-overflow.cjs +1 -0
  11. package/skills/embedded-captions/scripts/check-rail-climax.cjs +5 -1
  12. package/skills/embedded-captions/scripts/fixtures/heroless/theme.json +11 -0
  13. package/skills/embedded-captions/scripts/hf-cli.cjs +33 -0
  14. package/skills/embedded-captions/scripts/make-theme.cjs +95 -57
  15. package/skills/embedded-captions/scripts/make-theme.test.mjs +131 -0
  16. package/skills/embedded-captions/scripts/matte.cjs +1 -13
  17. package/skills/embedded-captions/scripts/measure-layout.cjs +2 -1
  18. package/skills/embedded-captions/scripts/preview-frames.cjs +39 -11
  19. package/skills/embedded-captions/scripts/preview-frames.test.mjs +24 -0
  20. package/skills/embedded-captions/scripts/render-and-composite.sh +8 -52
  21. package/skills/embedded-captions/scripts/safe-zones.cjs +4 -1
  22. package/skills/embedded-captions/scripts/transcribe.cjs +5 -14
  23. package/skills/embedded-captions/scripts/transcribe.test.mjs +41 -0
  24. package/skills/faceless-explainer/SKILL.md +20 -16
  25. package/skills/faceless-explainer/references/story-design.md +1 -1
  26. package/skills/faceless-explainer/scripts/assemble-index.mjs +6 -4
  27. package/skills/faceless-explainer/scripts/assemble-index.test.mjs +57 -2
  28. package/skills/faceless-explainer/scripts/audio.mjs +2 -0
  29. package/skills/faceless-explainer/scripts/build-frame.mjs +6 -3
  30. package/skills/faceless-explainer/scripts/captions.mjs +7 -4
  31. package/skills/faceless-explainer/scripts/frame-packets.mjs +4 -4
  32. package/skills/faceless-explainer/scripts/lib/bgm-volume.mjs +4 -0
  33. package/skills/faceless-explainer/scripts/lib/captured-fonts.mjs +58 -0
  34. package/skills/{hyperframes-core → faceless-explainer}/scripts/lib/frame-packets-core.mjs +5 -23
  35. package/skills/faceless-explainer/scripts/lib/storyboard.mjs +1 -1
  36. package/skills/faceless-explainer/scripts/lib/transitions.json +3 -3
  37. package/skills/faceless-explainer/scripts/transitions.mjs +1 -0
  38. package/skills/faceless-explainer/scripts/transitions.test.mjs +2 -0
  39. package/skills/faceless-explainer/sub-agents/frame-worker.md +1 -1
  40. package/skills/figma/SKILL.md +2 -0
  41. package/skills/general-video/SKILL.md +13 -11
  42. package/skills/general-video/scripts/frame-packets.mjs +4 -4
  43. package/skills/general-video/scripts/lib/frame-packets-core.mjs +194 -0
  44. package/skills/general-video/sub-agents/frame-worker.md +1 -1
  45. package/skills/hyperframes/SKILL.md +40 -30
  46. package/skills/{hyperframes-core → hyperframes}/references/brief-contract.md +15 -15
  47. package/skills/{hyperframes-core → hyperframes}/references/brief-format.md +8 -8
  48. package/skills/hyperframes/references/capability-menu.md +2 -2
  49. package/skills/{hyperframes-core → hyperframes}/references/frame-worker-core.md +1 -1
  50. package/skills/hyperframes/references/intent-interview.md +16 -16
  51. package/skills/hyperframes/references/plugin-installation.md +43 -0
  52. package/skills/{hyperframes-core → hyperframes}/references/production-loop.md +11 -11
  53. package/skills/hyperframes/references/review-loop.md +37 -0
  54. package/skills/hyperframes/references/route-briefs.md +1 -1
  55. package/skills/hyperframes/references/routes/motion-graphics.md +1 -1
  56. package/skills/{hyperframes-core → hyperframes}/references/script-format.md +3 -3
  57. package/skills/hyperframes/references/skill-lifecycle.md +2 -0
  58. package/skills/{hyperframes-core → hyperframes}/references/storyboard-format.md +3 -34
  59. package/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
  60. package/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
  61. package/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
  62. package/skills/hyperframes-animation/SKILL.md +5 -1
  63. package/skills/hyperframes-animation/adapters/gsap.md +1 -1
  64. package/skills/hyperframes-animation/adapters/lottie.md +15 -2
  65. package/skills/hyperframes-animation/adapters/three.md +14 -0
  66. package/skills/hyperframes-animation/blueprints/titlecard-reveal.md +1 -1
  67. package/skills/hyperframes-animation/references/motion-blur.md +133 -0
  68. package/skills/hyperframes-animation/rules/cursor-click-ripple.md +1 -1
  69. package/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +1 -1
  70. package/skills/hyperframes-animation/rules/hacker-flip-3d.md +1 -1
  71. package/skills/hyperframes-animation/rules/kinetic-beat-slam.md +2 -2
  72. package/skills/hyperframes-animation/rules/motion-blur-streak.md +1 -1
  73. package/skills/hyperframes-animation/rules/vertical-spring-ticker.md +1 -1
  74. package/skills/hyperframes-animation/scripts/package-loader.mjs +47 -16
  75. package/skills/hyperframes-animation/scripts/package-loader.test.mjs +52 -0
  76. package/skills/hyperframes-animation/techniques.md +1 -1
  77. package/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +3 -3
  78. package/skills/hyperframes-animation/transitions/css-push.md +4 -4
  79. package/skills/hyperframes-audio/SKILL.md +30 -22
  80. package/skills/hyperframes-audio/scripts/carve.mjs +6 -3
  81. package/skills/hyperframes-audio/scripts/carve.test.mjs +16 -1
  82. package/skills/hyperframes-cli/SKILL.md +44 -35
  83. package/skills/hyperframes-cli/references/init-and-scaffold.md +8 -6
  84. package/skills/hyperframes-cli/references/lint-validate-inspect.md +3 -3
  85. package/skills/hyperframes-cli/references/preview-render.md +35 -32
  86. package/skills/hyperframes-cli/references/upgrade-info-misc.md +50 -1
  87. package/skills/hyperframes-core/SKILL.md +30 -24
  88. package/skills/hyperframes-core/references/composition-patterns.md +3 -42
  89. package/skills/hyperframes-core/references/creator-editing-recipes.md +131 -7
  90. package/skills/hyperframes-core/references/data-attributes.md +11 -11
  91. package/skills/hyperframes-core/references/determinism-rules.md +2 -19
  92. package/skills/hyperframes-core/references/full-screen-motion.md +0 -9
  93. package/skills/hyperframes-core/references/minimal-composition.md +2 -2
  94. package/skills/hyperframes-core/references/sub-compositions.md +3 -66
  95. package/skills/hyperframes-core/references/tailwind.md +1 -20
  96. package/skills/hyperframes-core/references/tracks-and-clips.md +2 -6
  97. package/skills/hyperframes-core/references/variables-and-media.md +3 -3
  98. package/skills/hyperframes-creative/SKILL.md +2 -0
  99. package/skills/hyperframes-creative/references/house-style.md +15 -15
  100. package/skills/hyperframes-creative/references/story-spine.md +3 -1
  101. package/skills/hyperframes-creative/references/storyboard-recipe.md +57 -0
  102. package/skills/hyperframes-creative/references/typography.md +1 -1
  103. package/skills/hyperframes-creative/scripts/package-loader.mjs +47 -16
  104. package/skills/hyperframes-creative/scripts/package-loader.test.mjs +52 -0
  105. package/skills/hyperframes-keyframes/SKILL.md +4 -2
  106. package/skills/hyperframes-registry/SKILL.md +3 -1
  107. package/skills/hyperframes-registry/references/contributing.md +8 -2
  108. package/skills/hyperframes-registry/references/discovery.md +20 -34
  109. package/skills/hyperframes-studio/SKILL.md +77 -0
  110. package/skills/media-use/SKILL.md +14 -12
  111. package/skills/media-use/audio/references/captions/authoring.md +4 -0
  112. package/skills/media-use/audio/references/remove-background.md +1 -1
  113. package/skills/media-use/audio/references/tts-to-captions.md +11 -2
  114. package/skills/media-use/audio/references/tts.md +84 -6
  115. package/skills/media-use/audio/scripts/audio.mjs +15 -6
  116. package/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +113 -0
  117. package/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
  118. package/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
  119. package/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
  120. package/skills/media-use/audio/scripts/lib/bgm.mjs +2 -6
  121. package/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
  122. package/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
  123. package/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
  124. package/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
  125. package/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
  126. package/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
  127. package/skills/media-use/audio/scripts/lib/heygen.mjs +2 -1
  128. package/skills/media-use/audio/scripts/lib/tts.mjs +15 -3
  129. package/skills/media-use/audio/scripts/wait-bgm.mjs +8 -4
  130. package/skills/media-use/audio/scripts/wait-bgm.test.mjs +65 -0
  131. package/skills/media-use/references/audio.md +3 -2
  132. package/skills/media-use/references/grading.md +7 -7
  133. package/skills/media-use/references/media-treatment-recipes.md +1 -1
  134. package/skills/media-use/references/memory.md +2 -2
  135. package/skills/media-use/references/meta.md +2 -2
  136. package/skills/media-use/references/operations.md +15 -13
  137. package/skills/media-use/references/resolve.md +22 -11
  138. package/skills/media-use/references/setup-providers.md +11 -11
  139. package/skills/media-use/scripts/audio-duck.mjs +19 -27
  140. package/skills/media-use/scripts/compatibility.test.mjs +96 -0
  141. package/skills/media-use/scripts/lib/config-lock.mjs +45 -0
  142. package/skills/media-use/scripts/lib/duck.mjs +16 -10
  143. package/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
  144. package/skills/media-use/scripts/lib/media-home.mjs +20 -0
  145. package/skills/media-use/scripts/lib/npx-sync.mjs +28 -2
  146. package/skills/media-use/scripts/lib/prefs-store.mjs +2 -2
  147. package/skills/media-use/scripts/lib/recipe-store.mjs +2 -2
  148. package/skills/media-use/scripts/lib/telemetry.mjs +29 -41
  149. package/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
  150. package/skills/media-use/scripts/prefs.mjs +1 -1
  151. package/skills/media-use/scripts/recipe.mjs +1 -1
  152. package/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
  153. package/skills/media-use/scripts/resolve.mjs +27 -1267
  154. package/skills/media-use/scripts/transcribe.mjs +39 -25
  155. package/skills/media-use/scripts/transcribe.test.mjs +112 -0
  156. package/skills/media-use/scripts/transcript-cut.mjs +39 -8
  157. package/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
  158. package/skills/motion-graphics/SKILL.md +3 -1
  159. package/skills/motion-graphics/agents/builder.md +1 -0
  160. package/skills/motion-graphics/agents/director.md +2 -1
  161. package/skills/motion-graphics/catalog-map.md +25 -13
  162. package/skills/motion-graphics/categories/charts/module.md +2 -1
  163. package/skills/motion-graphics/categories/lower-thirds/module.md +4 -0
  164. package/skills/motion-graphics/categories/news/module.md +1 -1
  165. package/skills/motion-graphics/references/motion-vocabulary.md +4 -0
  166. package/skills/music-to-video/SKILL.md +8 -6
  167. package/skills/music-to-video/references/montage.md +3 -6
  168. package/skills/music-to-video/references/motion-primitives/3d-card-flip/index.html +10 -111
  169. package/skills/music-to-video/references/motion-primitives/3d-card-flip/scene.html +119 -0
  170. package/skills/music-to-video/references/motion-primitives/bg-flow-field/index.html +11 -284
  171. package/skills/music-to-video/references/motion-primitives/bg-flow-field/scene.html +294 -0
  172. package/skills/music-to-video/references/motion-primitives/binary-decrypt/index.html +10 -76
  173. package/skills/music-to-video/references/motion-primitives/binary-decrypt/scene.html +85 -0
  174. package/skills/music-to-video/references/motion-primitives/blur-resolve/index.html +10 -52
  175. package/skills/music-to-video/references/motion-primitives/blur-resolve/scene.html +60 -0
  176. package/skills/music-to-video/references/motion-primitives/braam-punch/index.html +10 -92
  177. package/skills/music-to-video/references/motion-primitives/braam-punch/scene.html +100 -0
  178. package/skills/music-to-video/references/motion-primitives/chromatic-split/index.html +10 -103
  179. package/skills/music-to-video/references/motion-primitives/chromatic-split/scene.html +111 -0
  180. package/skills/music-to-video/references/motion-primitives/chrome-sweep/index.html +10 -60
  181. package/skills/music-to-video/references/motion-primitives/chrome-sweep/scene.html +68 -0
  182. package/skills/music-to-video/references/motion-primitives/counting-punch/index.html +10 -110
  183. package/skills/music-to-video/references/motion-primitives/counting-punch/scene.html +119 -0
  184. package/skills/music-to-video/references/motion-primitives/crash-zoom-in/index.html +10 -112
  185. package/skills/music-to-video/references/motion-primitives/crash-zoom-in/scene.html +120 -0
  186. package/skills/music-to-video/references/motion-primitives/datamosh-smear/index.html +10 -121
  187. package/skills/music-to-video/references/motion-primitives/datamosh-smear/scene.html +131 -0
  188. package/skills/music-to-video/references/motion-primitives/directional-fill/index.html +10 -90
  189. package/skills/music-to-video/references/motion-primitives/directional-fill/scene.html +103 -0
  190. package/skills/music-to-video/references/motion-primitives/dolly-zoom/index.html +10 -94
  191. package/skills/music-to-video/references/motion-primitives/dolly-zoom/scene.html +102 -0
  192. package/skills/music-to-video/references/motion-primitives/electric-arc/index.html +10 -100
  193. package/skills/music-to-video/references/motion-primitives/electric-arc/scene.html +105 -0
  194. package/skills/music-to-video/references/motion-primitives/flash-cut/index.html +10 -89
  195. package/skills/music-to-video/references/motion-primitives/flash-cut/scene.html +97 -0
  196. package/skills/music-to-video/references/motion-primitives/gooey-metaball/index.html +10 -197
  197. package/skills/music-to-video/references/motion-primitives/gooey-metaball/scene.html +206 -0
  198. package/skills/music-to-video/references/motion-primitives/hard-cut/index.html +10 -74
  199. package/skills/music-to-video/references/motion-primitives/hard-cut/scene.html +82 -0
  200. package/skills/music-to-video/references/motion-primitives/hypercut-whip/index.html +10 -36
  201. package/skills/music-to-video/references/motion-primitives/hypercut-whip/scene.html +44 -0
  202. package/skills/music-to-video/references/motion-primitives/iris-open/index.html +10 -61
  203. package/skills/music-to-video/references/motion-primitives/iris-open/scene.html +69 -0
  204. package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/index.html +10 -55
  205. package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/scene.html +64 -0
  206. package/skills/music-to-video/references/motion-primitives/liquid-morph/index.html +10 -88
  207. package/skills/music-to-video/references/motion-primitives/liquid-morph/scene.html +96 -0
  208. package/skills/music-to-video/references/motion-primitives/mask-reveal/index.html +10 -66
  209. package/skills/music-to-video/references/motion-primitives/mask-reveal/scene.html +74 -0
  210. package/skills/music-to-video/references/motion-primitives/mosaic-pack/index.html +10 -81
  211. package/skills/music-to-video/references/motion-primitives/mosaic-pack/scene.html +89 -0
  212. package/skills/music-to-video/references/motion-primitives/neon-flicker/index.html +10 -65
  213. package/skills/music-to-video/references/motion-primitives/neon-flicker/scene.html +73 -0
  214. package/skills/music-to-video/references/motion-primitives/outline-to-fill/index.html +10 -74
  215. package/skills/music-to-video/references/motion-primitives/outline-to-fill/scene.html +82 -0
  216. package/skills/music-to-video/references/motion-primitives/palette-flip/index.html +10 -89
  217. package/skills/music-to-video/references/motion-primitives/palette-flip/scene.html +97 -0
  218. package/skills/music-to-video/references/motion-primitives/particle-burst/index.html +10 -98
  219. package/skills/music-to-video/references/motion-primitives/particle-burst/scene.html +106 -0
  220. package/skills/music-to-video/references/motion-primitives/pixel-dissolve/index.html +10 -78
  221. package/skills/music-to-video/references/motion-primitives/pixel-dissolve/scene.html +86 -0
  222. package/skills/music-to-video/references/motion-primitives/radial-burst-lines/index.html +10 -117
  223. package/skills/music-to-video/references/motion-primitives/radial-burst-lines/scene.html +130 -0
  224. package/skills/music-to-video/references/motion-primitives/screen-shake/index.html +10 -70
  225. package/skills/music-to-video/references/motion-primitives/screen-shake/scene.html +78 -0
  226. package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/index.html +10 -87
  227. package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/scene.html +100 -0
  228. package/skills/music-to-video/references/motion-primitives/spotlight-sweep/index.html +10 -94
  229. package/skills/music-to-video/references/motion-primitives/spotlight-sweep/scene.html +102 -0
  230. package/skills/music-to-video/references/motion-primitives/staggered-exit/index.html +10 -74
  231. package/skills/music-to-video/references/motion-primitives/staggered-exit/scene.html +82 -0
  232. package/skills/music-to-video/references/motion-primitives/text-spectral-rays/index.html +11 -271
  233. package/skills/music-to-video/references/motion-primitives/text-spectral-rays/scene.html +280 -0
  234. package/skills/music-to-video/references/motion-primitives/text-wave-distort/index.html +10 -92
  235. package/skills/music-to-video/references/motion-primitives/text-wave-distort/scene.html +106 -0
  236. package/skills/music-to-video/references/motion-primitives/tile-mosaic/index.html +10 -101
  237. package/skills/music-to-video/references/motion-primitives/tile-mosaic/scene.html +109 -0
  238. package/skills/music-to-video/references/motion-primitives/typewriter-reveal/index.html +10 -79
  239. package/skills/music-to-video/references/motion-primitives/typewriter-reveal/scene.html +91 -0
  240. package/skills/music-to-video/references/motion-primitives/word-grid-burst/index.html +10 -83
  241. package/skills/music-to-video/references/motion-primitives/word-grid-burst/scene.html +96 -0
  242. package/skills/music-to-video/references/planning.md +2 -2
  243. package/skills/music-to-video/scripts/lib/storyboard.mjs +1 -1
  244. package/skills/music-to-video/sub-agents/frame-worker.md +2 -2
  245. package/skills/pr-to-video/SKILL.md +20 -16
  246. package/skills/pr-to-video/references/code-vocabulary.md +14 -12
  247. package/skills/pr-to-video/references/story-design.md +1 -1
  248. package/skills/pr-to-video/scripts/assemble-index.mjs +6 -4
  249. package/skills/pr-to-video/scripts/assemble-index.test.mjs +57 -2
  250. package/skills/pr-to-video/scripts/audio.mjs +2 -0
  251. package/skills/pr-to-video/scripts/build-frame.mjs +6 -3
  252. package/skills/pr-to-video/scripts/captions.mjs +7 -4
  253. package/skills/pr-to-video/scripts/captions.test.mjs +41 -0
  254. package/skills/pr-to-video/scripts/frame-packets.mjs +4 -4
  255. package/skills/pr-to-video/scripts/lib/bgm-volume.mjs +4 -0
  256. package/skills/pr-to-video/scripts/lib/captured-fonts.mjs +58 -0
  257. package/skills/pr-to-video/scripts/lib/frame-packets-core.mjs +194 -0
  258. package/skills/pr-to-video/scripts/lib/storyboard.mjs +1 -1
  259. package/skills/pr-to-video/scripts/lib/transitions.json +3 -3
  260. package/skills/pr-to-video/scripts/transitions.mjs +7 -5
  261. package/skills/pr-to-video/sub-agents/frame-worker.md +1 -1
  262. package/skills/product-launch-video/SKILL.md +20 -16
  263. package/skills/product-launch-video/references/story-design.md +1 -1
  264. package/skills/product-launch-video/scripts/assemble-index.mjs +6 -4
  265. package/skills/product-launch-video/scripts/assemble-index.test.mjs +57 -2
  266. package/skills/product-launch-video/scripts/audio.mjs +2 -0
  267. package/skills/product-launch-video/scripts/audio.test.mjs +16 -0
  268. package/skills/product-launch-video/scripts/build-frame-subsets.test.mjs +152 -0
  269. package/skills/product-launch-video/scripts/build-frame.mjs +6 -3
  270. package/skills/product-launch-video/scripts/captions.mjs +7 -4
  271. package/skills/product-launch-video/scripts/frame-packets.mjs +4 -4
  272. package/skills/product-launch-video/scripts/lib/bgm-volume.mjs +4 -0
  273. package/skills/product-launch-video/scripts/lib/captured-fonts.mjs +58 -0
  274. package/skills/product-launch-video/scripts/lib/frame-packets-core.mjs +194 -0
  275. package/skills/product-launch-video/scripts/lib/storyboard.mjs +1 -1
  276. package/skills/product-launch-video/scripts/lib/transitions.json +3 -3
  277. package/skills/product-launch-video/scripts/transitions.mjs +7 -5
  278. package/skills/product-launch-video/scripts/transitions.test.mjs +68 -0
  279. package/skills/product-launch-video/sub-agents/frame-worker.md +1 -1
  280. package/skills/remotion-to-hyperframes/SKILL.md +7 -4
  281. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/expected.json +5 -5
  282. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/compositions/title.html +31 -0
  283. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/index.html +10 -25
  284. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/README.md +8 -8
  285. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/expected.json +9 -9
  286. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-1.html +35 -0
  287. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-2.html +35 -0
  288. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-3.html +36 -0
  289. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/index.html +28 -71
  290. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/expected.json +3 -3
  291. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-1.html +52 -0
  292. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-2.html +99 -0
  293. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-3.html +55 -0
  294. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/index.html +13 -212
  295. package/skills/remotion-to-hyperframes/references/api-map.md +16 -16
  296. package/skills/remotion-to-hyperframes/references/limitations.md +7 -7
  297. package/skills/remotion-to-hyperframes/references/lottie.md +5 -7
  298. package/skills/remotion-to-hyperframes/references/media.md +3 -3
  299. package/skills/remotion-to-hyperframes/references/parameters.md +5 -0
  300. package/skills/remotion-to-hyperframes/references/sequencing.md +71 -18
  301. package/skills/slideshow/SKILL.md +4 -1
  302. package/skills/slideshow/references/standalone-harness.md +0 -3
  303. package/skills/talking-head-recut/SKILL.md +10 -1
  304. package/skills/hyperframes-core/references/review-loop.md +0 -41
  305. package/skills/media-use/scripts/lib/adopt.mjs +0 -128
  306. package/skills/media-use/scripts/lib/adopt.test.mjs +0 -95
  307. package/skills/media-use/scripts/lib/bgm-provider.mjs +0 -20
  308. package/skills/media-use/scripts/lib/brand-provider.mjs +0 -59
  309. package/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +0 -108
  310. package/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +0 -85
  311. package/skills/media-use/scripts/lib/cache.mjs +0 -150
  312. package/skills/media-use/scripts/lib/candidates.mjs +0 -91
  313. package/skills/media-use/scripts/lib/candidates.test.mjs +0 -155
  314. package/skills/media-use/scripts/lib/codex-provider.mjs +0 -161
  315. package/skills/media-use/scripts/lib/codex-provider.test.mjs +0 -34
  316. package/skills/media-use/scripts/lib/coverage.test.mjs +0 -117
  317. package/skills/media-use/scripts/lib/cube-build.mjs +0 -181
  318. package/skills/media-use/scripts/lib/cube-build.test.mjs +0 -80
  319. package/skills/media-use/scripts/lib/cube-validate.mjs +0 -198
  320. package/skills/media-use/scripts/lib/cube-validate.test.mjs +0 -125
  321. package/skills/media-use/scripts/lib/cutlist.test.mjs +0 -148
  322. package/skills/media-use/scripts/lib/duck.test.mjs +0 -118
  323. package/skills/media-use/scripts/lib/error-diffusion.test.mjs +0 -102
  324. package/skills/media-use/scripts/lib/freeze.mjs +0 -70
  325. package/skills/media-use/scripts/lib/freeze.test.mjs +0 -46
  326. package/skills/media-use/scripts/lib/grade-analyzer.mjs +0 -264
  327. package/skills/media-use/scripts/lib/grade-analyzer.test.mjs +0 -285
  328. package/skills/media-use/scripts/lib/heygen-cli.mjs +0 -191
  329. package/skills/media-use/scripts/lib/heygen-cli.test.mjs +0 -301
  330. package/skills/media-use/scripts/lib/heygen-search.mjs +0 -45
  331. package/skills/media-use/scripts/lib/heygen-search.test.mjs +0 -49
  332. package/skills/media-use/scripts/lib/heygen-video-provider.mjs +0 -127
  333. package/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +0 -344
  334. package/skills/media-use/scripts/lib/image-provider.mjs +0 -44
  335. package/skills/media-use/scripts/lib/local-models.mjs +0 -318
  336. package/skills/media-use/scripts/lib/local-models.test.mjs +0 -220
  337. package/skills/media-use/scripts/lib/local-run.mjs +0 -78
  338. package/skills/media-use/scripts/lib/local-run.test.mjs +0 -121
  339. package/skills/media-use/scripts/lib/logo-provider.mjs +0 -222
  340. package/skills/media-use/scripts/lib/logo-provider.test.mjs +0 -137
  341. package/skills/media-use/scripts/lib/ltx-video-provider.mjs +0 -94
  342. package/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +0 -316
  343. package/skills/media-use/scripts/lib/lut-preset-provider.mjs +0 -266
  344. package/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +0 -176
  345. package/skills/media-use/scripts/lib/manifest.test.mjs +0 -388
  346. package/skills/media-use/scripts/lib/match.mjs +0 -47
  347. package/skills/media-use/scripts/lib/mflux-provider.mjs +0 -128
  348. package/skills/media-use/scripts/lib/mflux-provider.test.mjs +0 -174
  349. package/skills/media-use/scripts/lib/misses.mjs +0 -49
  350. package/skills/media-use/scripts/lib/misses.test.mjs +0 -78
  351. package/skills/media-use/scripts/lib/npx-sync.test.mjs +0 -50
  352. package/skills/media-use/scripts/lib/parakeet-words.test.mjs +0 -44
  353. package/skills/media-use/scripts/lib/prefs-store.test.mjs +0 -189
  354. package/skills/media-use/scripts/lib/probe.mjs +0 -39
  355. package/skills/media-use/scripts/lib/probe.test.mjs +0 -31
  356. package/skills/media-use/scripts/lib/providers.mjs +0 -5
  357. package/skills/media-use/scripts/lib/recipe-store.test.mjs +0 -367
  358. package/skills/media-use/scripts/lib/registry.mjs +0 -218
  359. package/skills/media-use/scripts/lib/registry.test.mjs +0 -261
  360. package/skills/media-use/scripts/lib/search.mjs +0 -24
  361. package/skills/media-use/scripts/lib/search.test.mjs +0 -32
  362. package/skills/media-use/scripts/lib/sfx-provider.mjs +0 -23
  363. package/skills/media-use/scripts/lib/specs.mjs +0 -132
  364. package/skills/media-use/scripts/lib/specs.test.mjs +0 -157
  365. package/skills/media-use/scripts/lib/stats.mjs +0 -117
  366. package/skills/media-use/scripts/lib/stats.test.mjs +0 -165
  367. package/skills/media-use/scripts/lib/telemetry.test.mjs +0 -373
  368. package/skills/media-use/scripts/lib/tts-local-provider.mjs +0 -92
  369. package/skills/media-use/scripts/lib/tts-local-provider.test.mjs +0 -72
  370. package/skills/media-use/scripts/lib/usage.mjs +0 -57
  371. package/skills/media-use/scripts/lib/usage.test.mjs +0 -54
  372. package/skills/media-use/scripts/lib/voice-provider.mjs +0 -57
  373. package/skills/media-use/scripts/lib/voice-provider.test.mjs +0 -46
  374. package/skills/media-use/scripts/resolve.test.mjs +0 -1120
  375. /package/skills/{hyperframes-core → hyperframes}/references/subagent-dispatch.md +0 -0
@@ -20,7 +20,7 @@ assemble those from a generic LUT plus handmade CSS vignette/grain/opacity.
20
20
  **Never `cat`/read a `.cube` file into context.** A 3D LUT is ~size^3 lines of raw numbers (33^3 ≈ 36k lines at the default size). It bloats context and carries zero human/agent-legible signal. To understand or choose a LUT, use `hyperframes grade-compare` to see it rendered, or `cube-validate.mjs` for a one-line `{ok,size}` check. Read `.media/index.md` or `luts/index.json` for the description. Never read the LUT body itself.
21
21
 
22
22
  ```bash
23
- node <SKILL_DIR>/scripts/resolve.mjs --type grade --intent "warm daylight" --project . --json
23
+ npx hyperframes media-use resolve --type grade --intent "warm daylight" --project . --json
24
24
  ```
25
25
 
26
26
  Preset-first output uses the core runtime vocabulary and does not freeze a file:
@@ -93,7 +93,7 @@ For a reusable color transform beyond the preset vocabulary, freeze a validated
93
93
  `.cube` under `.media/luts/` and return a block that references it:
94
94
 
95
95
  ```bash
96
- node <SKILL_DIR>/scripts/resolve.mjs --type grade --intent "teal orange blockbuster" --project . --json
96
+ npx hyperframes media-use resolve --type grade --intent "teal orange blockbuster" --project . --json
97
97
  ```
98
98
 
99
99
  ```json
@@ -106,20 +106,20 @@ node <SKILL_DIR>/scripts/resolve.mjs --type grade --intent "teal orange blockbus
106
106
  Use `lut` when you only need the reusable `.cube` file:
107
107
 
108
108
  ```bash
109
- node <SKILL_DIR>/scripts/resolve.mjs --type lut --intent "teal orange blockbuster" --project .
109
+ npx hyperframes media-use resolve --type lut --intent "teal orange blockbuster" --project .
110
110
  ```
111
111
 
112
112
  For a describable technical look, author an explicit parametric LUT with `--params`:
113
113
 
114
114
  ```bash
115
- node <SKILL_DIR>/scripts/resolve.mjs --type lut --params '{"contrast":0.2,"temperature":-0.3}' --project .
116
- node <SKILL_DIR>/scripts/resolve.mjs --type grade --params '{"exposure":0.2}' --project . --json
115
+ npx hyperframes media-use resolve --type lut --params '{"contrast":0.2,"temperature":-0.3}' --project .
116
+ npx hyperframes media-use resolve --type grade --params '{"exposure":0.2}' --project . --json
117
117
  ```
118
118
 
119
119
  For a LUT generated by your own script, ingest it with `--from`; media-use validates it before registration and rejects invalid or oversized cubes:
120
120
 
121
121
  ```bash
122
- node <SKILL_DIR>/scripts/resolve.mjs --type lut --from custom.cube --project .
122
+ npx hyperframes media-use resolve --type lut --from custom.cube --project .
123
123
  ```
124
124
 
125
125
  Parametric math (`buildCube`) cannot reproduce real film stocks or emulsion
@@ -155,6 +155,6 @@ validates generated or downloaded cubes as it freezes them under
155
155
  `.media/luts/`.
156
156
 
157
157
  ```bash
158
- node skills/media-use/scripts/resolve.mjs --type lut --intent "teal orange blockbuster" --project . --json
158
+ npx hyperframes media-use resolve --type lut --intent "teal orange blockbuster" --project . --json
159
159
  node skills/media-use/scripts/lib/cube-validate.mjs .media/luts/lut_001.cube
160
160
  ```
@@ -784,7 +784,7 @@ node <SKILL_DIR>/scripts/dither.mjs \
784
784
  --palette '#17121a,#824c50,#e09873,#f7ddb1' \
785
785
  --point-size 3
786
786
 
787
- node <SKILL_DIR>/scripts/resolve.mjs \
787
+ npx hyperframes media-use resolve \
788
788
  --from .media/generated/video_001.atkinson.mp4 --type video --project .
789
789
  ```
790
790
 
@@ -10,7 +10,7 @@ node <SKILL_DIR>/scripts/prefs.mjs record --hyperframes . --key destination --va
10
10
  node <SKILL_DIR>/scripts/prefs.mjs record --hyperframes . --key style_preset --value pin-and-paper --workflow faceless-explainer
11
11
  ```
12
12
 
13
- Only what the user actually confirmed gets recorded — never an inferred or defaulted value. How workflows consume these (a remembered value becomes the recommended default with a receipt, and never skips a question) is the brief contract's rule: `hyperframes-core/references/brief-contract.md` § 2, Remembered defaults.
13
+ Only what the user actually confirmed gets recorded — never an inferred or defaulted value. How workflows consume these (a remembered value becomes the recommended default with a receipt, and never skips a question) is the brief contract's rule: `hyperframes/references/brief-contract.md` § 2, Remembered defaults.
14
14
 
15
15
  ## Recipes — frozen video bundles
16
16
 
@@ -22,7 +22,7 @@ node <SKILL_DIR>/scripts/recipe.mjs list --hyperframes . --workflow product-laun
22
22
  node <SKILL_DIR>/scripts/recipe.mjs use --hyperframes . --name weekly-promo # also: resolve.mjs --type recipe --entity weekly-promo
23
23
  ```
24
24
 
25
- The freeze is offered once after the final approval (`hyperframes-core/references/review-loop.md` § 4), and the intent layer (`/hyperframes` → `references/intent-interview.md`, step 1) checks for a match before its first question. Adopting a recipe fills the brief, the design spec, and the storyboard skeleton — and unlike preferences it may skip the questions it answers: the bundle was approved as a whole, and adoption itself is the question.
25
+ The freeze is offered once after the final approval (`hyperframes/references/review-loop.md` § 4), and the intent layer (`/hyperframes` → `references/intent-interview.md`, step 1) checks for a match before its first question. Adopting a recipe fills the brief, the design spec, and the storyboard skeleton — and unlike preferences it may skip the questions it answers: the bundle was approved as a whole, and adoption itself is the question.
26
26
 
27
27
  ## Files
28
28
 
@@ -9,7 +9,7 @@ HyperFrames owns media _playback_; media-use owns everything else. Each row is e
9
9
  | HyperFrames gap | media-use owns it via |
10
10
  | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
11
11
  | Audio-only, no image/icon | `resolve --type image\|icon` (heygen asset search) |
12
- | No third-party brand logos | `resolve --type logo` (svgl → simple-icons → GitHub org avatar → domain favicon) |
12
+ | No third-party brand logos | `resolve --type logo` (theSVG → GitHub org avatar → domain favicon) |
13
13
  | No voice / audio generation | `resolve --type voice` (HeyGen TTS free-usage path; optional local Kokoro) + the audio engine (`audio/scripts/audio.mjs`) |
14
14
  | Scattered/duplicated audio engine | one consolidated engine under `audio/` (hyperframes-media retired) |
15
15
  | No agent media-ops (cut/reframe/transform) | `references/operations.md` + `resolve --from` to register outputs |
@@ -26,7 +26,7 @@ HyperFrames owns media _playback_; media-use owns everything else. Each row is e
26
26
  Use `resolve --stats` for a local, shareable report over the current project's `.media/` manifest, the global `~/.media/` cache, and local resolve misses. Human output is compact; add `--json` for a single machine-readable object, and `--days N` to window timestamped records.
27
27
 
28
28
  ```bash
29
- node <SKILL_DIR>/scripts/resolve.mjs --stats --project . --days 7
29
+ npx hyperframes media-use resolve --stats --project . --days 7
30
30
  # media-use stats
31
31
  # total resolves: 12
32
32
  # misses: 2
@@ -79,7 +79,7 @@ node <SKILL_DIR>/scripts/dither.mjs \
79
79
  --palette '#0f380f,#306230,#8bac0f,#9bbc0f' \
80
80
  --point-size 3
81
81
 
82
- node <SKILL_DIR>/scripts/resolve.mjs \
82
+ npx hyperframes media-use resolve \
83
83
  --from source.atkinson.mp4 --type video --project .
84
84
  ```
85
85
 
@@ -112,14 +112,16 @@ engine directly.
112
112
  # install once: uv venv ~/.venvs/parakeet && VIRTUAL_ENV=~/.venvs/parakeet uv pip install parakeet-mlx
113
113
  node <SKILL_DIR>/scripts/transcribe.mjs --input talk.mp4 --out talk.transcribe.json
114
114
 
115
- # equivalently, the hyperframes CLI has Parakeet built in (auto-detects it, whisper fallback):
115
+ # the hyperframes CLI runs Parakeet on macOS, Linux and Windows once it is installed:
116
+ npx hyperframes models install parakeet # once, ~640 MB, ask the user first
116
117
  npx hyperframes transcribe talk.mp4 --engine parakeet # or --engine auto (default)
117
118
  ```
118
119
 
119
- VERIFIED on 24GB: accurate, ~3s (cached) for 8s audio. Parakeet covers English +
120
- 25 European languages. For other languages, or when parakeet-mlx is not
121
- installed, transcribe.mjs auto-falls-back to whisper.cpp (99 languages) via
122
- `hyperframes transcribe`. `--engine parakeet|whisper` forces one. (Cohere
120
+ VERIFIED on 24GB: accurate, ~3s (cached) for 8s audio. Parakeet covers 25
121
+ European languages, English included. For other languages, or when parakeet-mlx is not
122
+ installed, transcribe.mjs falls back to `hyperframes transcribe`, which uses the
123
+ CLI's Parakeet when `models install parakeet` has run and whisper.cpp (99
124
+ languages) otherwise. `--engine parakeet|whisper` forces one. (Cohere
123
125
  Transcribe tops the leaderboard on paper but its mlx-audio quants produced
124
126
  garbage and ran 40-70x slower on a Mac in testing, so it is not wired in.)
125
127
 
@@ -145,9 +147,10 @@ Use `--plan` first when you want to inspect the kept segment JSON before encodin
145
147
 
146
148
  ## Ducking (declare in-composition / bake for export)
147
149
 
148
- B1, declare ducking in the composition. `audio-duck.mjs` emits GSAP volume
149
- keyframes. Paste them into the composition timeline, the source file stays
150
- untouched.
150
+ B1, declare ducking in the composition. `audio-duck.mjs` emits a volume lane
151
+ as a `data-automation` attribute. Add it to the background `<audio>` element;
152
+ the source file stays untouched. Lane times are clip-local, so pass
153
+ `--composition` to let the script subtract the element's `data-start`.
151
154
 
152
155
  ```bash
153
156
  node <SKILL_DIR>/scripts/audio-duck.mjs \
@@ -156,10 +159,9 @@ node <SKILL_DIR>/scripts/audio-duck.mjs \
156
159
  --composition index.html
157
160
  ```
158
161
 
159
- ```js
160
- // auto-duck: #bgm under narration (generated; base volume 0.6)
161
- tl.to("#bgm", { volume: 0.15, duration: 0.15 }, 3.42);
162
- tl.to("#bgm", { volume: 0.6, duration: 0.4 }, 9.87);
162
+ ```html
163
+ <!-- auto-duck: #bgm under narration; add to its <audio> element -->
164
+ data-automation='{"version":1,"lanes":[{"target":"volume","points":[{"t":0,"v":0.6},{"t":3.42,"v":0.6},{"t":3.57,"v":0.15},{"t":9.87,"v":0.15},{"t":10.27,"v":0.6}]}]}'
163
165
  ```
164
166
 
165
167
  B2, bake ducking only for exported or standalone files.
@@ -1,7 +1,7 @@
1
1
  # Resolve — command, flags, reuse, adopt, inventory
2
2
 
3
3
  ```bash
4
- node <SKILL_DIR>/scripts/resolve.mjs --type <type> --intent "<description>" --project <dir>
4
+ npx hyperframes media-use resolve --type <type> --intent "<description>" --project <dir>
5
5
  ```
6
6
 
7
7
  Returns one line: `resolved <id> → <path> (<type>, <metadata>)`
@@ -14,7 +14,7 @@ Returns one line: `resolved <id> → <path> (<type>, <metadata>)`
14
14
  | `sfx` | Sound effects | Bundled 19-file library + HeyGen catalog |
15
15
  | `image` | Photos, backgrounds | HeyGen asset search (75k+ vectors) |
16
16
  | `icon` | Icons, symbols | HeyGen asset search (type=icon) |
17
- | `logo` | Official brand marks | svgl → simple-icons → GitHub org avatar → domain favicon |
17
+ | `logo` | Official brand marks | theSVG → GitHub org avatar → domain favicon |
18
18
  | `voice` | TTS voiceover | HeyGen TTS free-usage path; optional local Kokoro |
19
19
  | `grade` | HyperFrames color-grading blocks | Core preset → look index params/CDN LUT → deterministic cube |
20
20
  | `lut` | Reusable `.cube` LUT files | Look index params/CDN LUT → deterministic cube |
@@ -23,31 +23,31 @@ Returns one line: `resolved <id> → <path> (<type>, <metadata>)`
23
23
 
24
24
  ```bash
25
25
  # Background music
26
- node <SKILL_DIR>/scripts/resolve.mjs --type bgm --intent "upbeat tech launch" --project .
26
+ npx hyperframes media-use resolve --type bgm --intent "upbeat tech launch" --project .
27
27
  # → resolved bgm_001 → .media/audio/bgm/bgm_001.mp3 (bgm, 25s)
28
28
 
29
29
  # Sound effect
30
- node <SKILL_DIR>/scripts/resolve.mjs --type sfx --intent "whoosh" --project .
30
+ npx hyperframes media-use resolve --type sfx --intent "whoosh" --project .
31
31
  # → resolved sfx_001 → .media/audio/sfx/sfx_001.mp3 (sfx, 0.57s)
32
32
 
33
33
  # Image
34
- node <SKILL_DIR>/scripts/resolve.mjs --type image --intent "gradient tech background" --project .
34
+ npx hyperframes media-use resolve --type image --intent "gradient tech background" --project .
35
35
  # → resolved image_001 → .media/images/image_001.jpg (image)
36
36
 
37
37
  # Icon
38
- node <SKILL_DIR>/scripts/resolve.mjs --type icon --intent "rocket" --project .
38
+ npx hyperframes media-use resolve --type icon --intent "rocket" --project .
39
39
  # → resolved icon_001 → .media/images/icon_001.png (icon, transparent)
40
40
 
41
41
  # Brand logo (official mark — never redrawn by hand)
42
- node <SKILL_DIR>/scripts/resolve.mjs --type logo --entity linkedin --intent "LinkedIn logo" --project .
42
+ npx hyperframes media-use resolve --type logo --entity linkedin --intent "LinkedIn logo" --project .
43
43
  # → resolved logo_001 → .media/images/logo_001.svg (logo, official mark)
44
44
 
45
45
  # Color grade block
46
- node <SKILL_DIR>/scripts/resolve.mjs --type grade --intent "warm daylight" --project . --json
46
+ npx hyperframes media-use resolve --type grade --intent "warm daylight" --project . --json
47
47
  # → {"ok":true,"preset":"warm-daylight","grading":{"preset":"warm-daylight","intensity":1},...}
48
48
 
49
49
  # LUT file
50
- node <SKILL_DIR>/scripts/resolve.mjs --type lut --intent "teal orange blockbuster" --project .
50
+ npx hyperframes media-use resolve --type lut --intent "teal orange blockbuster" --project .
51
51
  # → resolved lut_001 → .media/luts/lut_001.cube (lut)
52
52
  ```
53
53
 
@@ -76,7 +76,7 @@ node <SKILL_DIR>/scripts/resolve.mjs --type lut --intent "teal orange blockbuste
76
76
  Before resolving bgm/sfx/image/icon/logo/grade/lut, **check what already exists and reuse it when it fits.** media-use does not semantically match for you — you are the judge. It surfaces candidates; you decide.
77
77
 
78
78
  ```bash
79
- node <SKILL_DIR>/scripts/resolve.mjs --type bgm --intent "upbeat tech launch" --candidates --project .
79
+ npx hyperframes media-use resolve --type bgm --intent "upbeat tech launch" --candidates --project .
80
80
  # [project] upbeat tech launch (25s, heygen.audio.sounds)
81
81
  # .media/audio/bgm/bgm_001.wav
82
82
  # [global] energetic tech intro (22s, heygen.audio.sounds)
@@ -105,12 +105,23 @@ The deterministic floor still runs automatically: an identical (case/whitespace-
105
105
 
106
106
  Steps 1 and 3 are the **deterministic floor**: they only auto-reuse an exact-normalized match, never a fuzzy one. Semantic reuse ("close enough") is the agent's explicit call via [Reuse before you resolve](#reuse-before-you-resolve) — it never happens automatically. The agent gets back **one line**; candidates, scores, provenance stay on disk.
107
107
 
108
+ ## Stamping provenance when mounting a resolved video
109
+
110
+ `resolve` never writes composition HTML itself — mounting a `<video>` element
111
+ into a composition is always the agent's own edit. When the mounted video's
112
+ manifest record has `provenance.provider === "heygen.video"` (check
113
+ `.media/manifest.jsonl` or the one-line resolve output for the provider name),
114
+ add `data-media-source="heygen"` to that `<video>` tag. Leave the attribute off
115
+ entirely for every other provider (`ltx.local`, an adopted/local file, etc.) —
116
+ this is not a general provider taxonomy, just the one signal render telemetry
117
+ tracks today.
118
+
108
119
  ## Adopt existing projects
109
120
 
110
121
  Most HyperFrames projects already have assets in `assets/`. media-use adopts them:
111
122
 
112
123
  ```bash
113
- node <SKILL_DIR>/scripts/resolve.mjs --adopt --project .
124
+ npx hyperframes media-use resolve --adopt --project .
114
125
  # → adopted 9 assets from assets/
115
126
  # bgm_001 → assets/bgm/mango-fizz.mp3 (bgm, 146.6s)
116
127
  # image_001 → assets/images/avatar.jpg (image, 400×400)
@@ -12,7 +12,7 @@ heygen auth login --oauth # OAuth = free subscription credits; --api-key bills A
12
12
  This unlocks the FREE path for bgm/sfx/image/icon catalog search, TTS (voice), and avatar videos. Sign in with `--oauth` — the free allowance rides on the OAuth session (an API key bills API credits instead). **media-use requires heygen >= v0.3.0 uniformly** (the OAuth free-usage path needs it), so `--doctor` nudges older CLIs to update even for API-key-only use. Before resolving anything, verify setup with:
13
13
 
14
14
  ```bash
15
- node <SKILL_DIR>/scripts/resolve.mjs --doctor
15
+ npx hyperframes media-use resolve --doctor
16
16
  ```
17
17
 
18
18
  ## Providers
@@ -31,7 +31,7 @@ see the ladder and override.
31
31
  | image | heygen search free-usage path; optional local mflux; codex `image_gen` upsell |
32
32
  | voice | heygen tts free-usage path; optional local **Kokoro** (free, on-device) |
33
33
  | icon | heygen asset search free-usage path |
34
- | logo | svgl, then simple-icons, then GitHub org avatar, then domain favicon (all free) |
34
+ | logo | theSVG (thesvg.org), then GitHub org avatar, then domain favicon (all free) |
35
35
  | grade/lut | local core-preset map, params/CDN look index, deterministic `buildCube` fallback |
36
36
  | video | heygen avatar video free-usage path (sign-in nudge on auth failure); optional local LTX (`videogen` ladder). Image-to-video / photo-avatar / dub stay manual `heygen` recipes |
37
37
 
@@ -59,15 +59,15 @@ tools are OPT-IN alternatives where they exist; install one to unlock its free,
59
59
  private, on-device path instead of or ahead of HeyGen for that type. Only
60
60
  `ffmpeg`/`ffprobe` are strictly required for the tool to run at all.
61
61
 
62
- | Tool | Serves | Install |
63
- | ------------------ | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
64
- | `ffmpeg`/`ffprobe` | adopt probing, smart-grade signalstats, cut, duck bake, loudnorm | system package (`brew install ffmpeg`) |
65
- | `heygen` | catalog (bgm/sfx/image/icon) + TTS (voice) + avatar video — the free-usage path | install through [verified HeyGen release instructions](https://developers.heygen.com/cli), then `heygen auth login --oauth` (needs >= v0.3.0) |
66
- | `mflux-generate` | local image gen (FLUX), best-for-RAM | `uv venv ~/.venvs/mflux && VIRTUAL_ENV=~/.venvs/mflux uv pip install mflux==0.9.6` |
67
- | `codex` | image gen upsell (ChatGPT sub) | Codex CLI, logged in via ChatGPT (owns its own auth) |
68
- | `parakeet-mlx` | local transcription (default ASR, best) | `uv venv ~/.venvs/parakeet && VIRTUAL_ENV=~/.venvs/parakeet uv pip install parakeet-mlx` |
69
- | `ltx-2-mlx` | local video gen | `git clone https://github.com/dgrauet/ltx-2-mlx && cd ltx-2-mlx && uv sync --all-extras` |
70
- | `npx hyperframes` | Kokoro TTS (voice), whisper.cpp (transcribe fallback), remove-background | via the hyperframes CLI; whisper.cpp is built on first use (Homebrew on macOS, else git+cmake), models download from HuggingFace |
62
+ | Tool | Serves | Install |
63
+ | ------------------ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
64
+ | `ffmpeg`/`ffprobe` | adopt probing, smart-grade signalstats, cut, duck bake, loudnorm | system package (`brew install ffmpeg`) |
65
+ | `heygen` | catalog (bgm/sfx/image/icon) + TTS (voice) + avatar video — the free-usage path | install through [verified HeyGen release instructions](https://developers.heygen.com/cli), then `heygen auth login --oauth` (needs >= v0.3.0) |
66
+ | `mflux-generate` | local image gen (FLUX), best-for-RAM | `uv venv ~/.venvs/mflux && VIRTUAL_ENV=~/.venvs/mflux uv pip install mflux==0.9.6` |
67
+ | `codex` | image gen upsell (ChatGPT sub) | Codex CLI, logged in via ChatGPT (owns its own auth) |
68
+ | `parakeet-mlx` | local transcription (default ASR, best) on Apple Silicon | `uv venv ~/.venvs/parakeet && VIRTUAL_ENV=~/.venvs/parakeet uv pip install parakeet-mlx` |
69
+ | `ltx-2-mlx` | local video gen | `git clone https://github.com/dgrauet/ltx-2-mlx && cd ltx-2-mlx && uv sync --all-extras` |
70
+ | `npx hyperframes` | Kokoro TTS (voice), Parakeet or whisper.cpp (transcribe), remove-background | via the hyperframes CLI; Parakeet on macOS, Windows and glibc 2.32+ Linux: `npx hyperframes models install parakeet`; whisper.cpp is built on first use (Homebrew on macOS, else git+cmake) |
71
71
 
72
72
  The RAM-graded local-model shortlist + exact per-tier install/invoke lives in
73
73
  `scripts/lib/local-models.mjs` (the agent can read `describeModelLadder(cap, specs)`
@@ -3,7 +3,7 @@
3
3
  import { readFileSync } from "node:fs";
4
4
  import { resolve } from "node:path";
5
5
  import { parseArgs } from "node:util";
6
- import { duckKeyframes, speechSpans } from "./lib/duck.mjs";
6
+ import { duckKeyframes, duckLane, speechSpans } from "./lib/duck.mjs";
7
7
  import { track } from "./lib/telemetry.mjs";
8
8
 
9
9
  const { values: args } = parseArgs({
@@ -25,7 +25,7 @@ const { values: args } = parseArgs({
25
25
  });
26
26
 
27
27
  if (args.help) {
28
- console.log(`media-use audio-duck — generate GSAP volume ducking keyframes
28
+ console.log(`media-use audio-duck — generate a volume ducking lane (data-automation)
29
29
 
30
30
  Usage:
31
31
  node audio-duck.mjs --meta audio_meta.json --target "#bgm"
@@ -40,8 +40,8 @@ Options:
40
40
  --sequential Place multi-line meta back to back at composition time
41
41
  --gap Extra seconds between sequential lines (default: 0)
42
42
  --offsets Explicit placement, "l1=0,l2=3.4" (voice id = start seconds)
43
- --composition Read target data-volume from this HTML file
44
- --json Output { spans, keyframes }
43
+ --composition Read target data-volume and data-start from this HTML file
44
+ --json Output { spans, keyframes, lane }
45
45
  --help, -h Show this help`);
46
46
  process.exit(0);
47
47
  }
@@ -59,7 +59,7 @@ function run() {
59
59
  if (!args.meta || !args.target) throw new Error("--meta and --target are required");
60
60
  const meta = JSON.parse(readFileSync(resolve(args.meta), "utf8"));
61
61
  const target = args.target;
62
- const baseVolume = readBaseVolume(args.composition, target);
62
+ const { baseVolume, clipStart } = readTargetAttrs(args.composition, target);
63
63
  const offsets = args.offsets
64
64
  ? Object.fromEntries(
65
65
  args.offsets.split(",").map((pair) => {
@@ -81,41 +81,33 @@ function run() {
81
81
  baseVolume,
82
82
  });
83
83
 
84
+ const lane = duckLane(keyframes, { clipStart, baseVolume });
85
+
84
86
  if (args.json) {
85
- console.log(JSON.stringify({ spans, keyframes }));
87
+ console.log(JSON.stringify({ spans, keyframes, lane }));
86
88
  return;
87
89
  }
88
90
 
89
- console.log(
90
- `// auto-duck: ${target} under narration (generated; base volume ${fmt(baseVolume)})`,
91
- );
92
- for (const keyframe of keyframes) {
93
- console.log(
94
- `tl.to(${JSON.stringify(target)}, { volume: ${fmt(keyframe.volume)}, duration: ${fmt(
95
- keyframe.duration,
96
- )} }, ${fmt(keyframe.time)});`,
97
- );
98
- }
91
+ console.log(`<!-- auto-duck: ${target} under narration; add to its <audio> element -->`);
92
+ console.log(`data-automation='${JSON.stringify(lane)}'`);
99
93
  }
100
94
 
101
- function readBaseVolume(composition, target) {
102
- if (!composition || !target.startsWith("#")) return 1;
95
+ function readTargetAttrs(composition, target) {
96
+ if (!composition || !target.startsWith("#")) return { baseVolume: 1, clipStart: 0 };
103
97
  const id = target.slice(1);
104
98
  const html = readFileSync(resolve(composition), "utf8");
105
99
  // ponytail: regex is enough here because this only reads one attribute from
106
100
  // one user-authored composition element, not arbitrary HTML.
107
101
  const tag = html.match(new RegExp(`<[^>]*\\bid=["']${escapeRegExp(id)}["'][^>]*>`, "i"))?.[0];
108
- const raw = tag?.match(/\bdata-volume=["']([^"']+)["']/i)?.[1];
109
- const volume = Number(raw);
110
- return Number.isFinite(volume) ? volume : 1;
102
+ const attr = (name) => Number(tag?.match(new RegExp(`\\b${name}=["']([^"']+)["']`, "i"))?.[1]);
103
+ const volume = attr("data-volume");
104
+ const start = attr("data-start");
105
+ return {
106
+ baseVolume: Number.isFinite(volume) ? volume : 1,
107
+ clipStart: Number.isFinite(start) ? start : 0,
108
+ };
111
109
  }
112
110
 
113
111
  function escapeRegExp(value) {
114
112
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
115
113
  }
116
-
117
- function fmt(n) {
118
- return Number(n)
119
- .toFixed(3)
120
- .replace(/\.?0+$/, "");
121
- }
@@ -0,0 +1,96 @@
1
+ import assert from "node:assert/strict";
2
+ import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { execFileSync } from "node:child_process";
6
+ import test from "node:test";
7
+ import { pathToFileURL } from "node:url";
8
+
9
+ process.env.HYPERFRAMES_MEDIA_HOME = mkdtempSync(join(tmpdir(), "media-use-compat-home-"));
10
+
11
+ function run(scriptsDir, script, args) {
12
+ return execFileSync(process.execPath, [join(scriptsDir, script), ...args], {
13
+ encoding: "utf8",
14
+ stdio: ["ignore", "pipe", "pipe"],
15
+ });
16
+ }
17
+
18
+ test("published memory scripts run without reaching outside the skill", () => {
19
+ const scratchDir = mkdtempSync(join(tmpdir(), "media-use-compat-"));
20
+ const skillDir = join(scratchDir, "media-use");
21
+ cpSync(new URL("..", import.meta.url), skillDir, { recursive: true });
22
+ const scriptsDir = join(skillDir, "scripts");
23
+ const projectDir = join(scratchDir, "project");
24
+ try {
25
+ run(scriptsDir, "prefs.mjs", ["get", "--hyperframes", projectDir, "--json"]);
26
+ run(scriptsDir, "recipe.mjs", ["list", "--hyperframes", projectDir, "--json"]);
27
+ run(scriptsDir, "transcribe.mjs", ["--help"]);
28
+ } finally {
29
+ rmSync(scratchDir, { recursive: true, force: true });
30
+ }
31
+ });
32
+
33
+ test("published audio helpers import without the CLI package tree", () => {
34
+ const root = mkdtempSync(join(tmpdir(), "media-use-audio-"));
35
+ const skill = join(root, "media-use");
36
+ try {
37
+ cpSync(new URL("..", import.meta.url), skill, { recursive: true });
38
+ for (const helper of ["heygen.mjs", "tts.mjs"])
39
+ run(join(skill, "audio/scripts/lib"), helper, []);
40
+ } finally {
41
+ rmSync(root, { recursive: true, force: true });
42
+ }
43
+ });
44
+
45
+ for (const name of ["faceless-explainer", "pr-to-video", "product-launch-video"]) {
46
+ test(name + " assembles from its installed directory alone", () => {
47
+ const root = mkdtempSync(join(tmpdir(), "installed-workflow-"));
48
+ try {
49
+ const skill = join(root, name);
50
+ cpSync(new URL("../../" + name, import.meta.url), skill, { recursive: true });
51
+ const project = join(root, "project");
52
+ mkdirSync(join(project, "compositions/frames"), { recursive: true });
53
+ writeFileSync(
54
+ join(project, "STORYBOARD.md"),
55
+ "---\nformat: 1920x1080\nmessage: Test\n---\n\n## Frame 1\n- duration: 3s\n- src: compositions/frames/01-a.html\n",
56
+ );
57
+ writeFileSync(
58
+ join(project, "compositions/frames/01-a.html"),
59
+ '<template><div data-composition-id="01-a" data-duration="3" data-width="1920" data-height="1080"><section class="clip" data-start="0" data-duration="3"></section></div></template>',
60
+ );
61
+ run(join(skill, "scripts"), "assemble-index.mjs", [
62
+ "--hyperframes",
63
+ project,
64
+ "--storyboard",
65
+ join(project, "STORYBOARD.md"),
66
+ ]);
67
+ assert.match(readFileSync(join(project, "index.html"), "utf8"), /01-a/);
68
+ importPacketBuilder(join(skill, "scripts/frame-packets.mjs"));
69
+ } finally {
70
+ rmSync(root, { recursive: true, force: true });
71
+ }
72
+ });
73
+ }
74
+
75
+ test("general-video packet builder starts from its installed directory alone", () => {
76
+ const root = mkdtempSync(join(tmpdir(), "installed-packets-"));
77
+ try {
78
+ cpSync(new URL("../../general-video", import.meta.url), root, { recursive: true });
79
+ importPacketBuilder(join(root, "scripts/frame-packets.mjs"));
80
+ } finally {
81
+ rmSync(root, { recursive: true, force: true });
82
+ }
83
+ });
84
+
85
+ function importPacketBuilder(path) {
86
+ execFileSync(
87
+ process.execPath,
88
+ [
89
+ "--input-type=module",
90
+ "-e",
91
+ 'const m = await import(process.argv[1]); if (typeof m.buildFramePackets !== "function") throw new Error("missing builder");',
92
+ pathToFileURL(path).href,
93
+ ],
94
+ { stdio: "pipe" },
95
+ );
96
+ }
@@ -0,0 +1,45 @@
1
+ // The one lock on ~/.hyperframes/config.json, for the CLI, its auto-update step and media-use. The auto-update step
2
+ // embeds this function's source, so it must use only its arguments and globals.
3
+ export function withFileLock(lockPath, fs, task) {
4
+ const token = `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
5
+ const started = Date.now();
6
+ for (;;) {
7
+ let fd;
8
+ try {
9
+ fd = fs.openSync(lockPath, "wx");
10
+ } catch (error) {
11
+ if (error.code !== "EEXIST") throw error;
12
+ // Never taken over: a lock older than any hold was left by a process that stopped, and a person removes it.
13
+ let leftover = false;
14
+ try {
15
+ leftover = Date.now() - fs.statSync(lockPath).mtimeMs > 5000;
16
+ } catch {}
17
+ if (leftover || Date.now() - started > 10000)
18
+ throw Object.assign(
19
+ new Error(
20
+ `Settings are locked by another hyperframes process. If none is running, delete ${lockPath}`,
21
+ ),
22
+ { code: "HF_SETTINGS_LOCKED" },
23
+ );
24
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25);
25
+ continue;
26
+ }
27
+ try {
28
+ fs.writeSync(fd, token);
29
+ } catch (error) {
30
+ fs.rmSync(lockPath, { force: true });
31
+ throw error;
32
+ } finally {
33
+ fs.closeSync(fd);
34
+ }
35
+ break;
36
+ }
37
+ try {
38
+ return task();
39
+ } finally {
40
+ // No code removes another's lock, so release needs no check (only a person deleting a live one defeats it).
41
+ try {
42
+ fs.rmSync(lockPath);
43
+ } catch {}
44
+ }
45
+ }
@@ -1,15 +1,6 @@
1
1
  import { wordListsFromMediaMeta } from "./words.mjs";
2
2
 
3
- /**
4
- * Speech spans from word timestamps.
5
- *
6
- * audio_meta.json word times are relative to EACH LINE'S OWN FILE, not to the
7
- * composition. Without placement info, multiple lines would overlap at t=0 and
8
- * merge into one bogus span. Placement options:
9
- * offsets: { [voiceId]: startSeconds } explicit composition placement
10
- * sequential: stack lines back to back (plus `gap` seconds between lines)
11
- * A single word list (bare transcript) needs neither.
12
- */
3
+ // audio_meta.json word times are relative to each line's own file.
13
4
  export function speechSpans(meta, { mergeGap = 0.6, offsets, sequential = false, gap = 0 } = {}) {
14
5
  const merge = Number(mergeGap);
15
6
  const lists = wordListsFromMediaMeta(meta);
@@ -63,6 +54,21 @@ export function duckKeyframes(
63
54
  return keyframes.sort((a, b) => a.time - b.time);
64
55
  }
65
56
 
57
+ /** Volume lane for `data-automation`: composition-time keyframes as clip-local ramps. */
58
+ export function duckLane(keyframes, { clipStart = 0, baseVolume = 1 } = {}) {
59
+ const start = finiteOr(clipStart, 0);
60
+ const points = [{ t: 0, v: round3(finiteOr(baseVolume, 1)) }];
61
+ const push = (t, v) => {
62
+ if (t > points.at(-1).t) points.push({ t: round3(t), v });
63
+ };
64
+ for (const kf of keyframes) {
65
+ const t = Math.max(0, kf.time - start);
66
+ push(t, points.at(-1).v);
67
+ push(t + kf.duration, kf.volume);
68
+ }
69
+ return { version: 1, lanes: [{ target: "volume", points }] };
70
+ }
71
+
66
72
  function mergeIntervals(intervals, mergeGap) {
67
73
  const sorted = intervals
68
74
  .map((range) => ({ start: round3(range.start), end: round3(range.end) }))