@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.
- package/.claude-plugin/marketplace.json +3 -3
- package/AGENTS.md +33 -0
- package/CHANGELOG.md +49 -0
- package/CLAUDE.md +17 -6
- package/GEMINI.md +63 -0
- package/README.md +216 -426
- package/START_HERE.md +4 -2
- package/package.json +5 -3
- package/plugins/ai-video-editor/README.md +32 -0
- package/plugins/ai-video-editor/SKILL.md +152 -0
- package/plugins/ai-video-editor/assets/fonts/fonts.css +2409 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/anton-400.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/archivo-800.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/cabin-sketch-700.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/dm-sans-700.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/fraunces-600.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/fraunces-700.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/fredoka-700.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/inter-700.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/inter-800.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/inter-tight-800.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/kalam-700.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/ttf/noto-sans-devanagari-700.ttf +0 -0
- package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-400-normal.woff2 +0 -0
- package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-500-normal.woff2 +0 -0
- package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-600-normal.woff2 +0 -0
- package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-700-normal.woff2 +0 -0
- package/plugins/ai-video-editor/assets/fonts/web/noto-sans-devanagari-devanagari-800-normal.woff2 +0 -0
- package/plugins/ai-video-editor/engine/hidpi.js +117 -0
- package/plugins/ai-video-editor/engine/page.html +43 -0
- package/plugins/ai-video-editor/engine/player.js +145 -0
- package/plugins/ai-video-editor/references/example-story-warm-canvas.js +95 -0
- package/plugins/ai-video-editor/references/story-guide.md +112 -0
- package/plugins/ai-video-editor/requirements.txt +4 -0
- package/plugins/ai-video-editor/styles/chalk-talk/base.js +490 -0
- package/plugins/ai-video-editor/styles/chalk-talk/style.json +14 -0
- package/plugins/ai-video-editor/styles/chalk-talk/style.md +41 -0
- package/plugins/ai-video-editor/styles/clean-tech/base.js +447 -0
- package/plugins/ai-video-editor/styles/clean-tech/style.json +15 -0
- package/plugins/ai-video-editor/styles/clean-tech/style.md +38 -0
- package/plugins/ai-video-editor/styles/creator-motion-graphics/base.js +698 -0
- package/plugins/ai-video-editor/styles/creator-motion-graphics/style.json +16 -0
- package/plugins/ai-video-editor/styles/creator-motion-graphics/style.md +39 -0
- package/plugins/ai-video-editor/styles/data-story/base.js +432 -0
- package/plugins/ai-video-editor/styles/data-story/style.json +14 -0
- package/plugins/ai-video-editor/styles/data-story/style.md +38 -0
- package/plugins/ai-video-editor/styles/index.json +103 -0
- package/plugins/ai-video-editor/styles/pop-info/base.js +570 -0
- package/plugins/ai-video-editor/styles/pop-info/style.json +13 -0
- package/plugins/ai-video-editor/styles/pop-info/style.md +37 -0
- package/plugins/ai-video-editor/styles/software-walkthrough/base.js +544 -0
- package/plugins/ai-video-editor/styles/software-walkthrough/style.json +15 -0
- package/plugins/ai-video-editor/styles/software-walkthrough/style.md +38 -0
- package/plugins/ai-video-editor/styles/warm-canvas/base.js +610 -0
- package/plugins/ai-video-editor/styles/warm-canvas/style.json +14 -0
- package/plugins/ai-video-editor/styles/warm-canvas/style.md +37 -0
- package/plugins/aiinsight-shorts/CHANGELOG.md +6 -0
- package/plugins/aiinsight-shorts/README.md +43 -0
- package/plugins/aiinsight-shorts/SKILL.md +138 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/STYLE.md +58 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/data/cues.json +140 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/data/lines.json +67 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/data/words.json +614 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/data/words.txt +102 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/fonts/Inter-Black.otf +0 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/fonts/Inter-ExtraBold.otf +0 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/index.html +17 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/script.json +27 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/sheet.html +11 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/board.js +62 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/captions.js +68 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/engine.js +65 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/human.js +128 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/lib.js +44 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/look2d.js +33 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/sdf.js +79 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/sets.js +107 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/core/timing.js +23 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/main.js +56 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/sheet.js +79 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/src/shots.js +136 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/tools/capture.mjs +122 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/tools/mix.py +172 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/LICENSE-three.txt +21 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/environments/RoomEnvironment.js +144 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/BokehPass.js +141 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/MaskPass.js +104 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/OutputPass.js +97 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/Pass.js +95 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/RenderPass.js +99 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/BokehShader.js +145 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/CopyShader.js +45 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/addons/shaders/OutputShader.js +85 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/example/vendor/three.module.js +6 -0
- package/plugins/aiinsight-shorts/styles/deep-dive/style-sheet.png +0 -0
- package/plugins/aiinsight-shorts/styles/inside-out/STYLE.md +97 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/data/cues.json +178 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/data/lines.json +73 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/data/words.json +662 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/fonts/Inter-Black.otf +0 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/index.html +17 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/script.json +26 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/captions.js +68 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/kit.js +345 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/lib.js +44 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/src/core/timing.js +23 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/src/main.js +62 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/src/shots.js +195 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/tools/capture.mjs +122 -0
- package/plugins/aiinsight-shorts/styles/inside-out/example/tools/mix.py +172 -0
- package/plugins/aiinsight-shorts/styles/inside-out/style-sheet.png +0 -0
- package/plugins/aiinsight-shorts/styles/night-file/STYLE.md +36 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/data/cues.json +146 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/data/lines.json +73 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/data/words.json +572 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/data/words.txt +95 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/fonts/FreeMonoBold.ttf +0 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/fonts/Inter-Black.otf +0 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/index.html +18 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/script.json +26 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/sheet.html +13 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/board.js +62 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/captions.js +49 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/engine.js +65 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/human.js +128 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/kit.js +151 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/lib.js +44 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/sdf.js +79 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/sets3d.js +106 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/core/timing.js +23 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/main.js +56 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/sheet.js +86 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/src/shots.js +130 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/tools/capture.mjs +122 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/tools/mix.py +172 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/LICENSE-three.txt +21 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/environments/RoomEnvironment.js +144 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/BokehPass.js +141 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/MaskPass.js +104 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/OutputPass.js +97 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/Pass.js +95 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/RenderPass.js +99 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/BokehShader.js +145 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/CopyShader.js +45 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/addons/shaders/OutputShader.js +85 -0
- package/plugins/aiinsight-shorts/styles/night-file/example/vendor/three.module.js +6 -0
- package/plugins/aiinsight-shorts/styles/night-file/style-sheet.png +0 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/STYLE.md +30 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/cues.json +167 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/lines.json +67 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/words.json +614 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/data/words.txt +102 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/fonts/Caladea-Bold.ttf +0 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/fonts/Inter-Black.otf +0 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/index.html +15 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/script.json +26 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/sheet.html +12 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/board.js +62 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/captions.js +47 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/kit.js +152 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/lib.js +44 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/core/timing.js +23 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/main.js +62 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/sheet.js +61 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/src/shots.js +139 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/tools/capture.mjs +122 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/example/tools/mix.py +172 -0
- package/plugins/aiinsight-shorts/styles/paper-atlas/style-sheet.png +0 -0
- package/plugins/aiinsight-shorts/styles/stick-story/STYLE.md +32 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/data/cues.json +182 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/data/lines.json +79 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/data/words.json +662 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/data/words.txt +110 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/fonts/Inter-Black.otf +0 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/fonts/Inter-ExtraBold.otf +0 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/index.html +13 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/script.json +27 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/sheet.html +10 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/board.js +62 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/captions.js +47 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/kit.js +166 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/lib.js +44 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/core/timing.js +23 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/main.js +62 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/sheet.js +64 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/src/shots.js +148 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/tools/capture.mjs +122 -0
- package/plugins/aiinsight-shorts/styles/stick-story/example/tools/mix.py +172 -0
- package/plugins/aiinsight-shorts/styles/stick-story/style-sheet.png +0 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/STYLE.md +51 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/data/cues.json +271 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/data/lines.json +127 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/data/words.json +908 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/data/words.txt +151 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/fonts/Caladea-Bold.ttf +0 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/fonts/Inter-Black.otf +0 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/fonts/Inter-ExtraBold.otf +0 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/index.html +19 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/script.json +37 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/sheet.html +13 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/board.js +62 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/captions.js +56 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/engine.js +65 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/lib.js +44 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/props.js +166 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/timing.js +23 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/toon.js +352 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/core/world.js +340 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/main.js +56 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/sheet.js +99 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/src/shots.js +377 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/tools/capture.mjs +122 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/tools/mix.py +204 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/LICENSE-three.txt +21 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/environments/RoomEnvironment.js +144 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/BokehPass.js +141 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/MaskPass.js +104 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/OutputPass.js +97 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/Pass.js +95 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/RenderPass.js +99 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/BokehShader.js +145 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/CopyShader.js +45 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/addons/shaders/OutputShader.js +85 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/example/vendor/three.module.js +6 -0
- package/plugins/aiinsight-shorts/styles/tall-tale/style-sheet.png +0 -0
- package/plugins/faceless-shorts/README.md +34 -0
- package/plugins/faceless-shorts/SKILL.md +124 -0
- package/plugins/faceless-shorts/styles/deep-dive/STYLE.md +58 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/data/cues.json +140 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/data/lines.json +67 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/data/words.json +614 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/data/words.txt +102 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/fonts/Inter-Black.otf +0 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/fonts/Inter-ExtraBold.otf +0 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/index.html +16 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/script.json +27 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/sheet.html +10 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/board.js +62 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/captions.js +68 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/engine.js +65 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/human.js +128 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/lib.js +44 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/look2d.js +33 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/sdf.js +79 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/sets.js +107 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/core/timing.js +23 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/main.js +56 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/sheet.js +79 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/src/shots.js +136 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/tools/capture.mjs +122 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/tools/mix.py +172 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/LICENSE-three.txt +21 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/environments/RoomEnvironment.js +144 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/BokehPass.js +141 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/MaskPass.js +104 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/OutputPass.js +97 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/Pass.js +95 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/RenderPass.js +99 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/BokehShader.js +145 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/CopyShader.js +45 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/addons/shaders/OutputShader.js +85 -0
- package/plugins/faceless-shorts/styles/deep-dive/example/vendor/three.module.js +6 -0
- package/plugins/faceless-shorts/styles/deep-dive/style-sheet.png +0 -0
- package/plugins/faceless-shorts/styles/inside-out/STYLE.md +97 -0
- package/plugins/faceless-shorts/styles/inside-out/example/data/cues.json +178 -0
- package/plugins/faceless-shorts/styles/inside-out/example/data/lines.json +73 -0
- package/plugins/faceless-shorts/styles/inside-out/example/data/words.json +662 -0
- package/plugins/faceless-shorts/styles/inside-out/example/fonts/Inter-Black.otf +0 -0
- package/plugins/faceless-shorts/styles/inside-out/example/index.html +16 -0
- package/plugins/faceless-shorts/styles/inside-out/example/script.json +26 -0
- package/plugins/faceless-shorts/styles/inside-out/example/src/core/captions.js +68 -0
- package/plugins/faceless-shorts/styles/inside-out/example/src/core/kit.js +345 -0
- package/plugins/faceless-shorts/styles/inside-out/example/src/core/lib.js +44 -0
- package/plugins/faceless-shorts/styles/inside-out/example/src/core/timing.js +23 -0
- package/plugins/faceless-shorts/styles/inside-out/example/src/main.js +62 -0
- package/plugins/faceless-shorts/styles/inside-out/example/src/shots.js +195 -0
- package/plugins/faceless-shorts/styles/inside-out/example/tools/capture.mjs +122 -0
- package/plugins/faceless-shorts/styles/inside-out/example/tools/mix.py +172 -0
- package/plugins/faceless-shorts/styles/inside-out/style-sheet.png +0 -0
- package/plugins/faceless-shorts/styles/night-file/STYLE.md +36 -0
- package/plugins/faceless-shorts/styles/night-file/example/data/cues.json +146 -0
- package/plugins/faceless-shorts/styles/night-file/example/data/lines.json +73 -0
- package/plugins/faceless-shorts/styles/night-file/example/data/words.json +572 -0
- package/plugins/faceless-shorts/styles/night-file/example/data/words.txt +95 -0
- package/plugins/faceless-shorts/styles/night-file/example/fonts/FreeMonoBold.ttf +0 -0
- package/plugins/faceless-shorts/styles/night-file/example/fonts/Inter-Black.otf +0 -0
- package/plugins/faceless-shorts/styles/night-file/example/index.html +16 -0
- package/plugins/faceless-shorts/styles/night-file/example/script.json +26 -0
- package/plugins/faceless-shorts/styles/night-file/example/sheet.html +11 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/board.js +62 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/captions.js +49 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/engine.js +65 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/human.js +128 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/kit.js +151 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/lib.js +44 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/sdf.js +79 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/sets3d.js +106 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/core/timing.js +23 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/main.js +56 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/sheet.js +86 -0
- package/plugins/faceless-shorts/styles/night-file/example/src/shots.js +130 -0
- package/plugins/faceless-shorts/styles/night-file/example/tools/capture.mjs +122 -0
- package/plugins/faceless-shorts/styles/night-file/example/tools/mix.py +172 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/LICENSE-three.txt +21 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/environments/RoomEnvironment.js +144 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/BokehPass.js +141 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/MaskPass.js +104 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/OutputPass.js +97 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/Pass.js +95 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/RenderPass.js +99 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/BokehShader.js +145 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/CopyShader.js +45 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/addons/shaders/OutputShader.js +85 -0
- package/plugins/faceless-shorts/styles/night-file/example/vendor/three.module.js +6 -0
- package/plugins/faceless-shorts/styles/night-file/style-sheet.png +0 -0
- package/plugins/faceless-shorts/styles/paper-atlas/STYLE.md +30 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/data/cues.json +167 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/data/lines.json +67 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/data/words.json +614 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/data/words.txt +102 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/fonts/Caladea-Bold.ttf +0 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/fonts/Inter-Black.otf +0 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/index.html +13 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/script.json +26 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/sheet.html +10 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/board.js +62 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/captions.js +47 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/kit.js +152 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/lib.js +44 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/core/timing.js +23 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/main.js +62 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/sheet.js +61 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/src/shots.js +139 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/tools/capture.mjs +122 -0
- package/plugins/faceless-shorts/styles/paper-atlas/example/tools/mix.py +172 -0
- package/plugins/faceless-shorts/styles/paper-atlas/style-sheet.png +0 -0
- package/plugins/faceless-shorts/styles/stick-story/STYLE.md +32 -0
- package/plugins/faceless-shorts/styles/stick-story/example/data/cues.json +182 -0
- package/plugins/faceless-shorts/styles/stick-story/example/data/lines.json +79 -0
- package/plugins/faceless-shorts/styles/stick-story/example/data/words.json +662 -0
- package/plugins/faceless-shorts/styles/stick-story/example/data/words.txt +110 -0
- package/plugins/faceless-shorts/styles/stick-story/example/fonts/Inter-Black.otf +0 -0
- package/plugins/faceless-shorts/styles/stick-story/example/fonts/Inter-ExtraBold.otf +0 -0
- package/plugins/faceless-shorts/styles/stick-story/example/index.html +12 -0
- package/plugins/faceless-shorts/styles/stick-story/example/script.json +27 -0
- package/plugins/faceless-shorts/styles/stick-story/example/sheet.html +9 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/core/board.js +62 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/core/captions.js +47 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/core/kit.js +166 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/core/lib.js +44 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/core/timing.js +23 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/main.js +62 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/sheet.js +64 -0
- package/plugins/faceless-shorts/styles/stick-story/example/src/shots.js +148 -0
- package/plugins/faceless-shorts/styles/stick-story/example/tools/capture.mjs +122 -0
- package/plugins/faceless-shorts/styles/stick-story/example/tools/mix.py +172 -0
- package/plugins/faceless-shorts/styles/stick-story/style-sheet.png +0 -0
- package/plugins/faceless-shorts/styles/tall-tale/STYLE.md +51 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/data/cues.json +271 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/data/lines.json +127 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/data/words.json +908 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/data/words.txt +151 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/fonts/Caladea-Bold.ttf +0 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/fonts/Inter-Black.otf +0 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/fonts/Inter-ExtraBold.otf +0 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/index.html +17 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/script.json +37 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/sheet.html +11 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/board.js +62 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/captions.js +56 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/engine.js +65 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/lib.js +44 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/props.js +166 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/timing.js +23 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/toon.js +352 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/core/world.js +340 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/main.js +56 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/sheet.js +99 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/src/shots.js +377 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/tools/capture.mjs +122 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/tools/mix.py +204 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/LICENSE-three.txt +21 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/environments/RoomEnvironment.js +144 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/BokehPass.js +141 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/EffectComposer.js +231 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/MaskPass.js +104 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/OutputPass.js +97 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/Pass.js +95 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/RenderPass.js +99 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/ShaderPass.js +77 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/postprocessing/UnrealBloomPass.js +415 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/BokehShader.js +145 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/CopyShader.js +45 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/LuminosityHighPassShader.js +64 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/addons/shaders/OutputShader.js +85 -0
- package/plugins/faceless-shorts/styles/tall-tale/example/vendor/three.module.js +6 -0
- package/plugins/faceless-shorts/styles/tall-tale/style-sheet.png +0 -0
- package/plugins/motion-styles/LIBRARY.md +896 -0
- package/plugins/motion-styles/README.md +29 -0
- package/plugins/motion-styles/SKILL.md +70 -0
- package/plugins/motion-styles/catalog.json +2253 -0
- package/plugins/motion-styles/prompts/bio-glow.md +149 -0
- package/plugins/motion-styles/prompts/blueprint.md +145 -0
- package/plugins/motion-styles/prompts/breaking-desk.md +147 -0
- package/plugins/motion-styles/prompts/callout-kit.md +147 -0
- package/plugins/motion-styles/prompts/chalk-talk.md +153 -0
- package/plugins/motion-styles/prompts/chat-story.md +143 -0
- package/plugins/motion-styles/prompts/clay-diorama.md +149 -0
- package/plugins/motion-styles/prompts/clean-tech.md +147 -0
- package/plugins/motion-styles/prompts/comic-panels.md +145 -0
- package/plugins/motion-styles/prompts/cosmic-scale.md +147 -0
- package/plugins/motion-styles/prompts/creator-motion.md +149 -0
- package/plugins/motion-styles/prompts/data-city.md +149 -0
- package/plugins/motion-styles/prompts/data-story.md +147 -0
- package/plugins/motion-styles/prompts/deep-layers.md +147 -0
- package/plugins/motion-styles/prompts/doc-cinema.md +145 -0
- package/plugins/motion-styles/prompts/evidence-board.md +145 -0
- package/plugins/motion-styles/prompts/exploded-view.md +149 -0
- package/plugins/motion-styles/prompts/glass-icons.md +147 -0
- package/plugins/motion-styles/prompts/glitch-pack.md +145 -0
- package/plugins/motion-styles/prompts/globe-arcs.md +147 -0
- package/plugins/motion-styles/prompts/headline-backdrop.md +145 -0
- package/plugins/motion-styles/prompts/iso-cutaway.md +147 -0
- package/plugins/motion-styles/prompts/isotype.md +145 -0
- package/plugins/motion-styles/prompts/karaoke-subs.md +145 -0
- package/plugins/motion-styles/prompts/low-poly-atlas.md +149 -0
- package/plugins/motion-styles/prompts/lower-thirds.md +147 -0
- package/plugins/motion-styles/prompts/marker-board.md +145 -0
- package/plugins/motion-styles/prompts/market-tape.md +145 -0
- package/plugins/motion-styles/prompts/math-canvas.md +145 -0
- package/plugins/motion-styles/prompts/myth-or-fact.md +145 -0
- package/plugins/motion-styles/prompts/neon-line.md +145 -0
- package/plugins/motion-styles/prompts/paper-craft.md +145 -0
- package/plugins/motion-styles/prompts/parchment-map.md +147 -0
- package/plugins/motion-styles/prompts/physics-toybox.md +147 -0
- package/plugins/motion-styles/prompts/pixel-quest.md +145 -0
- package/plugins/motion-styles/prompts/podcast-clip.md +147 -0
- package/plugins/motion-styles/prompts/pop-info.md +145 -0
- package/plugins/motion-styles/prompts/product-turntable.md +149 -0
- package/plugins/motion-styles/prompts/punch-captions.md +145 -0
- package/plugins/motion-styles/prompts/quiz-countdown.md +145 -0
- package/plugins/motion-styles/prompts/quote-cinema.md +145 -0
- package/plugins/motion-styles/prompts/recipe-steps.md +145 -0
- package/plugins/motion-styles/prompts/rubber-hose-reel.md +145 -0
- package/plugins/motion-styles/prompts/shadow-puppets.md +145 -0
- package/plugins/motion-styles/prompts/size-lineup.md +149 -0
- package/plugins/motion-styles/prompts/software-walkthrough.md +147 -0
- package/plugins/motion-styles/prompts/stack-split.md +145 -0
- package/plugins/motion-styles/prompts/sticker-pop.md +145 -0
- package/plugins/motion-styles/prompts/storybook.md +145 -0
- package/plugins/motion-styles/prompts/swiss-grid.md +145 -0
- package/plugins/motion-styles/prompts/synth-grid.md +147 -0
- package/plugins/motion-styles/prompts/tactics-board.md +145 -0
- package/plugins/motion-styles/prompts/terminal.md +145 -0
- package/plugins/motion-styles/prompts/tier-list.md +143 -0
- package/plugins/motion-styles/prompts/timeline-rail.md +145 -0
- package/plugins/motion-styles/prompts/top-5-countdown.md +145 -0
- package/plugins/motion-styles/prompts/versus-split.md +145 -0
- package/plugins/motion-styles/prompts/vhs-camcorder.md +145 -0
- package/plugins/motion-styles/prompts/visual-novel.md +145 -0
- package/plugins/motion-styles/prompts/warm-canvas.md +145 -0
- package/plugins/motion-styles/prompts/woodcut-tale.md +145 -0
- package/plugins/motion-styles/prompts/zine-collage.md +145 -0
- package/plugins/motion-styles/sources/bio-glow.html +639 -0
- package/plugins/motion-styles/sources/blueprint.html +617 -0
- package/plugins/motion-styles/sources/breaking-desk.html +585 -0
- package/plugins/motion-styles/sources/callout-kit.html +586 -0
- package/plugins/motion-styles/sources/chalk-talk.html +597 -0
- package/plugins/motion-styles/sources/chat-story.html +597 -0
- package/plugins/motion-styles/sources/clay-diorama.html +681 -0
- package/plugins/motion-styles/sources/clean-tech.html +554 -0
- package/plugins/motion-styles/sources/comic-panels.html +608 -0
- package/plugins/motion-styles/sources/cosmic-scale.html +628 -0
- package/plugins/motion-styles/sources/creator-motion.html +805 -0
- package/plugins/motion-styles/sources/data-city.html +613 -0
- package/plugins/motion-styles/sources/data-story.html +539 -0
- package/plugins/motion-styles/sources/deep-layers.html +624 -0
- package/plugins/motion-styles/sources/doc-cinema.html +590 -0
- package/plugins/motion-styles/sources/evidence-board.html +610 -0
- package/plugins/motion-styles/sources/exploded-view.html +618 -0
- package/plugins/motion-styles/sources/glass-icons.html +612 -0
- package/plugins/motion-styles/sources/glitch-pack.html +583 -0
- package/plugins/motion-styles/sources/globe-arcs.html +621 -0
- package/plugins/motion-styles/sources/headline-backdrop.html +584 -0
- package/plugins/motion-styles/sources/iso-cutaway.html +621 -0
- package/plugins/motion-styles/sources/isotype.html +588 -0
- package/plugins/motion-styles/sources/karaoke-subs.html +577 -0
- package/plugins/motion-styles/sources/low-poly-atlas.html +621 -0
- package/plugins/motion-styles/sources/lower-thirds.html +582 -0
- package/plugins/motion-styles/sources/marker-board.html +598 -0
- package/plugins/motion-styles/sources/market-tape.html +598 -0
- package/plugins/motion-styles/sources/math-canvas.html +592 -0
- package/plugins/motion-styles/sources/myth-or-fact.html +587 -0
- package/plugins/motion-styles/sources/neon-line.html +597 -0
- package/plugins/motion-styles/sources/paper-craft.html +612 -0
- package/plugins/motion-styles/sources/parchment-map.html +624 -0
- package/plugins/motion-styles/sources/physics-toybox.html +617 -0
- package/plugins/motion-styles/sources/pixel-quest.html +609 -0
- package/plugins/motion-styles/sources/podcast-clip.html +585 -0
- package/plugins/motion-styles/sources/pop-info.html +677 -0
- package/plugins/motion-styles/sources/product-turntable.html +611 -0
- package/plugins/motion-styles/sources/punch-captions.html +583 -0
- package/plugins/motion-styles/sources/quiz-countdown.html +593 -0
- package/plugins/motion-styles/sources/quote-cinema.html +581 -0
- package/plugins/motion-styles/sources/recipe-steps.html +599 -0
- package/plugins/motion-styles/sources/rubber-hose-reel.html +627 -0
- package/plugins/motion-styles/sources/shadow-puppets.html +609 -0
- package/plugins/motion-styles/sources/size-lineup.html +620 -0
- package/plugins/motion-styles/sources/software-walkthrough.html +651 -0
- package/plugins/motion-styles/sources/stack-split.html +588 -0
- package/plugins/motion-styles/sources/sticker-pop.html +587 -0
- package/plugins/motion-styles/sources/storybook.html +600 -0
- package/plugins/motion-styles/sources/swiss-grid.html +590 -0
- package/plugins/motion-styles/sources/synth-grid.html +614 -0
- package/plugins/motion-styles/sources/tactics-board.html +608 -0
- package/plugins/motion-styles/sources/terminal.html +593 -0
- package/plugins/motion-styles/sources/tier-list.html +600 -0
- package/plugins/motion-styles/sources/timeline-rail.html +598 -0
- package/plugins/motion-styles/sources/top-5-countdown.html +589 -0
- package/plugins/motion-styles/sources/versus-split.html +592 -0
- package/plugins/motion-styles/sources/vhs-camcorder.html +587 -0
- package/plugins/motion-styles/sources/visual-novel.html +623 -0
- package/plugins/motion-styles/sources/warm-canvas.html +742 -0
- package/plugins/motion-styles/sources/woodcut-tale.html +598 -0
- package/plugins/motion-styles/sources/zine-collage.html +594 -0
- package/plugins/video-pipeline/.claude-plugin/plugin.json +2 -2
- package/plugins/video-pipeline/skills/.upstream-skills.json +156 -143
- package/plugins/video-pipeline/skills/video-pipeline/references/mcp-tools.md +3 -3
- package/scripts/deep-validate.js +3 -2
- package/src/audio-mixer/mixer.js +69 -0
- package/src/cli/make.js +19 -0
- package/src/harness/lib/browser.mjs +22 -1
- package/src/harness/lib/capture.mjs +33 -11
- package/src/harness/lib/jobs.mjs +16 -1
- package/src/mcp-server/server.js +726 -10
- package/src/pipeline/providers.js +77 -17
- package/src/skills/sync-upstream.js +15 -3
- package/src/utils/media-downloader.js +7 -0
- package/src/utils/tool-installer.js +212 -0
- package/src/utils/transcribe.js +9 -1
- package/src/video-renderer/renderer.js +68 -38
- package/src/video-renderer/scene-animator.js +50 -15
- package/src/workflows/assets.js +49 -5
- package/src/workflows/render.js +2 -0
- 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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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 (/[\
|
|
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 (/[\
|
|
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
|
|
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 —
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
+
};
|
package/src/utils/transcribe.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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})
|
|
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 (
|
|
313
|
-
const
|
|
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
|
|
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 = [
|
|
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
|
|
428
|
-
showAnchor
|
|
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',
|
|
447
|
-
'--out',
|
|
448
|
-
'--fps',
|
|
449
|
-
'--first',
|
|
450
|
-
'--last',
|
|
451
|
-
'--workers', '
|
|
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
|
-
|
|
473
|
-
|
|
474
|
-
'
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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
|
}
|