@amg555/frameforge-mcp 2.7.3 → 2.7.7

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 (565) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/AGENTS.md +33 -0
  3. package/CHANGELOG.md +49 -0
  4. package/CLAUDE.md +17 -6
  5. package/GEMINI.md +63 -0
  6. package/README.md +216 -426
  7. package/START_HERE.md +4 -2
  8. package/package.json +5 -3
  9. package/plugins/ai-video-editor/README.md +32 -0
  10. package/plugins/ai-video-editor/SKILL.md +152 -0
  11. package/plugins/ai-video-editor/assets/fonts/fonts.css +2409 -0
  12. package/plugins/ai-video-editor/assets/fonts/ttf/anton-400.ttf +0 -0
  13. package/plugins/ai-video-editor/assets/fonts/ttf/archivo-800.ttf +0 -0
  14. package/plugins/ai-video-editor/assets/fonts/ttf/cabin-sketch-700.ttf +0 -0
  15. package/plugins/ai-video-editor/assets/fonts/ttf/dm-sans-700.ttf +0 -0
  16. package/plugins/ai-video-editor/assets/fonts/ttf/fraunces-600.ttf +0 -0
  17. package/plugins/ai-video-editor/assets/fonts/ttf/fraunces-700.ttf +0 -0
  18. package/plugins/ai-video-editor/assets/fonts/ttf/fredoka-700.ttf +0 -0
  19. package/plugins/ai-video-editor/assets/fonts/ttf/inter-700.ttf +0 -0
  20. package/plugins/ai-video-editor/assets/fonts/ttf/inter-800.ttf +0 -0
  21. package/plugins/ai-video-editor/assets/fonts/ttf/inter-tight-800.ttf +0 -0
  22. package/plugins/ai-video-editor/assets/fonts/ttf/kalam-700.ttf +0 -0
  23. package/plugins/ai-video-editor/assets/fonts/ttf/noto-sans-devanagari-700.ttf +0 -0
  24. package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-400-normal.woff2 +0 -0
  25. package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-500-normal.woff2 +0 -0
  26. package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-600-normal.woff2 +0 -0
  27. package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-700-normal.woff2 +0 -0
  28. package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-800-normal.woff2 +0 -0
  29. package/plugins/ai-video-editor/engine/hidpi.js +117 -0
  30. package/plugins/ai-video-editor/engine/page.html +43 -0
  31. package/plugins/ai-video-editor/engine/player.js +145 -0
  32. package/plugins/ai-video-editor/references/example-story-warm-canvas.js +95 -0
  33. package/plugins/ai-video-editor/references/story-guide.md +112 -0
  34. package/plugins/ai-video-editor/requirements.txt +4 -0
  35. package/plugins/ai-video-editor/styles/chalk-talk/base.js +490 -0
  36. package/plugins/ai-video-editor/styles/chalk-talk/style.json +14 -0
  37. package/plugins/ai-video-editor/styles/chalk-talk/style.md +41 -0
  38. package/plugins/ai-video-editor/styles/clean-tech/base.js +447 -0
  39. package/plugins/ai-video-editor/styles/clean-tech/style.json +15 -0
  40. package/plugins/ai-video-editor/styles/clean-tech/style.md +38 -0
  41. package/plugins/ai-video-editor/styles/creator-motion-graphics/base.js +698 -0
  42. package/plugins/ai-video-editor/styles/creator-motion-graphics/style.json +16 -0
  43. package/plugins/ai-video-editor/styles/creator-motion-graphics/style.md +39 -0
  44. package/plugins/ai-video-editor/styles/data-story/base.js +432 -0
  45. package/plugins/ai-video-editor/styles/data-story/style.json +14 -0
  46. package/plugins/ai-video-editor/styles/data-story/style.md +38 -0
  47. package/plugins/ai-video-editor/styles/index.json +103 -0
  48. package/plugins/ai-video-editor/styles/pop-info/base.js +570 -0
  49. package/plugins/ai-video-editor/styles/pop-info/style.json +13 -0
  50. package/plugins/ai-video-editor/styles/pop-info/style.md +37 -0
  51. package/plugins/ai-video-editor/styles/software-walkthrough/base.js +544 -0
  52. package/plugins/ai-video-editor/styles/software-walkthrough/style.json +15 -0
  53. package/plugins/ai-video-editor/styles/software-walkthrough/style.md +38 -0
  54. package/plugins/ai-video-editor/styles/warm-canvas/base.js +610 -0
  55. package/plugins/ai-video-editor/styles/warm-canvas/style.json +14 -0
  56. package/plugins/ai-video-editor/styles/warm-canvas/style.md +37 -0
  57. package/plugins/aiinsight-shorts/CHANGELOG.md +6 -0
  58. package/plugins/aiinsight-shorts/README.md +43 -0
  59. package/plugins/aiinsight-shorts/SKILL.md +138 -0
  60. package/plugins/aiinsight-shorts/styles/deep-dive/STYLE.md +58 -0
  61. package/plugins/aiinsight-shorts/styles/deep-dive/example/data/cues.json +140 -0
  62. package/plugins/aiinsight-shorts/styles/deep-dive/example/data/lines.json +67 -0
  63. package/plugins/aiinsight-shorts/styles/deep-dive/example/data/words.json +614 -0
  64. package/plugins/aiinsight-shorts/styles/deep-dive/example/data/words.txt +102 -0
  65. package/plugins/aiinsight-shorts/styles/deep-dive/example/fonts/Inter-Black.otf +0 -0
  66. package/plugins/aiinsight-shorts/styles/deep-dive/example/fonts/Inter-ExtraBold.otf +0 -0
  67. package/plugins/aiinsight-shorts/styles/deep-dive/example/index.html +17 -0
  68. package/plugins/aiinsight-shorts/styles/deep-dive/example/script.json +27 -0
  69. package/plugins/aiinsight-shorts/styles/deep-dive/example/sheet.html +11 -0
  70. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/board.js +62 -0
  71. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/captions.js +68 -0
  72. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/engine.js +65 -0
  73. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/human.js +128 -0
  74. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/lib.js +44 -0
  75. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/look2d.js +33 -0
  76. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/sdf.js +79 -0
  77. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/sets.js +107 -0
  78. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/timing.js +23 -0
  79. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/main.js +56 -0
  80. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/sheet.js +79 -0
  81. package/plugins/aiinsight-shorts/styles/deep-dive/example/src/shots.js +136 -0
  82. package/plugins/aiinsight-shorts/styles/deep-dive/example/tools/capture.mjs +122 -0
  83. package/plugins/aiinsight-shorts/styles/deep-dive/example/tools/mix.py +172 -0
  84. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/LICENSE-three.txt +21 -0
  85. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/environments/RoomEnvironment.js +144 -0
  86. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/BokehPass.js +141 -0
  87. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
  88. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/MaskPass.js +104 -0
  89. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/OutputPass.js +97 -0
  90. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/Pass.js +95 -0
  91. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/RenderPass.js +99 -0
  92. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
  93. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
  94. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/BokehShader.js +145 -0
  95. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/CopyShader.js +45 -0
  96. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
  97. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/OutputShader.js +85 -0
  98. package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/three.module.js +6 -0
  99. package/plugins/aiinsight-shorts/styles/deep-dive/style-sheet.png +0 -0
  100. package/plugins/aiinsight-shorts/styles/inside-out/STYLE.md +97 -0
  101. package/plugins/aiinsight-shorts/styles/inside-out/example/data/cues.json +178 -0
  102. package/plugins/aiinsight-shorts/styles/inside-out/example/data/lines.json +73 -0
  103. package/plugins/aiinsight-shorts/styles/inside-out/example/data/words.json +662 -0
  104. package/plugins/aiinsight-shorts/styles/inside-out/example/fonts/Inter-Black.otf +0 -0
  105. package/plugins/aiinsight-shorts/styles/inside-out/example/index.html +17 -0
  106. package/plugins/aiinsight-shorts/styles/inside-out/example/script.json +26 -0
  107. package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/captions.js +68 -0
  108. package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/kit.js +345 -0
  109. package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/lib.js +44 -0
  110. package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/timing.js +23 -0
  111. package/plugins/aiinsight-shorts/styles/inside-out/example/src/main.js +62 -0
  112. package/plugins/aiinsight-shorts/styles/inside-out/example/src/shots.js +195 -0
  113. package/plugins/aiinsight-shorts/styles/inside-out/example/tools/capture.mjs +122 -0
  114. package/plugins/aiinsight-shorts/styles/inside-out/example/tools/mix.py +172 -0
  115. package/plugins/aiinsight-shorts/styles/inside-out/style-sheet.png +0 -0
  116. package/plugins/aiinsight-shorts/styles/night-file/STYLE.md +36 -0
  117. package/plugins/aiinsight-shorts/styles/night-file/example/data/cues.json +146 -0
  118. package/plugins/aiinsight-shorts/styles/night-file/example/data/lines.json +73 -0
  119. package/plugins/aiinsight-shorts/styles/night-file/example/data/words.json +572 -0
  120. package/plugins/aiinsight-shorts/styles/night-file/example/data/words.txt +95 -0
  121. package/plugins/aiinsight-shorts/styles/night-file/example/fonts/FreeMonoBold.ttf +0 -0
  122. package/plugins/aiinsight-shorts/styles/night-file/example/fonts/Inter-Black.otf +0 -0
  123. package/plugins/aiinsight-shorts/styles/night-file/example/index.html +18 -0
  124. package/plugins/aiinsight-shorts/styles/night-file/example/script.json +26 -0
  125. package/plugins/aiinsight-shorts/styles/night-file/example/sheet.html +13 -0
  126. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/board.js +62 -0
  127. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/captions.js +49 -0
  128. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/engine.js +65 -0
  129. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/human.js +128 -0
  130. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/kit.js +151 -0
  131. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/lib.js +44 -0
  132. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/sdf.js +79 -0
  133. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/sets3d.js +106 -0
  134. package/plugins/aiinsight-shorts/styles/night-file/example/src/core/timing.js +23 -0
  135. package/plugins/aiinsight-shorts/styles/night-file/example/src/main.js +56 -0
  136. package/plugins/aiinsight-shorts/styles/night-file/example/src/sheet.js +86 -0
  137. package/plugins/aiinsight-shorts/styles/night-file/example/src/shots.js +130 -0
  138. package/plugins/aiinsight-shorts/styles/night-file/example/tools/capture.mjs +122 -0
  139. package/plugins/aiinsight-shorts/styles/night-file/example/tools/mix.py +172 -0
  140. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/LICENSE-three.txt +21 -0
  141. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/environments/RoomEnvironment.js +144 -0
  142. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/BokehPass.js +141 -0
  143. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
  144. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/MaskPass.js +104 -0
  145. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/OutputPass.js +97 -0
  146. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/Pass.js +95 -0
  147. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/RenderPass.js +99 -0
  148. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
  149. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
  150. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/BokehShader.js +145 -0
  151. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/CopyShader.js +45 -0
  152. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
  153. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/OutputShader.js +85 -0
  154. package/plugins/aiinsight-shorts/styles/night-file/example/vendor/three.module.js +6 -0
  155. package/plugins/aiinsight-shorts/styles/night-file/style-sheet.png +0 -0
  156. package/plugins/aiinsight-shorts/styles/paper-atlas/STYLE.md +30 -0
  157. package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/cues.json +167 -0
  158. package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/lines.json +67 -0
  159. package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/words.json +614 -0
  160. package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/words.txt +102 -0
  161. package/plugins/aiinsight-shorts/styles/paper-atlas/example/fonts/Caladea-Bold.ttf +0 -0
  162. package/plugins/aiinsight-shorts/styles/paper-atlas/example/fonts/Inter-Black.otf +0 -0
  163. package/plugins/aiinsight-shorts/styles/paper-atlas/example/index.html +15 -0
  164. package/plugins/aiinsight-shorts/styles/paper-atlas/example/script.json +26 -0
  165. package/plugins/aiinsight-shorts/styles/paper-atlas/example/sheet.html +12 -0
  166. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/board.js +62 -0
  167. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/captions.js +47 -0
  168. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/kit.js +152 -0
  169. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/lib.js +44 -0
  170. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/timing.js +23 -0
  171. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/main.js +62 -0
  172. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/sheet.js +61 -0
  173. package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/shots.js +139 -0
  174. package/plugins/aiinsight-shorts/styles/paper-atlas/example/tools/capture.mjs +122 -0
  175. package/plugins/aiinsight-shorts/styles/paper-atlas/example/tools/mix.py +172 -0
  176. package/plugins/aiinsight-shorts/styles/paper-atlas/style-sheet.png +0 -0
  177. package/plugins/aiinsight-shorts/styles/stick-story/STYLE.md +32 -0
  178. package/plugins/aiinsight-shorts/styles/stick-story/example/data/cues.json +182 -0
  179. package/plugins/aiinsight-shorts/styles/stick-story/example/data/lines.json +79 -0
  180. package/plugins/aiinsight-shorts/styles/stick-story/example/data/words.json +662 -0
  181. package/plugins/aiinsight-shorts/styles/stick-story/example/data/words.txt +110 -0
  182. package/plugins/aiinsight-shorts/styles/stick-story/example/fonts/Inter-Black.otf +0 -0
  183. package/plugins/aiinsight-shorts/styles/stick-story/example/fonts/Inter-ExtraBold.otf +0 -0
  184. package/plugins/aiinsight-shorts/styles/stick-story/example/index.html +13 -0
  185. package/plugins/aiinsight-shorts/styles/stick-story/example/script.json +27 -0
  186. package/plugins/aiinsight-shorts/styles/stick-story/example/sheet.html +10 -0
  187. package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/board.js +62 -0
  188. package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/captions.js +47 -0
  189. package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/kit.js +166 -0
  190. package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/lib.js +44 -0
  191. package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/timing.js +23 -0
  192. package/plugins/aiinsight-shorts/styles/stick-story/example/src/main.js +62 -0
  193. package/plugins/aiinsight-shorts/styles/stick-story/example/src/sheet.js +64 -0
  194. package/plugins/aiinsight-shorts/styles/stick-story/example/src/shots.js +148 -0
  195. package/plugins/aiinsight-shorts/styles/stick-story/example/tools/capture.mjs +122 -0
  196. package/plugins/aiinsight-shorts/styles/stick-story/example/tools/mix.py +172 -0
  197. package/plugins/aiinsight-shorts/styles/stick-story/style-sheet.png +0 -0
  198. package/plugins/aiinsight-shorts/styles/tall-tale/STYLE.md +51 -0
  199. package/plugins/aiinsight-shorts/styles/tall-tale/example/data/cues.json +271 -0
  200. package/plugins/aiinsight-shorts/styles/tall-tale/example/data/lines.json +127 -0
  201. package/plugins/aiinsight-shorts/styles/tall-tale/example/data/words.json +908 -0
  202. package/plugins/aiinsight-shorts/styles/tall-tale/example/data/words.txt +151 -0
  203. package/plugins/aiinsight-shorts/styles/tall-tale/example/fonts/Caladea-Bold.ttf +0 -0
  204. package/plugins/aiinsight-shorts/styles/tall-tale/example/fonts/Inter-Black.otf +0 -0
  205. package/plugins/aiinsight-shorts/styles/tall-tale/example/fonts/Inter-ExtraBold.otf +0 -0
  206. package/plugins/aiinsight-shorts/styles/tall-tale/example/index.html +19 -0
  207. package/plugins/aiinsight-shorts/styles/tall-tale/example/script.json +37 -0
  208. package/plugins/aiinsight-shorts/styles/tall-tale/example/sheet.html +13 -0
  209. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/board.js +62 -0
  210. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/captions.js +56 -0
  211. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/engine.js +65 -0
  212. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/lib.js +44 -0
  213. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/props.js +166 -0
  214. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/timing.js +23 -0
  215. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/toon.js +352 -0
  216. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/world.js +340 -0
  217. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/main.js +56 -0
  218. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/sheet.js +99 -0
  219. package/plugins/aiinsight-shorts/styles/tall-tale/example/src/shots.js +377 -0
  220. package/plugins/aiinsight-shorts/styles/tall-tale/example/tools/capture.mjs +122 -0
  221. package/plugins/aiinsight-shorts/styles/tall-tale/example/tools/mix.py +204 -0
  222. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/LICENSE-three.txt +21 -0
  223. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/environments/RoomEnvironment.js +144 -0
  224. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/BokehPass.js +141 -0
  225. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
  226. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/MaskPass.js +104 -0
  227. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/OutputPass.js +97 -0
  228. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/Pass.js +95 -0
  229. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/RenderPass.js +99 -0
  230. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
  231. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
  232. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/BokehShader.js +145 -0
  233. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/CopyShader.js +45 -0
  234. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
  235. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/OutputShader.js +85 -0
  236. package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/three.module.js +6 -0
  237. package/plugins/aiinsight-shorts/styles/tall-tale/style-sheet.png +0 -0
  238. package/plugins/faceless-shorts/README.md +34 -0
  239. package/plugins/faceless-shorts/SKILL.md +124 -0
  240. package/plugins/faceless-shorts/styles/deep-dive/STYLE.md +58 -0
  241. package/plugins/faceless-shorts/styles/deep-dive/example/data/cues.json +140 -0
  242. package/plugins/faceless-shorts/styles/deep-dive/example/data/lines.json +67 -0
  243. package/plugins/faceless-shorts/styles/deep-dive/example/data/words.json +614 -0
  244. package/plugins/faceless-shorts/styles/deep-dive/example/data/words.txt +102 -0
  245. package/plugins/faceless-shorts/styles/deep-dive/example/fonts/Inter-Black.otf +0 -0
  246. package/plugins/faceless-shorts/styles/deep-dive/example/fonts/Inter-ExtraBold.otf +0 -0
  247. package/plugins/faceless-shorts/styles/deep-dive/example/index.html +16 -0
  248. package/plugins/faceless-shorts/styles/deep-dive/example/script.json +27 -0
  249. package/plugins/faceless-shorts/styles/deep-dive/example/sheet.html +10 -0
  250. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/board.js +62 -0
  251. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/captions.js +68 -0
  252. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/engine.js +65 -0
  253. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/human.js +128 -0
  254. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/lib.js +44 -0
  255. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/look2d.js +33 -0
  256. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/sdf.js +79 -0
  257. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/sets.js +107 -0
  258. package/plugins/faceless-shorts/styles/deep-dive/example/src/core/timing.js +23 -0
  259. package/plugins/faceless-shorts/styles/deep-dive/example/src/main.js +56 -0
  260. package/plugins/faceless-shorts/styles/deep-dive/example/src/sheet.js +79 -0
  261. package/plugins/faceless-shorts/styles/deep-dive/example/src/shots.js +136 -0
  262. package/plugins/faceless-shorts/styles/deep-dive/example/tools/capture.mjs +122 -0
  263. package/plugins/faceless-shorts/styles/deep-dive/example/tools/mix.py +172 -0
  264. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/LICENSE-three.txt +21 -0
  265. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/environments/RoomEnvironment.js +144 -0
  266. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/BokehPass.js +141 -0
  267. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
  268. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/MaskPass.js +104 -0
  269. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/OutputPass.js +97 -0
  270. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/Pass.js +95 -0
  271. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/RenderPass.js +99 -0
  272. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
  273. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
  274. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/BokehShader.js +145 -0
  275. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/CopyShader.js +45 -0
  276. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
  277. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/OutputShader.js +85 -0
  278. package/plugins/faceless-shorts/styles/deep-dive/example/vendor/three.module.js +6 -0
  279. package/plugins/faceless-shorts/styles/deep-dive/style-sheet.png +0 -0
  280. package/plugins/faceless-shorts/styles/inside-out/STYLE.md +97 -0
  281. package/plugins/faceless-shorts/styles/inside-out/example/data/cues.json +178 -0
  282. package/plugins/faceless-shorts/styles/inside-out/example/data/lines.json +73 -0
  283. package/plugins/faceless-shorts/styles/inside-out/example/data/words.json +662 -0
  284. package/plugins/faceless-shorts/styles/inside-out/example/fonts/Inter-Black.otf +0 -0
  285. package/plugins/faceless-shorts/styles/inside-out/example/index.html +16 -0
  286. package/plugins/faceless-shorts/styles/inside-out/example/script.json +26 -0
  287. package/plugins/faceless-shorts/styles/inside-out/example/src/core/captions.js +68 -0
  288. package/plugins/faceless-shorts/styles/inside-out/example/src/core/kit.js +345 -0
  289. package/plugins/faceless-shorts/styles/inside-out/example/src/core/lib.js +44 -0
  290. package/plugins/faceless-shorts/styles/inside-out/example/src/core/timing.js +23 -0
  291. package/plugins/faceless-shorts/styles/inside-out/example/src/main.js +62 -0
  292. package/plugins/faceless-shorts/styles/inside-out/example/src/shots.js +195 -0
  293. package/plugins/faceless-shorts/styles/inside-out/example/tools/capture.mjs +122 -0
  294. package/plugins/faceless-shorts/styles/inside-out/example/tools/mix.py +172 -0
  295. package/plugins/faceless-shorts/styles/inside-out/style-sheet.png +0 -0
  296. package/plugins/faceless-shorts/styles/night-file/STYLE.md +36 -0
  297. package/plugins/faceless-shorts/styles/night-file/example/data/cues.json +146 -0
  298. package/plugins/faceless-shorts/styles/night-file/example/data/lines.json +73 -0
  299. package/plugins/faceless-shorts/styles/night-file/example/data/words.json +572 -0
  300. package/plugins/faceless-shorts/styles/night-file/example/data/words.txt +95 -0
  301. package/plugins/faceless-shorts/styles/night-file/example/fonts/FreeMonoBold.ttf +0 -0
  302. package/plugins/faceless-shorts/styles/night-file/example/fonts/Inter-Black.otf +0 -0
  303. package/plugins/faceless-shorts/styles/night-file/example/index.html +16 -0
  304. package/plugins/faceless-shorts/styles/night-file/example/script.json +26 -0
  305. package/plugins/faceless-shorts/styles/night-file/example/sheet.html +11 -0
  306. package/plugins/faceless-shorts/styles/night-file/example/src/core/board.js +62 -0
  307. package/plugins/faceless-shorts/styles/night-file/example/src/core/captions.js +49 -0
  308. package/plugins/faceless-shorts/styles/night-file/example/src/core/engine.js +65 -0
  309. package/plugins/faceless-shorts/styles/night-file/example/src/core/human.js +128 -0
  310. package/plugins/faceless-shorts/styles/night-file/example/src/core/kit.js +151 -0
  311. package/plugins/faceless-shorts/styles/night-file/example/src/core/lib.js +44 -0
  312. package/plugins/faceless-shorts/styles/night-file/example/src/core/sdf.js +79 -0
  313. package/plugins/faceless-shorts/styles/night-file/example/src/core/sets3d.js +106 -0
  314. package/plugins/faceless-shorts/styles/night-file/example/src/core/timing.js +23 -0
  315. package/plugins/faceless-shorts/styles/night-file/example/src/main.js +56 -0
  316. package/plugins/faceless-shorts/styles/night-file/example/src/sheet.js +86 -0
  317. package/plugins/faceless-shorts/styles/night-file/example/src/shots.js +130 -0
  318. package/plugins/faceless-shorts/styles/night-file/example/tools/capture.mjs +122 -0
  319. package/plugins/faceless-shorts/styles/night-file/example/tools/mix.py +172 -0
  320. package/plugins/faceless-shorts/styles/night-file/example/vendor/LICENSE-three.txt +21 -0
  321. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/environments/RoomEnvironment.js +144 -0
  322. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/BokehPass.js +141 -0
  323. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
  324. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/MaskPass.js +104 -0
  325. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/OutputPass.js +97 -0
  326. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/Pass.js +95 -0
  327. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/RenderPass.js +99 -0
  328. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
  329. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
  330. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/BokehShader.js +145 -0
  331. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/CopyShader.js +45 -0
  332. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
  333. package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/OutputShader.js +85 -0
  334. package/plugins/faceless-shorts/styles/night-file/example/vendor/three.module.js +6 -0
  335. package/plugins/faceless-shorts/styles/night-file/style-sheet.png +0 -0
  336. package/plugins/faceless-shorts/styles/paper-atlas/STYLE.md +30 -0
  337. package/plugins/faceless-shorts/styles/paper-atlas/example/data/cues.json +167 -0
  338. package/plugins/faceless-shorts/styles/paper-atlas/example/data/lines.json +67 -0
  339. package/plugins/faceless-shorts/styles/paper-atlas/example/data/words.json +614 -0
  340. package/plugins/faceless-shorts/styles/paper-atlas/example/data/words.txt +102 -0
  341. package/plugins/faceless-shorts/styles/paper-atlas/example/fonts/Caladea-Bold.ttf +0 -0
  342. package/plugins/faceless-shorts/styles/paper-atlas/example/fonts/Inter-Black.otf +0 -0
  343. package/plugins/faceless-shorts/styles/paper-atlas/example/index.html +13 -0
  344. package/plugins/faceless-shorts/styles/paper-atlas/example/script.json +26 -0
  345. package/plugins/faceless-shorts/styles/paper-atlas/example/sheet.html +10 -0
  346. package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/board.js +62 -0
  347. package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/captions.js +47 -0
  348. package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/kit.js +152 -0
  349. package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/lib.js +44 -0
  350. package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/timing.js +23 -0
  351. package/plugins/faceless-shorts/styles/paper-atlas/example/src/main.js +62 -0
  352. package/plugins/faceless-shorts/styles/paper-atlas/example/src/sheet.js +61 -0
  353. package/plugins/faceless-shorts/styles/paper-atlas/example/src/shots.js +139 -0
  354. package/plugins/faceless-shorts/styles/paper-atlas/example/tools/capture.mjs +122 -0
  355. package/plugins/faceless-shorts/styles/paper-atlas/example/tools/mix.py +172 -0
  356. package/plugins/faceless-shorts/styles/paper-atlas/style-sheet.png +0 -0
  357. package/plugins/faceless-shorts/styles/stick-story/STYLE.md +32 -0
  358. package/plugins/faceless-shorts/styles/stick-story/example/data/cues.json +182 -0
  359. package/plugins/faceless-shorts/styles/stick-story/example/data/lines.json +79 -0
  360. package/plugins/faceless-shorts/styles/stick-story/example/data/words.json +662 -0
  361. package/plugins/faceless-shorts/styles/stick-story/example/data/words.txt +110 -0
  362. package/plugins/faceless-shorts/styles/stick-story/example/fonts/Inter-Black.otf +0 -0
  363. package/plugins/faceless-shorts/styles/stick-story/example/fonts/Inter-ExtraBold.otf +0 -0
  364. package/plugins/faceless-shorts/styles/stick-story/example/index.html +12 -0
  365. package/plugins/faceless-shorts/styles/stick-story/example/script.json +27 -0
  366. package/plugins/faceless-shorts/styles/stick-story/example/sheet.html +9 -0
  367. package/plugins/faceless-shorts/styles/stick-story/example/src/core/board.js +62 -0
  368. package/plugins/faceless-shorts/styles/stick-story/example/src/core/captions.js +47 -0
  369. package/plugins/faceless-shorts/styles/stick-story/example/src/core/kit.js +166 -0
  370. package/plugins/faceless-shorts/styles/stick-story/example/src/core/lib.js +44 -0
  371. package/plugins/faceless-shorts/styles/stick-story/example/src/core/timing.js +23 -0
  372. package/plugins/faceless-shorts/styles/stick-story/example/src/main.js +62 -0
  373. package/plugins/faceless-shorts/styles/stick-story/example/src/sheet.js +64 -0
  374. package/plugins/faceless-shorts/styles/stick-story/example/src/shots.js +148 -0
  375. package/plugins/faceless-shorts/styles/stick-story/example/tools/capture.mjs +122 -0
  376. package/plugins/faceless-shorts/styles/stick-story/example/tools/mix.py +172 -0
  377. package/plugins/faceless-shorts/styles/stick-story/style-sheet.png +0 -0
  378. package/plugins/faceless-shorts/styles/tall-tale/STYLE.md +51 -0
  379. package/plugins/faceless-shorts/styles/tall-tale/example/data/cues.json +271 -0
  380. package/plugins/faceless-shorts/styles/tall-tale/example/data/lines.json +127 -0
  381. package/plugins/faceless-shorts/styles/tall-tale/example/data/words.json +908 -0
  382. package/plugins/faceless-shorts/styles/tall-tale/example/data/words.txt +151 -0
  383. package/plugins/faceless-shorts/styles/tall-tale/example/fonts/Caladea-Bold.ttf +0 -0
  384. package/plugins/faceless-shorts/styles/tall-tale/example/fonts/Inter-Black.otf +0 -0
  385. package/plugins/faceless-shorts/styles/tall-tale/example/fonts/Inter-ExtraBold.otf +0 -0
  386. package/plugins/faceless-shorts/styles/tall-tale/example/index.html +17 -0
  387. package/plugins/faceless-shorts/styles/tall-tale/example/script.json +37 -0
  388. package/plugins/faceless-shorts/styles/tall-tale/example/sheet.html +11 -0
  389. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/board.js +62 -0
  390. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/captions.js +56 -0
  391. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/engine.js +65 -0
  392. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/lib.js +44 -0
  393. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/props.js +166 -0
  394. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/timing.js +23 -0
  395. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/toon.js +352 -0
  396. package/plugins/faceless-shorts/styles/tall-tale/example/src/core/world.js +340 -0
  397. package/plugins/faceless-shorts/styles/tall-tale/example/src/main.js +56 -0
  398. package/plugins/faceless-shorts/styles/tall-tale/example/src/sheet.js +99 -0
  399. package/plugins/faceless-shorts/styles/tall-tale/example/src/shots.js +377 -0
  400. package/plugins/faceless-shorts/styles/tall-tale/example/tools/capture.mjs +122 -0
  401. package/plugins/faceless-shorts/styles/tall-tale/example/tools/mix.py +204 -0
  402. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/LICENSE-three.txt +21 -0
  403. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/environments/RoomEnvironment.js +144 -0
  404. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/BokehPass.js +141 -0
  405. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
  406. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/MaskPass.js +104 -0
  407. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/OutputPass.js +97 -0
  408. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/Pass.js +95 -0
  409. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/RenderPass.js +99 -0
  410. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
  411. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
  412. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/BokehShader.js +145 -0
  413. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/CopyShader.js +45 -0
  414. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
  415. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/OutputShader.js +85 -0
  416. package/plugins/faceless-shorts/styles/tall-tale/example/vendor/three.module.js +6 -0
  417. package/plugins/faceless-shorts/styles/tall-tale/style-sheet.png +0 -0
  418. package/plugins/motion-styles/LIBRARY.md +896 -0
  419. package/plugins/motion-styles/README.md +29 -0
  420. package/plugins/motion-styles/SKILL.md +70 -0
  421. package/plugins/motion-styles/catalog.json +2253 -0
  422. package/plugins/motion-styles/prompts/bio-glow.md +149 -0
  423. package/plugins/motion-styles/prompts/blueprint.md +145 -0
  424. package/plugins/motion-styles/prompts/breaking-desk.md +147 -0
  425. package/plugins/motion-styles/prompts/callout-kit.md +147 -0
  426. package/plugins/motion-styles/prompts/chalk-talk.md +153 -0
  427. package/plugins/motion-styles/prompts/chat-story.md +143 -0
  428. package/plugins/motion-styles/prompts/clay-diorama.md +149 -0
  429. package/plugins/motion-styles/prompts/clean-tech.md +147 -0
  430. package/plugins/motion-styles/prompts/comic-panels.md +145 -0
  431. package/plugins/motion-styles/prompts/cosmic-scale.md +147 -0
  432. package/plugins/motion-styles/prompts/creator-motion.md +149 -0
  433. package/plugins/motion-styles/prompts/data-city.md +149 -0
  434. package/plugins/motion-styles/prompts/data-story.md +147 -0
  435. package/plugins/motion-styles/prompts/deep-layers.md +147 -0
  436. package/plugins/motion-styles/prompts/doc-cinema.md +145 -0
  437. package/plugins/motion-styles/prompts/evidence-board.md +145 -0
  438. package/plugins/motion-styles/prompts/exploded-view.md +149 -0
  439. package/plugins/motion-styles/prompts/glass-icons.md +147 -0
  440. package/plugins/motion-styles/prompts/glitch-pack.md +145 -0
  441. package/plugins/motion-styles/prompts/globe-arcs.md +147 -0
  442. package/plugins/motion-styles/prompts/headline-backdrop.md +145 -0
  443. package/plugins/motion-styles/prompts/iso-cutaway.md +147 -0
  444. package/plugins/motion-styles/prompts/isotype.md +145 -0
  445. package/plugins/motion-styles/prompts/karaoke-subs.md +145 -0
  446. package/plugins/motion-styles/prompts/low-poly-atlas.md +149 -0
  447. package/plugins/motion-styles/prompts/lower-thirds.md +147 -0
  448. package/plugins/motion-styles/prompts/marker-board.md +145 -0
  449. package/plugins/motion-styles/prompts/market-tape.md +145 -0
  450. package/plugins/motion-styles/prompts/math-canvas.md +145 -0
  451. package/plugins/motion-styles/prompts/myth-or-fact.md +145 -0
  452. package/plugins/motion-styles/prompts/neon-line.md +145 -0
  453. package/plugins/motion-styles/prompts/paper-craft.md +145 -0
  454. package/plugins/motion-styles/prompts/parchment-map.md +147 -0
  455. package/plugins/motion-styles/prompts/physics-toybox.md +147 -0
  456. package/plugins/motion-styles/prompts/pixel-quest.md +145 -0
  457. package/plugins/motion-styles/prompts/podcast-clip.md +147 -0
  458. package/plugins/motion-styles/prompts/pop-info.md +145 -0
  459. package/plugins/motion-styles/prompts/product-turntable.md +149 -0
  460. package/plugins/motion-styles/prompts/punch-captions.md +145 -0
  461. package/plugins/motion-styles/prompts/quiz-countdown.md +145 -0
  462. package/plugins/motion-styles/prompts/quote-cinema.md +145 -0
  463. package/plugins/motion-styles/prompts/recipe-steps.md +145 -0
  464. package/plugins/motion-styles/prompts/rubber-hose-reel.md +145 -0
  465. package/plugins/motion-styles/prompts/shadow-puppets.md +145 -0
  466. package/plugins/motion-styles/prompts/size-lineup.md +149 -0
  467. package/plugins/motion-styles/prompts/software-walkthrough.md +147 -0
  468. package/plugins/motion-styles/prompts/stack-split.md +145 -0
  469. package/plugins/motion-styles/prompts/sticker-pop.md +145 -0
  470. package/plugins/motion-styles/prompts/storybook.md +145 -0
  471. package/plugins/motion-styles/prompts/swiss-grid.md +145 -0
  472. package/plugins/motion-styles/prompts/synth-grid.md +147 -0
  473. package/plugins/motion-styles/prompts/tactics-board.md +145 -0
  474. package/plugins/motion-styles/prompts/terminal.md +145 -0
  475. package/plugins/motion-styles/prompts/tier-list.md +143 -0
  476. package/plugins/motion-styles/prompts/timeline-rail.md +145 -0
  477. package/plugins/motion-styles/prompts/top-5-countdown.md +145 -0
  478. package/plugins/motion-styles/prompts/versus-split.md +145 -0
  479. package/plugins/motion-styles/prompts/vhs-camcorder.md +145 -0
  480. package/plugins/motion-styles/prompts/visual-novel.md +145 -0
  481. package/plugins/motion-styles/prompts/warm-canvas.md +145 -0
  482. package/plugins/motion-styles/prompts/woodcut-tale.md +145 -0
  483. package/plugins/motion-styles/prompts/zine-collage.md +145 -0
  484. package/plugins/motion-styles/sources/bio-glow.html +639 -0
  485. package/plugins/motion-styles/sources/blueprint.html +617 -0
  486. package/plugins/motion-styles/sources/breaking-desk.html +585 -0
  487. package/plugins/motion-styles/sources/callout-kit.html +586 -0
  488. package/plugins/motion-styles/sources/chalk-talk.html +597 -0
  489. package/plugins/motion-styles/sources/chat-story.html +597 -0
  490. package/plugins/motion-styles/sources/clay-diorama.html +681 -0
  491. package/plugins/motion-styles/sources/clean-tech.html +554 -0
  492. package/plugins/motion-styles/sources/comic-panels.html +608 -0
  493. package/plugins/motion-styles/sources/cosmic-scale.html +628 -0
  494. package/plugins/motion-styles/sources/creator-motion.html +805 -0
  495. package/plugins/motion-styles/sources/data-city.html +613 -0
  496. package/plugins/motion-styles/sources/data-story.html +539 -0
  497. package/plugins/motion-styles/sources/deep-layers.html +624 -0
  498. package/plugins/motion-styles/sources/doc-cinema.html +590 -0
  499. package/plugins/motion-styles/sources/evidence-board.html +610 -0
  500. package/plugins/motion-styles/sources/exploded-view.html +618 -0
  501. package/plugins/motion-styles/sources/glass-icons.html +612 -0
  502. package/plugins/motion-styles/sources/glitch-pack.html +583 -0
  503. package/plugins/motion-styles/sources/globe-arcs.html +621 -0
  504. package/plugins/motion-styles/sources/headline-backdrop.html +584 -0
  505. package/plugins/motion-styles/sources/iso-cutaway.html +621 -0
  506. package/plugins/motion-styles/sources/isotype.html +588 -0
  507. package/plugins/motion-styles/sources/karaoke-subs.html +577 -0
  508. package/plugins/motion-styles/sources/low-poly-atlas.html +621 -0
  509. package/plugins/motion-styles/sources/lower-thirds.html +582 -0
  510. package/plugins/motion-styles/sources/marker-board.html +598 -0
  511. package/plugins/motion-styles/sources/market-tape.html +598 -0
  512. package/plugins/motion-styles/sources/math-canvas.html +592 -0
  513. package/plugins/motion-styles/sources/myth-or-fact.html +587 -0
  514. package/plugins/motion-styles/sources/neon-line.html +597 -0
  515. package/plugins/motion-styles/sources/paper-craft.html +612 -0
  516. package/plugins/motion-styles/sources/parchment-map.html +624 -0
  517. package/plugins/motion-styles/sources/physics-toybox.html +617 -0
  518. package/plugins/motion-styles/sources/pixel-quest.html +609 -0
  519. package/plugins/motion-styles/sources/podcast-clip.html +585 -0
  520. package/plugins/motion-styles/sources/pop-info.html +677 -0
  521. package/plugins/motion-styles/sources/product-turntable.html +611 -0
  522. package/plugins/motion-styles/sources/punch-captions.html +583 -0
  523. package/plugins/motion-styles/sources/quiz-countdown.html +593 -0
  524. package/plugins/motion-styles/sources/quote-cinema.html +581 -0
  525. package/plugins/motion-styles/sources/recipe-steps.html +599 -0
  526. package/plugins/motion-styles/sources/rubber-hose-reel.html +627 -0
  527. package/plugins/motion-styles/sources/shadow-puppets.html +609 -0
  528. package/plugins/motion-styles/sources/size-lineup.html +620 -0
  529. package/plugins/motion-styles/sources/software-walkthrough.html +651 -0
  530. package/plugins/motion-styles/sources/stack-split.html +588 -0
  531. package/plugins/motion-styles/sources/sticker-pop.html +587 -0
  532. package/plugins/motion-styles/sources/storybook.html +600 -0
  533. package/plugins/motion-styles/sources/swiss-grid.html +590 -0
  534. package/plugins/motion-styles/sources/synth-grid.html +614 -0
  535. package/plugins/motion-styles/sources/tactics-board.html +608 -0
  536. package/plugins/motion-styles/sources/terminal.html +593 -0
  537. package/plugins/motion-styles/sources/tier-list.html +600 -0
  538. package/plugins/motion-styles/sources/timeline-rail.html +598 -0
  539. package/plugins/motion-styles/sources/top-5-countdown.html +589 -0
  540. package/plugins/motion-styles/sources/versus-split.html +592 -0
  541. package/plugins/motion-styles/sources/vhs-camcorder.html +587 -0
  542. package/plugins/motion-styles/sources/visual-novel.html +623 -0
  543. package/plugins/motion-styles/sources/warm-canvas.html +742 -0
  544. package/plugins/motion-styles/sources/woodcut-tale.html +598 -0
  545. package/plugins/motion-styles/sources/zine-collage.html +594 -0
  546. package/plugins/video-pipeline/.claude-plugin/plugin.json +2 -2
  547. package/plugins/video-pipeline/skills/.upstream-skills.json +156 -143
  548. package/plugins/video-pipeline/skills/video-pipeline/references/mcp-tools.md +3 -3
  549. package/scripts/deep-validate.js +3 -2
  550. package/src/audio-mixer/mixer.js +69 -0
  551. package/src/cli/make.js +19 -0
  552. package/src/harness/lib/browser.mjs +22 -1
  553. package/src/harness/lib/capture.mjs +33 -11
  554. package/src/harness/lib/jobs.mjs +16 -1
  555. package/src/mcp-server/server.js +726 -10
  556. package/src/pipeline/providers.js +77 -17
  557. package/src/skills/sync-upstream.js +15 -3
  558. package/src/utils/media-downloader.js +7 -0
  559. package/src/utils/tool-installer.js +212 -0
  560. package/src/utils/transcribe.js +9 -1
  561. package/src/video-renderer/renderer.js +68 -38
  562. package/src/video-renderer/scene-animator.js +50 -15
  563. package/src/workflows/assets.js +49 -5
  564. package/src/workflows/render.js +2 -0
  565. package/src/workflows/script.js +14 -3
@@ -356,6 +356,8 @@ class TTSProvider {
356
356
  * @param {string} [opts.rate] Speaking rate (overrides TTS_RATE)
357
357
  * @param {string} [opts.apiKey] API key (overrides provider-specific env var)
358
358
  * @param {string} [opts.webhookUrl] Webhook URL (overrides WEBHOOK_TTS_URL)
359
+ * @param {string} [opts.language] BCP-47 language hint (e.g. 'ml', 'hi', 'fr') used as fallback
360
+ * voice selector when text is in a Latin script
359
361
  */
360
362
  constructor(opts = {}) {
361
363
  this.name = (opts.platform || process.env.PROVIDER_TTS || 'edge-tts').toLowerCase();
@@ -371,37 +373,87 @@ class TTSProvider {
371
373
  * @param {string} [text] narration text for language detection
372
374
  * @returns {string}
373
375
  */
374
- selectNarratorVoice(explicitVoice, text = '') {
376
+ selectNarratorVoice(explicitVoice, text = '', langHint = '') {
375
377
  if (explicitVoice) return explicitVoice;
376
378
 
377
- // Language detection for edge-tts
378
- if (this.name === 'edge-tts' && text) {
379
- const gender = (process.env.TTS_VOICE_GENDER || 'default').toLowerCase();
380
- if (/[\u0D00-\u0D7F]/.test(text)) {
379
+ const gender = (process.env.TTS_VOICE_GENDER || 'default').toLowerCase();
380
+
381
+ // Language detection for edge-tts — Unicode-range script detection + BCP-47 hint
382
+ if (this.name === 'edge-tts') {
383
+ // Unicode script ranges (text content detection)
384
+ if (text && /[\u0D00-\u0D7F]/.test(text)) {
381
385
  return gender === 'female' ? 'ml-IN-SobhanaNeural' : 'ml-IN-MidhunNeural';
382
386
  }
383
- if (/[\u0900-\u097F]/.test(text)) {
387
+ if (text && /[\u0900-\u097F]/.test(text)) {
384
388
  return gender === 'female' ? 'hi-IN-SwaraNeural' : 'hi-IN-MadhurNeural';
385
389
  }
386
- if (/[\u0B80-\u0BFF]/.test(text)) {
390
+ if (text && /[\u0B80-\u0BFF]/.test(text)) {
387
391
  return gender === 'female' ? 'ta-IN-PallaviNeural' : 'ta-IN-ValluvarNeural';
388
392
  }
389
- if (/[\u0C00-\u0C7F]/.test(text)) {
393
+ if (text && /[\u0C00-\u0C7F]/.test(text)) {
390
394
  return gender === 'female' ? 'te-IN-ShrutiNeural' : 'te-IN-MohanNeural';
391
395
  }
392
- if (/[\u4E00-\u9FFF]/.test(text)) {
396
+ if (text && /[\u0C80-\u0CFF]/.test(text)) {
397
+ // Kannada
398
+ return gender === 'female' ? 'kn-IN-SapnaNeural' : 'kn-IN-GaganNeural';
399
+ }
400
+ if (text && /[\u0980-\u09FF]/.test(text)) {
401
+ // Bengali
402
+ return gender === 'female' ? 'bn-IN-TanishaaNeural' : 'bn-IN-BashkarNeural';
403
+ }
404
+ if (text && /[\u4E00-\u9FFF\u3400-\u4DBF]/.test(text)) {
393
405
  return gender === 'female' ? 'zh-CN-XiaoxiaoNeural' : 'zh-CN-YunjianNeural';
394
406
  }
395
- if (/[\u3040-\u30FF]/.test(text)) {
407
+ if (text && /[\u3040-\u30FF\u31F0-\u31FF]/.test(text)) {
396
408
  return gender === 'female' ? 'ja-JP-NanamiNeural' : 'ja-JP-KeitaNeural';
397
409
  }
398
- if (/[\u0600-\u06FF]/.test(text)) {
410
+ if (text && /[\uAC00-\uD7AF]/.test(text)) {
411
+ // Korean
412
+ return gender === 'female' ? 'ko-KR-SunHiNeural' : 'ko-KR-InJoonNeural';
413
+ }
414
+ if (text && /[\u0600-\u06FF]/.test(text)) {
399
415
  return gender === 'female' ? 'ar-SA-ZariyahNeural' : 'ar-SA-HamedNeural';
400
416
  }
417
+ if (text && /[\u0400-\u04FF]/.test(text)) {
418
+ // Cyrillic (Russian)
419
+ return gender === 'female' ? 'ru-RU-SvetlanaNeural' : 'ru-RU-DmitryNeural';
420
+ }
421
+
422
+ // BCP-47 language hint fallback (used when text is English but language is known)
423
+ const lang = (langHint || this._overrides.language || process.env.TTS_LANGUAGE || '').toLowerCase().slice(0, 2);
424
+ const LANG_VOICE_MAP = {
425
+ ml: gender === 'female' ? 'ml-IN-SobhanaNeural' : 'ml-IN-MidhunNeural',
426
+ hi: gender === 'female' ? 'hi-IN-SwaraNeural' : 'hi-IN-MadhurNeural',
427
+ ta: gender === 'female' ? 'ta-IN-PallaviNeural' : 'ta-IN-ValluvarNeural',
428
+ te: gender === 'female' ? 'te-IN-ShrutiNeural' : 'te-IN-MohanNeural',
429
+ kn: gender === 'female' ? 'kn-IN-SapnaNeural' : 'kn-IN-GaganNeural',
430
+ bn: gender === 'female' ? 'bn-IN-TanishaaNeural' : 'bn-IN-BashkarNeural',
431
+ mr: gender === 'female' ? 'mr-IN-AarohiNeural' : 'mr-IN-ManoharNeural',
432
+ gu: gender === 'female' ? 'gu-IN-DhwaniNeural' : 'gu-IN-NiranjanNeural',
433
+ pa: gender === 'female' ? 'pa-IN-OjasvNeural' : 'pa-IN-OjasvNeural',
434
+ ur: gender === 'female' ? 'ur-PK-UzmaNeural' : 'ur-PK-AsadNeural',
435
+ zh: gender === 'female' ? 'zh-CN-XiaoxiaoNeural' : 'zh-CN-YunjianNeural',
436
+ ja: gender === 'female' ? 'ja-JP-NanamiNeural' : 'ja-JP-KeitaNeural',
437
+ ko: gender === 'female' ? 'ko-KR-SunHiNeural' : 'ko-KR-InJoonNeural',
438
+ ar: gender === 'female' ? 'ar-SA-ZariyahNeural' : 'ar-SA-HamedNeural',
439
+ ru: gender === 'female' ? 'ru-RU-SvetlanaNeural' : 'ru-RU-DmitryNeural',
440
+ fr: gender === 'female' ? 'fr-FR-DeniseNeural' : 'fr-FR-HenriNeural',
441
+ de: gender === 'female' ? 'de-DE-KatjaNeural' : 'de-DE-ConradNeural',
442
+ es: gender === 'female' ? 'es-ES-ElviraNeural' : 'es-ES-AlvaroNeural',
443
+ pt: gender === 'female' ? 'pt-BR-FranciscaNeural': 'pt-BR-AntonioNeural',
444
+ it: gender === 'female' ? 'it-IT-ElsaNeural' : 'it-IT-DiegoNeural',
445
+ nl: gender === 'female' ? 'nl-NL-ColetteNeural' : 'nl-NL-MaartenNeural',
446
+ pl: gender === 'female' ? 'pl-PL-ZofiaNeural' : 'pl-PL-MarekNeural',
447
+ sv: gender === 'female' ? 'sv-SE-SofieNeural' : 'sv-SE-MattiasNeural',
448
+ tr: gender === 'female' ? 'tr-TR-EmelNeural' : 'tr-TR-AhmetNeural',
449
+ vi: gender === 'female' ? 'vi-VN-HoaiMyNeural' : 'vi-VN-NamMinhNeural',
450
+ id: gender === 'female' ? 'id-ID-GadisNeural' : 'id-ID-ArdiNeural',
451
+ th: gender === 'female' ? 'th-TH-PremwadeeNeural': 'th-TH-NiwatNeural',
452
+ };
453
+ if (lang && LANG_VOICE_MAP[lang]) return LANG_VOICE_MAP[lang];
401
454
  }
402
455
 
403
- const voices = NARRATOR_VOICES[this.name] || NARRATOR_VOICES['edge-tts'];
404
- const gender = (process.env.TTS_VOICE_GENDER || 'default').toLowerCase();
456
+ const voices = NARRATOR_VOICES[this.name] || NARRATOR_VOICES['edge-tts'];
405
457
  return voices[gender] || voices.default;
406
458
  }
407
459
 
@@ -411,8 +463,8 @@ class TTSProvider {
411
463
  * voice is optional — if omitted, selectNarratorVoice() picks automatically
412
464
  * @returns {Promise<string>} resolves with outputPath
413
465
  */
414
- async synthesize({ text, voice, outputPath }) {
415
- const resolvedVoice = this.selectNarratorVoice(voice, text);
466
+ async synthesize({ text, voice, outputPath, language = '' }) {
467
+ const resolvedVoice = this.selectNarratorVoice(voice, text, language);
416
468
  switch (this.name) {
417
469
  case 'edge-tts': return this._edgeTTS({ text, voice: resolvedVoice, outputPath });
418
470
  case 'elevenlabs': return this._elevenLabs({ text, voice: resolvedVoice, outputPath });
@@ -491,6 +543,13 @@ class TTSProvider {
491
543
  }
492
544
 
493
545
  async _edgeTTS({ text, voice, outputPath }) {
546
+ try {
547
+ const { isCommandAvailable, ensureEdgeTts } = require('../utils/tool-installer');
548
+ if (!isCommandAvailable('edge-tts')) {
549
+ ensureEdgeTts();
550
+ }
551
+ } catch (_) {}
552
+
494
553
  const rawPath = outputPath.replace(/\.[^.]+$/, '_raw.mp3');
495
554
  const txtPath = rawPath + '.txt';
496
555
  const safeVoice = voice || this.selectNarratorVoice(null, text);
@@ -507,11 +566,12 @@ class TTSProvider {
507
566
  proc.on('close', code => code === 0 ? resolve() : reject(new Error(`edge-tts exited ${code}: ${stderr}`)));
508
567
  proc.on('error', reject);
509
568
  });
510
- // Normalise audio via FFmpeg — trim trailing silence, normalise levels
569
+ // Normalise audio via FFmpeg — professional sound engineer voice chain:
570
+ // Highpass 80Hz (sub rumble cut) -> Mud notch 300Hz -> Vocal presence 4.5kHz -> Smooth broadcast leveling
511
571
  await new Promise((resolve, reject) => {
512
572
  const proc = spawn('ffmpeg', ['-nostdin', '-y', '-threads', '2',
513
573
  '-i', rawPath,
514
- '-af', 'silenceremove=stop_periods=-1:stop_duration=0.3:stop_threshold=-40dB,highpass=f=80,volume=1.0,dynaudnorm=f=150:g=5:p=0.95',
574
+ '-af', 'silenceremove=stop_periods=-1:stop_duration=0.3:stop_threshold=-40dB,highpass=f=80,equalizer=f=300:t=q:w=1.2:g=-1.5,equalizer=f=4500:t=q:w=1.5:g=1.5,volume=1.0,dynaudnorm=f=150:g=5:p=0.95',
515
575
  '-ar', '48000', '-ac', '2', '-c:a', 'aac', '-b:a', '192k', outputPath], { timeout: 30000 });
516
576
  let stderr = '';
517
577
  proc.stderr?.on('data', d => { stderr += d; });
@@ -99,13 +99,25 @@ const REPOSITORIES = [
99
99
  capabilities: ['edit_video', 'plan_video_edit', 'mix_audio_pro'],
100
100
  userImpact: 'New FFmpeg filter patterns or video editing operations available',
101
101
  },
102
+ {
103
+ id: 'aiinsight-shorts', repo: 'frameforge/aiinsight-shorts', branch: 'main', category: 'shorts',
104
+ desc: '6-style faceless-shorts skill (Deep Dive 3D, Night File 3D, Inside Out, Stick Story, Paper Atlas, Tall Tale 3D) — canvas+three.js, Kokoro TTS, Whisper word-sync, ffmpeg MP4. By Motion Graphics / AI Insight Spot.',
105
+ capabilities: ['create_short', 'list_short_styles'],
106
+ userImpact: 'New faceless-shorts styles, kit components, or rendering techniques available from aiinsight-shorts upstream',
107
+ },
108
+ {
109
+ id: 'openshorts', repo: 'mutonby/openshorts', branch: 'main', category: 'clip-detection',
110
+ desc: 'Open-source OpusClip alternative — AI viral moment detection, face-tracked 9:16 reframing (TRACK/SPLIT/SCREENCAST layouts), karaoke subtitles, hook overlays, social auto-publish. MIT. 7.9k stars.',
111
+ capabilities: ['detect_viral_clips', 'karaoke_subtitles'],
112
+ userImpact: 'New clip detection algorithms, subtitle styles, layout types, or hook rendering techniques from openshorts upstream',
113
+ },
102
114
  ];
103
115
 
104
116
  function fetchJson(url) {
105
117
  return new Promise((resolve, reject) => {
106
118
  const opts = {
107
119
  headers: {
108
- 'User-Agent': 'FrameForge-Skill-Sync/2.7.3',
120
+ 'User-Agent': 'FrameForge-Skill-Sync/2.7.7',
109
121
  'Accept': 'application/vnd.github.v3+json',
110
122
  },
111
123
  };
@@ -176,7 +188,7 @@ async function syncSkills(opts = {}) {
176
188
  const updatedResults = results.filter(r => r.updated);
177
189
 
178
190
  manifest.lastSync = new Date().toISOString();
179
- manifest.version = '2.7.3';
191
+ manifest.version = '2.7.7';
180
192
  manifest.updatedCount = updatedCount;
181
193
  if (updatedResults.length > 0) {
182
194
  manifest.pendingUpdates = updatedResults.map(r => {
@@ -266,7 +278,7 @@ function getUpstreamSummary() {
266
278
  return {
267
279
  repoCount,
268
280
  lastSync: manifest.lastSync,
269
- version: manifest.version || '2.7.3',
281
+ version: manifest.version || '2.7.7',
270
282
  pendingUpdates: pending,
271
283
  hasUpdates: pending.length > 0,
272
284
  repos: manifest.repos || {},
@@ -95,6 +95,13 @@ function downloadMediaWithYtDlp(url, opts = {}) {
95
95
 
96
96
  args.push('-o', outTemplate, url);
97
97
 
98
+ if (!detectYtDlp()) {
99
+ const { ensureYtDlp } = require('./tool-installer');
100
+ if (!ensureYtDlp()) {
101
+ throw new Error('yt-dlp is not installed and auto-install failed. Run: pip install yt-dlp');
102
+ }
103
+ }
104
+
98
105
  const res = spawnSync('yt-dlp', args, {
99
106
  encoding: 'utf8',
100
107
  timeout: 180000, // 3 min max
@@ -0,0 +1,212 @@
1
+ /**
2
+ * tool-installer.js — Automatic Dependency Provisioning for FrameForge
3
+ *
4
+ * Automatically checks and installs required runtime tools on demand:
5
+ * - edge-tts (free broadcast-grade neural TTS)
6
+ * - yt-dlp (video/audio downloader)
7
+ * - whisper (word-level transcription & silence alignment)
8
+ * - playwright chromium (headless browser for code-driven animation)
9
+ *
10
+ * Ensures smooth zero-config experience: users run an npm command and
11
+ * FrameForge automatically fetches missing binaries/packages if needed.
12
+ */
13
+
14
+ 'use strict';
15
+
16
+ const { spawnSync } = require('child_process');
17
+ const path = require('path');
18
+ const fs = require('fs');
19
+
20
+ /**
21
+ * Check if a command is executable on PATH
22
+ * @param {string} cmd
23
+ * @param {string[]} args
24
+ * @returns {boolean}
25
+ */
26
+ function isCommandAvailable(cmd, args = ['--version']) {
27
+ // FFmpeg and FFprobe use single-dash -version
28
+ const checkArgs = (cmd === 'ffmpeg' || cmd === 'ffprobe') && args[0] === '--version'
29
+ ? ['-version']
30
+ : args;
31
+
32
+ const candidates = process.platform === 'win32' && !path.extname(cmd)
33
+ ? [cmd, `${cmd}.exe`, `${cmd}.cmd`, `${cmd}.bat`]
34
+ : [cmd];
35
+
36
+ for (const bin of candidates) {
37
+ try {
38
+ const res = spawnSync(bin, checkArgs, {
39
+ encoding: 'utf8',
40
+ timeout: 4000,
41
+ shell: false,
42
+ });
43
+ if (res.status === 0) return true;
44
+ } catch (_) {}
45
+ }
46
+ return false;
47
+ }
48
+
49
+ /**
50
+ * Run a package installation command synchronously with progress logging
51
+ * @param {string} cmd
52
+ * @param {string[]} args
53
+ * @param {string} toolName
54
+ * @returns {boolean}
55
+ */
56
+ function runInstallCommand(cmd, args, toolName) {
57
+ console.log(`[ToolInstaller] 📦 Auto-installing missing dependency: ${toolName}...`);
58
+ try {
59
+ const res = spawnSync(cmd, args, {
60
+ stdio: 'inherit',
61
+ timeout: 180000, // 3 min cap
62
+ shell: false,
63
+ });
64
+ const ok = res.status === 0;
65
+ if (ok) {
66
+ console.log(`[ToolInstaller] ✔ Successfully installed ${toolName}`);
67
+ } else {
68
+ console.warn(`[ToolInstaller] ⚠️ Automatic install of ${toolName} exited with code ${res.status}`);
69
+ }
70
+ return ok;
71
+ } catch (err) {
72
+ console.warn(`[ToolInstaller] ⚠️ Failed to auto-install ${toolName}: ${err.message}`);
73
+ return false;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Ensure FFmpeg is installed. Auto-installs via system package managers if missing.
79
+ * @returns {boolean}
80
+ */
81
+ function ensureFfmpeg() {
82
+ if (isCommandAvailable('ffmpeg')) return true;
83
+
84
+ console.log('[ToolInstaller] FFmpeg not found on PATH. Attempting automatic installation...');
85
+ if (process.platform === 'win32') {
86
+ if (isCommandAvailable('winget', ['--version'])) {
87
+ if (runInstallCommand('winget', ['install', '--id', 'Gyan.FFmpeg', '-e', '--silent', '--accept-package-agreements', '--accept-source-agreements'], 'FFmpeg (winget)')) {
88
+ return isCommandAvailable('ffmpeg');
89
+ }
90
+ }
91
+ if (isCommandAvailable('choco', ['--version'])) {
92
+ if (runInstallCommand('choco', ['install', 'ffmpeg', '-y'], 'FFmpeg (Chocolatey)')) {
93
+ return isCommandAvailable('ffmpeg');
94
+ }
95
+ }
96
+ if (isCommandAvailable('scoop', ['--version'])) {
97
+ if (runInstallCommand('scoop', ['install', 'ffmpeg'], 'FFmpeg (Scoop)')) {
98
+ return isCommandAvailable('ffmpeg');
99
+ }
100
+ }
101
+ } else if (process.platform === 'darwin') {
102
+ if (isCommandAvailable('brew', ['--version'])) {
103
+ if (runInstallCommand('brew', ['install', 'ffmpeg'], 'FFmpeg (Homebrew)')) {
104
+ return isCommandAvailable('ffmpeg');
105
+ }
106
+ }
107
+ } else if (process.platform === 'linux') {
108
+ if (isCommandAvailable('apt-get', ['--version'])) {
109
+ if (runInstallCommand('sudo', ['apt-get', 'install', '-y', 'ffmpeg'], 'FFmpeg (apt)')) {
110
+ return isCommandAvailable('ffmpeg');
111
+ }
112
+ }
113
+ }
114
+ return false;
115
+ }
116
+
117
+ /**
118
+ * Ensure edge-tts is installed. Auto-installs via pip if missing.
119
+ * @returns {boolean}
120
+ */
121
+ function ensureEdgeTts() {
122
+ if (isCommandAvailable('edge-tts')) return true;
123
+
124
+ console.log('[ToolInstaller] edge-tts CLI not found. Attempting auto-install...');
125
+ // Try python -m pip first, then bare pip
126
+ if (isCommandAvailable('python', ['-m', 'pip', '--version'])) {
127
+ if (runInstallCommand('python', ['-m', 'pip', 'install', '--quiet', 'edge-tts'], 'edge-tts')) {
128
+ return isCommandAvailable('edge-tts');
129
+ }
130
+ }
131
+ if (isCommandAvailable('pip', ['--version'])) {
132
+ if (runInstallCommand('pip', ['install', '--quiet', 'edge-tts'], 'edge-tts')) {
133
+ return isCommandAvailable('edge-tts');
134
+ }
135
+ }
136
+ return false;
137
+ }
138
+
139
+ /**
140
+ * Ensure yt-dlp is installed. Auto-installs via pip if missing.
141
+ * @returns {boolean}
142
+ */
143
+ function ensureYtDlp() {
144
+ if (isCommandAvailable('yt-dlp')) return true;
145
+
146
+ console.log('[ToolInstaller] yt-dlp not found. Attempting auto-install...');
147
+ if (isCommandAvailable('python', ['-m', 'pip', '--version'])) {
148
+ if (runInstallCommand('python', ['-m', 'pip', 'install', '--quiet', 'yt-dlp'], 'yt-dlp')) {
149
+ return isCommandAvailable('yt-dlp');
150
+ }
151
+ }
152
+ if (isCommandAvailable('pip', ['--version'])) {
153
+ if (runInstallCommand('pip', ['install', '--quiet', 'yt-dlp'], 'yt-dlp')) {
154
+ return isCommandAvailable('yt-dlp');
155
+ }
156
+ }
157
+ return false;
158
+ }
159
+
160
+ /**
161
+ * Ensure whisper is installed. Auto-installs via pip if missing.
162
+ * @returns {boolean}
163
+ */
164
+ function ensureWhisper() {
165
+ // Check if python has whisper module
166
+ const check = spawnSync('python', ['-c', 'import whisper; print("ok")'], {
167
+ encoding: 'utf8',
168
+ timeout: 4000,
169
+ shell: process.platform === 'win32',
170
+ });
171
+ if (check.status === 0 && (check.stdout || '').includes('ok')) return true;
172
+
173
+ console.log('[ToolInstaller] Whisper engine not found. Attempting auto-install (openai-whisper)...');
174
+ if (isCommandAvailable('python', ['-m', 'pip', '--version'])) {
175
+ if (runInstallCommand('python', ['-m', 'pip', 'install', '--quiet', 'openai-whisper'], 'openai-whisper')) {
176
+ return true;
177
+ }
178
+ }
179
+ return false;
180
+ }
181
+
182
+ /**
183
+ * Ensure Playwright Chromium browser is installed.
184
+ * @returns {boolean}
185
+ */
186
+ function ensurePlaywrightChromium() {
187
+ console.log('[ToolInstaller] Checking/installing Chromium browser for Playwright...');
188
+ return runInstallCommand('npx', ['playwright', 'install', 'chromium'], 'Chromium (Playwright)');
189
+ }
190
+
191
+ /**
192
+ * Auto-install all recommended dependencies at once
193
+ */
194
+ function autoInstallAll() {
195
+ console.log('\n=== FrameForge Tool Provisioner ===\n');
196
+ const ffmpegOk = ensureFfmpeg();
197
+ const ttsOk = ensureEdgeTts();
198
+ const ytdlpOk = ensureYtDlp();
199
+ const crOk = ensurePlaywrightChromium();
200
+ console.log(`\nResults: ffmpeg: ${ffmpegOk ? '✔' : '✖'}, edge-tts: ${ttsOk ? '✔' : '✖'}, yt-dlp: ${ytdlpOk ? '✔' : '✖'}, chromium: ${crOk ? '✔' : '✖'}\n`);
201
+ return { ffmpegOk, ttsOk, ytdlpOk, crOk };
202
+ }
203
+
204
+ module.exports = {
205
+ isCommandAvailable,
206
+ ensureFfmpeg,
207
+ ensureEdgeTts,
208
+ ensureYtDlp,
209
+ ensureWhisper,
210
+ ensurePlaywrightChromium,
211
+ autoInstallAll,
212
+ };
@@ -204,7 +204,15 @@ async function transcribeAudio(mediaPath, opts = {}) {
204
204
  throw new Error(`Media file not found for transcription: ${mediaPath}`);
205
205
  }
206
206
 
207
- const engine = detectWhisper();
207
+ let engine = detectWhisper();
208
+ if (!engine.available) {
209
+ try {
210
+ const { ensureWhisper } = require('./tool-installer');
211
+ if (ensureWhisper()) {
212
+ engine = detectWhisper();
213
+ }
214
+ } catch (_) {}
215
+ }
208
216
  const pauses = detectPausesWithFFmpeg(mediaPath);
209
217
  let parsed = { text: '', duration: 0, words: [], segments: [] };
210
218
  const isWin = process.platform === 'win32';
@@ -175,6 +175,7 @@ class VideoRenderer {
175
175
  colorGrade = null,
176
176
  showCaptions = false,
177
177
  showAnchor = false,
178
+ sfxCues = [],
178
179
  } = {}) {
179
180
  const effectiveShowCaptions = Boolean(
180
181
  showCaptions ||
@@ -200,7 +201,14 @@ class VideoRenderer {
200
201
  }
201
202
  const voiceDur = this._getAudioDuration(voicePath);
202
203
  const dur = (typeof duration === 'number' && duration > 0) ? Math.max(duration, voiceDur) : voiceDur;
203
- const clampedDur = Math.max(1, Number.isFinite(dur) ? dur + 0.15 : 3.15);
204
+ // Hard cap: individual scenes should be 1–12s. Longer narration → more scenes, not longer frames.
205
+ // This prevents a single browser render job from blocking the pipeline for minutes.
206
+ const MAX_SCENE_DUR = 12;
207
+ const rawDur = Number.isFinite(dur) ? dur + 0.15 : 3.15;
208
+ const clampedDur = Math.min(MAX_SCENE_DUR, Math.max(1, rawDur));
209
+ if (rawDur > MAX_SCENE_DUR) {
210
+ console.warn(`[Renderer] Scene ${sceneIndex}: narration duration ${rawDur.toFixed(2)}s exceeds max ${MAX_SCENE_DUR}s. Clamped. Consider splitting long narration into shorter scenes.`);
211
+ }
204
212
 
205
213
  const isVideoInput = Boolean(videoPath) || (videoPath && /\.(mp4|mov|webm|mkv|m4v)$/i.test(videoPath));
206
214
 
@@ -303,14 +311,17 @@ class VideoRenderer {
303
311
  manifest,
304
312
  musicMood,
305
313
  showCaptions: effectiveShowCaptions,
314
+ showAnchor: effectiveShowAnchor,
315
+ sfxCues,
306
316
  });
307
317
  } catch (err) {
308
- console.warn(`[Renderer] Code-driven browser scene render failed (${err.message}), falling back to procedural animation`);
318
+ console.warn(`[Renderer] Code-driven browser scene render failed (${err.message}):`, err.stack || err);
309
319
  }
310
320
  }
311
321
 
312
- // Priority 3: Procedural dynamic animated fallback (dynamic moving gradients / camera drift)
313
- const captionFilter = effectiveShowCaptions ? this._captionFilter(caption) : '';
322
+ // Priority 3: Procedural dynamic animated fallback (subtle gradient / camera drift)
323
+ const fallbackText = caption || title || topic || '';
324
+ const captionFilter = effectiveShowCaptions ? this._captionFilter(caption) : (fallbackText ? this._captionFilter(fallbackText) : '');
314
325
  let inputArgs = [];
315
326
  let vf = '';
316
327
 
@@ -327,10 +338,10 @@ class VideoRenderer {
327
338
  const c0 = (pal.bg0 || '#0d1117').replace('#', '');
328
339
  const c1 = (pal.accent || '#38bdf8').replace('#', '');
329
340
  inputArgs = [
330
- '-f', 'lavfi', '-i', `gradients=s=${renderWidth}x${renderHeight}:r=30:c0=0x${c0}:c1=0x${c1}:speed=0.5:type=radial`,
341
+ '-f', 'lavfi', '-i', `gradients=s=${renderWidth}x${renderHeight}:r=${fps}:c0=0x${c0}:c1=0x${c1}:speed=0.01:type=linear`,
331
342
  '-i', voicePath,
332
343
  ];
333
- const vfFilters = ['vignette=PI/4'];
344
+ const vfFilters = [];
334
345
  if (captionFilter) vfFilters.push(captionFilter);
335
346
  vf = vfFilters.join(',');
336
347
  }
@@ -389,6 +400,8 @@ class VideoRenderer {
389
400
  manifest,
390
401
  musicMood,
391
402
  showCaptions = false,
403
+ showAnchor = false,
404
+ sfxCues = [],
392
405
  }) {
393
406
  let htmlContent;
394
407
  if (html && typeof html === 'string' && html.trim().length > 0) {
@@ -424,8 +437,8 @@ class VideoRenderer {
424
437
  height: renderHeight,
425
438
  sceneIndex,
426
439
  musicMood,
427
- showCaptions: effectiveShowCaptions,
428
- showAnchor: effectiveShowAnchor,
440
+ showCaptions,
441
+ showAnchor,
429
442
  camera: effectiveCam,
430
443
  cameraHint: effectiveCam,
431
444
  });
@@ -443,12 +456,14 @@ class VideoRenderer {
443
456
  const res = spawnSync(process.execPath, [
444
457
  harnessBin,
445
458
  'frames',
446
- '--html', animHtmlPath,
447
- '--out', framesDir,
448
- '--fps', String(fps),
449
- '--first', '0',
450
- '--last', String(lastFrame),
451
- '--workers', '4',
459
+ '--html', animHtmlPath,
460
+ '--out', framesDir,
461
+ '--fps', String(fps),
462
+ '--first', '0',
463
+ '--last', String(lastFrame),
464
+ '--workers', '2',
465
+ '--width', String(renderWidth),
466
+ '--height', String(renderHeight),
452
467
  ], { encoding: 'utf8', timeout: 5 * 60 * 1000 });
453
468
 
454
469
  if (res.status !== 0) {
@@ -468,36 +483,51 @@ class VideoRenderer {
468
483
  }
469
484
  } catch (_) {}
470
485
 
486
+ // Mix SFX into voice track before encode (earshot perceptual lead contract)
487
+ let audioForEncode = voicePath;
488
+ if (Array.isArray(sfxCues) && sfxCues.length > 0) {
489
+ const sfxMixedPath = path.join(this.vdir, `scene_${sceneIndex}_voice_sfx.m4a`);
490
+ try {
491
+ this.mixer.mixSfxIntoAudio(voicePath, sfxCues, sfxMixedPath);
492
+ audioForEncode = sfxMixedPath;
493
+ console.log(`[Renderer] 🔊 Scene ${sceneIndex}: mixed ${sfxCues.length} SFX cue(s) into audio`);
494
+ } catch (sfxErr) {
495
+ console.warn(`[Renderer] SFX mix failed for scene ${sceneIndex} (using plain voice): ${sfxErr.message}`);
496
+ }
497
+ }
498
+
471
499
  const framesPattern = path.join(framesDir, 'f%06d.jpg');
472
- const encResult = spawnSync('ffmpeg', [
473
- '-nostdin', '-y', '-threads', '2',
474
- '-framerate', String(fps),
475
- '-pattern_type', 'sequence',
476
- '-i', framesPattern,
477
- '-i', voicePath,
478
- '-map', '0:v:0', '-map', '1:a:0',
479
- '-c:v', 'libx264', '-preset', 'fast', '-crf', '17',
480
- '-profile:v', 'high', '-level', '4.1',
481
- '-color_range', 'tv', '-colorspace', 'bt709',
482
- '-color_primaries', 'bt709', '-color_trc', 'bt709',
483
- '-x264-params', 'colorprim=bt709:transfer=bt709:colormatrix=bt709:aq-mode=3:deblock=-1,-1',
484
- '-pix_fmt', 'yuv420p',
485
- '-c:a', 'aac', '-b:a', '320k', '-ar', '48000', '-ac', '2',
486
- '-af', `apad=whole_dur=${clampedDur}`,
487
- '-t', String(clampedDur),
488
- '-movflags', '+faststart',
489
- outputPath,
490
- ], { timeout: 5 * 60 * 1000, encoding: 'utf8' });
500
+ let encResult;
501
+ try {
502
+ encResult = spawnSync('ffmpeg', [
503
+ '-nostdin', '-y', '-threads', '2',
504
+ '-framerate', String(fps),
505
+ '-pattern_type', 'sequence',
506
+ '-i', framesPattern,
507
+ '-i', audioForEncode,
508
+ '-map', '0:v:0', '-map', '1:a:0',
509
+ '-c:v', 'libx264', '-preset', 'fast', '-crf', '17',
510
+ '-profile:v', 'high', '-level', '4.1',
511
+ '-color_range', 'tv', '-colorspace', 'bt709',
512
+ '-color_primaries', 'bt709', '-color_trc', 'bt709',
513
+ '-x264-params', 'colorprim=bt709:transfer=bt709:colormatrix=bt709:aq-mode=3:deblock=-1,-1',
514
+ '-pix_fmt', 'yuv420p',
515
+ '-c:a', 'aac', '-b:a', '320k', '-ar', '48000', '-ac', '2',
516
+ '-af', `apad=whole_dur=${clampedDur}`,
517
+ '-t', String(clampedDur),
518
+ '-movflags', '+faststart',
519
+ outputPath,
520
+ ], { timeout: 5 * 60 * 1000, encoding: 'utf8' });
521
+ } finally {
522
+ // Always clean up frames and html — even if encode fails — to avoid accumulating GBs on disk
523
+ try { fs.rmSync(framesDir, { recursive: true, force: true }); } catch (_) {}
524
+ try { fs.unlinkSync(animHtmlPath); } catch (_) {}
525
+ }
491
526
 
492
527
  if (encResult.status !== 0) {
493
528
  throw new Error(`Scene ${sceneIndex} video encode failed: ${(encResult.stderr || '').slice(-300)}`);
494
529
  }
495
530
 
496
- try {
497
- fs.rmSync(framesDir, { recursive: true, force: true });
498
- fs.unlinkSync(animHtmlPath);
499
- } catch (_) {}
500
-
501
531
  manifest?.setSceneRendered(sceneIndex, outputPath);
502
532
  return outputPath;
503
533
  }