@amg555/frameforge-mcp 2.3.3 → 2.3.5

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 (64) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +3 -2
  3. package/out/frames/f000000.jpg +0 -0
  4. package/out/frames/f000001.jpg +0 -0
  5. package/out/frames/f000002.jpg +0 -0
  6. package/out/frames/f000003.jpg +0 -0
  7. package/out/frames/f000004.jpg +0 -0
  8. package/out/frames/f000005.jpg +0 -0
  9. package/out/frames/f000006.jpg +0 -0
  10. package/out/frames/f000007.jpg +0 -0
  11. package/out/frames/f000008.jpg +0 -0
  12. package/out/frames/f000009.jpg +0 -0
  13. package/out/frames/f000010.jpg +0 -0
  14. package/out/frames/f000011.jpg +0 -0
  15. package/out/frames/f000012.jpg +0 -0
  16. package/out/frames/f000013.jpg +0 -0
  17. package/out/frames/f000014.jpg +0 -0
  18. package/out/frames/f000015.jpg +0 -0
  19. package/out/frames/f000016.jpg +0 -0
  20. package/out/frames/f000017.jpg +0 -0
  21. package/out/frames/f000018.jpg +0 -0
  22. package/out/frames/f000019.jpg +0 -0
  23. package/out/frames/f000020.jpg +0 -0
  24. package/out/frames/f000021.jpg +0 -0
  25. package/out/frames/f000022.jpg +0 -0
  26. package/out/frames/f000023.jpg +0 -0
  27. package/out/frames/f000024.jpg +0 -0
  28. package/out/frames/f000025.jpg +0 -0
  29. package/out/frames/f000026.jpg +0 -0
  30. package/out/frames/f000027.jpg +0 -0
  31. package/out/frames/f000028.jpg +0 -0
  32. package/out/frames/f000029.jpg +0 -0
  33. package/out/frames/f000030.jpg +0 -0
  34. package/out/frames/f000031.jpg +0 -0
  35. package/out/frames/f000032.jpg +0 -0
  36. package/out/frames/f000033.jpg +0 -0
  37. package/out/frames/f000034.jpg +0 -0
  38. package/out/frames/f000035.jpg +0 -0
  39. package/out/frames/f000036.jpg +0 -0
  40. package/out/frames/f000037.jpg +0 -0
  41. package/out/frames/f000038.jpg +0 -0
  42. package/out/frames/f000039.jpg +0 -0
  43. package/out/frames/f000040.jpg +0 -0
  44. package/out/frames/f000041.jpg +0 -0
  45. package/out/frames/f000042.jpg +0 -0
  46. package/out/frames/f000043.jpg +0 -0
  47. package/out/frames/f000044.jpg +0 -0
  48. package/out/frames/f000045.jpg +0 -0
  49. package/out/frames/f000046.jpg +0 -0
  50. package/out/frames/f000047.jpg +0 -0
  51. package/package.json +2 -2
  52. package/plugins/video-pipeline/skills/video-pipeline/SKILL.md +1 -1
  53. package/plugins/video-pipeline/skills/video-pipeline/assets/project/reel/engine.css +2 -2
  54. package/plugins/video-pipeline/skills/video-pipeline/assets/project/reel/engine.js +1 -1
  55. package/plugins/video-pipeline/skills/video-pipeline/references/providers.md +11 -0
  56. package/scripts/deep-validate.js +2 -2
  57. package/scripts/html-renderer/new-project.mjs +2 -2
  58. package/src/cli/doctor.js +12 -5
  59. package/src/harness/bin/harness.mjs +20 -7
  60. package/src/mcp-server/server.js +1 -1
  61. package/src/video-renderer/renderer.js +222 -60
  62. package/src/video-renderer/scene-animator.js +459 -0
  63. package/src/workflows/assets.js +4 -0
  64. package/src/workflows/render.js +12 -7
package/CHANGELOG.md CHANGED
@@ -4,6 +4,50 @@ All notable changes to FrameForge are documented here.
4
4
 
5
5
  ---
6
6
 
7
+ ## [2.3.5] — 2026-11-09
8
+
9
+ ### Added
10
+ - **Integrated Code-Driven Scene Animator** (`src/video-renderer/scene-animator.js`):
11
+ - Dynamic 24fps HTML5/Canvas animation generator adhering to pure-function-of-time contract `seek(t)`
12
+ - Contextual motion graphic themes: Code IDE/terminal typing, Data charts & counters, Network node graphs, Flow diagrams, and floating Ken-Burns image cards
13
+ - Dynamic gradient backgrounds with ambient particle systems and perspective motion grids
14
+ - High-performance Chromium harness rendering + direct FFmpeg BT.709 H.264 VUI muxing
15
+ - **Full Multilingual & Malayalam Font Support**:
16
+ - Direct font resolver for Malayalam & Indic scripts (`Nirmala.ttc`, `Noto Sans Malayalam`, `Malayalam Sangam MN`, `Kartika`, `Meera`, `Manjari`)
17
+ - FFmpeg `text_shaping=1` HarfBuzz layout integration preserving complex conjuncts, chillu letters, and viramas
18
+ - Unicode-safe slicing and UTF-8 handling in caption and narration filters
19
+ - Updated `engine.css`, `engine.js`, and `new-project.mjs` typography stacks for seamless multilingual rendering
20
+
21
+ ### Fixed
22
+ - Replaced static solid-color slideshow fallback in `renderer.js` with live code-driven animation engine
23
+ - Fixed `--flag value` space-separated argument parsing in `harness.mjs` CLI
24
+ - Fixed `--out` directory path resolution in `cmdFrames` frame exporter
25
+
26
+ ---
27
+
28
+ ## [2.3.4] — 2026-11-09
29
+
30
+ ### Added
31
+ - **Full Code-Driven Video Production Harness** (`src/harness/`, `bin/harness.mjs`, `npx frameforge-harness`):
32
+ - H1 Browser resolution & GPU auto-selection (Direct3D11 / Metal / ANGLE)
33
+ - H2 Deterministic frame stepper & virtual clock injection
34
+ - H3 Resumable atomic frame worker pool (`.tmp` + `renameSync`, <1000B corruption checks)
35
+ - H4 Visual review generators: contact sheets, motion strips, 9:16 mobile crop previews
36
+ - H5 3-point history-leak & frame purity verification gate ($a === b \land a === c$) with `frames_sha256` digest
37
+ - H6 Pixel luminance and blind-spot frame math (blank, blown, corner-confined detection)
38
+ - H7 Determinism primitives in `engine.js` (`boilSeed`, `kf`, `onTwos`, `seg`, `pulse`, `shots`)
39
+ - H8 Broadcast-grade BT.709 color encoding & x264 VUI parameter tags
40
+ - H9 Unified CLI commands (`doctor`, `storyboard`, `verify`, `sheet`, `strip`, `crop`, `pixels`, `frames`, `encode`, `all`)
41
+ - **MCP `render_animation` parity**: added `verify`, `doctor`, `pixels` modes and structured `purityReport` return object.
42
+ - **VoxForge**: added `VOXFORGE_URL` detection to system doctor and documented in all provider tables.
43
+
44
+ ### Fixed
45
+ - Fixed relative module imports in scaffolded projects (`./browser.mjs`, etc.).
46
+ - Enforced BT.709 color tags across all procedural scene fallbacks in `renderer.js`.
47
+ - Included `plugins/` skill templates and assets in npm package distribution.
48
+
49
+ ---
50
+
7
51
  ## [2.3.2] — 2026-11-06
8
52
 
9
53
  ### Added
package/README.md CHANGED
@@ -9,9 +9,9 @@
9
9
  [![npm](https://img.shields.io/npm/v/@amg555/frameforge-mcp.svg?label=npm)](https://www.npmjs.com/package/@amg555/frameforge-mcp)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
11
11
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
12
- [![Version](https://img.shields.io/badge/version-2.3.3-blue.svg)](CHANGELOG.md)
12
+ [![Version](https://img.shields.io/badge/version-2.3.5-blue.svg)](CHANGELOG.md)
13
13
  [![MCP Spec](https://img.shields.io/badge/MCP-2024--11--05-blue.svg)](https://modelcontextprotocol.io/)
14
- [![Tests](https://img.shields.io/badge/tests-512%20passing-brightgreen.svg)](#testing)
14
+ [![Tests](https://img.shields.io/badge/tests-539%20passing-brightgreen.svg)](#testing)
15
15
 
16
16
  </div>
17
17
 
@@ -219,6 +219,7 @@ Switch any provider with one `.env` change — no code changes.
219
219
  | Provider | Free? | Key needed |
220
220
  |----------|-------|------------|
221
221
  | `edge-tts` | ✅ free, offline | none — **default** |
222
+ | `voxforge` | ✅ free, local/private | none — `VOXFORGE_URL` ([VoxForge](https://github.com/AMG555/VoxForge)) |
222
223
  | `elevenlabs` | paid | `ELEVENLABS_API_KEY` |
223
224
  | `azure` | paid | `AZURE_SPEECH_KEY` + `AZURE_SPEECH_REGION` |
224
225
  | `openai` | paid | `OPENAI_API_KEY` |
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amg555/frameforge-mcp",
3
- "version": "2.3.3",
3
+ "version": "2.3.5",
4
4
  "description": "FrameForge — AI video production engine for agentic IDEs. npx @amg555/frameforge-mcp. FFmpeg + TTS run on your machine. 17 MCP tools.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -30,7 +30,7 @@
30
30
  "start:local-render": "cross-env RENDER_MODE=full WORKER_PORT=3211 node src/worker/server-render-free.js",
31
31
  "db:migrate": "node scripts/db-migrate.js",
32
32
  "validate": "node scripts/deep-validate.js",
33
- "test": "node --test src/pipeline/retry-policy.test.js src/pipeline/telemetry.test.js src/pipeline/artifact-manifest.test.js src/pipeline/artifact-retention.test.js src/pipeline/external-adapter.test.js src/workflows/publishing.test.js src/workflows/script.test.js src/animation/animation-system.test.js src/fact-checker/review-gate.test.js src/fact-checker/checker.test.js src/utils/log-redaction.test.js src/worker/server-render-free.test.js src/worker/server.test.js src/mcp-server/server.test.js src/quality-gate/gate.test.js src/shorts-extractor/extractor.test.js src/audio-mixer/mixer.test.js src/video-renderer/renderer.test.js plugins/video-pipeline/skills/video-pipeline/assets/project/reel/engine.test.js src/harness/lib/pixels.test.js src/harness/lib/verify-purity.test.js src/harness/harness.test.js src/integration.test.js",
33
+ "test": "node --test src/pipeline/retry-policy.test.js src/pipeline/telemetry.test.js src/pipeline/artifact-manifest.test.js src/pipeline/artifact-retention.test.js src/pipeline/external-adapter.test.js src/workflows/publishing.test.js src/workflows/script.test.js src/animation/animation-system.test.js src/fact-checker/review-gate.test.js src/fact-checker/checker.test.js src/utils/log-redaction.test.js src/worker/server-render-free.test.js src/worker/server.test.js src/mcp-server/server.test.js src/quality-gate/gate.test.js src/shorts-extractor/extractor.test.js src/audio-mixer/mixer.test.js src/video-renderer/scene-animator.test.js src/video-renderer/renderer.test.js plugins/video-pipeline/skills/video-pipeline/assets/project/reel/engine.test.js src/harness/lib/pixels.test.js src/harness/lib/verify-purity.test.js src/harness/harness.test.js src/integration.test.js",
34
34
  "lint": "echo 'No linter configured — add eslint for production'",
35
35
  "check-credentials": "node src/utils/log-redaction.js",
36
36
  "generate-assets": "node scripts/generate-initial-assets.js",
@@ -41,7 +41,7 @@ IDE Agent (IBM Bob / Codex / opencode / Cursor / Windsurf / Claude Code)
41
41
  │ LLM provider: PROVIDER_LLM=groq|openrouter|anthropic|gemini
42
42
  │ |mistral|together|cerebras|openai
43
43
  │ |ollama|webhook
44
- │ TTS provider: PROVIDER_TTS=edge-tts|elevenlabs|azure|openai|webhook
44
+ │ TTS provider: PROVIDER_TTS=edge-tts|voxforge|elevenlabs|azure|openai|webhook
45
45
  │ Visuals: Code-driven animations (default) + user media (video_path / image_path)
46
46
  │
47
47
  ▼ Optional: queue_full_pipeline
@@ -21,9 +21,9 @@
21
21
  --danger: #ef4444;
22
22
 
23
23
  /* Typography scale */
24
- --font-body: -apple-system, "Segoe UI", system-ui, sans-serif;
24
+ --font-body: -apple-system, "Segoe UI", "Nirmala UI", "Noto Sans Malayalam", "Malayalam Sangam MN", "Kartika", "Meera", "Manjari", system-ui, sans-serif;
25
25
  --font-mono: "Fira Code", "Cascadia Code", "Consolas", monospace;
26
- --font-display: "Archivo", "Segoe UI", system-ui, sans-serif;
26
+ --font-display: "Archivo", "Nirmala UI", "Noto Sans Malayalam", "Malayalam Sangam MN", "Kartika", "Meera", "Manjari", -apple-system, "Segoe UI", system-ui, sans-serif;
27
27
 
28
28
  /* Spacing */
29
29
  --gap-sm: 8px;
@@ -331,7 +331,7 @@ export function shots(shotList = []) {
331
331
  * @param {{ font, color, x, y, size, weight, align, opacity, duration }} opts
332
332
  */
333
333
  export function text(str, {
334
- font = '48px/1.3 system-ui',
334
+ font = '48px/1.3 "Nirmala UI", "Noto Sans Malayalam", "Malayalam Sangam MN", "Kartika", system-ui, sans-serif',
335
335
  color = '#ffffff',
336
336
  x = 'center',
337
337
  y = 100,
@@ -52,6 +52,17 @@ PROVIDER_TTS=edge-tts
52
52
  # Voice list: edge-tts --list-voices
53
53
  ```
54
54
 
55
+ ### voxforge (free, private multi-engine neural TTS & voice cloning in Rust)
56
+ ```bash
57
+ PROVIDER_TTS=voxforge
58
+ VOXFORGE_URL=http://localhost:5005 # or your self-hosted VoxForge workstation URL
59
+ # Optional:
60
+ VOXFORGE_KEY=... # optional auth token if enabled
61
+ VOXFORGE_VOICE=default # voice/clone reference
62
+ VOXFORGE_MODEL=voxforge-v1 # engine model (XTTS, Piper, Kokoro, Whisper)
63
+ ```
64
+ Repo: [AMG555/VoxForge](https://github.com/AMG555/VoxForge) — local, private neural TTS & voice cloning workstation.
65
+
55
66
  ### elevenlabs (voice cloning)
56
67
  ```bash
57
68
  PROVIDER_TTS=elevenlabs
@@ -20,7 +20,7 @@ check('batch handling', code.includes('Array.isArray(body)'));
20
20
  check('ping handler', code.includes("method === 'ping'"));
21
21
  check('notifications/init', code.includes("notifications/initialized"));
22
22
  check('body size limit', code.includes('MAX_BODY_BYTES'));
23
- check('SERVER_INFO version 2.3.3', code.includes("version: '2.3.3'"));
23
+ check('SERVER_INFO version 2.3.5', code.includes("version: '2.3.5'"));
24
24
  check('18 tools defined (incl get_job_status)', code.includes('get_job_status'));
25
25
  check('export_to_editor tool defined', code.includes('export_to_editor'));
26
26
  check('voxforge TTS provider', code.includes('voxforge'));
@@ -293,7 +293,7 @@ check('cf-worker has checkRateLimit', cfWorker.includes('checkRateLimit'));
293
293
  check('cf-worker hashes token (SHA-256)', cfWorker.includes('SHA-256'));
294
294
  check('cf-worker uses RATE_LIMITS KV', cfWorker.includes('env.RATE_LIMITS'));
295
295
  check('cf-worker returns 429 on limit', cfWorker.includes('429'));
296
- check('cf-worker version 2.3.3', cfWorker.includes("'2.3.3'"));
296
+ check('cf-worker version 2.3.5', cfWorker.includes("'2.3.5'"));
297
297
  check('wrangler.toml has kv_namespaces',fs.readFileSync('./cloudflare-mcp/wrangler.toml','utf8').includes('kv_namespaces'));
298
298
 
299
299
  // ── plugins/skills present ────────────────────────────────────────────────
@@ -97,7 +97,7 @@ const indexHtml = `<!DOCTYPE html>
97
97
  <!-- Preload primary typeface — must resolve before frame 0 (fonts.ready gate) -->
98
98
  <link rel="preconnect" href="https://fonts.googleapis.com">
99
99
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
100
- <link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
100
+ <link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,100..900;1,100..900&family=Noto+Sans+Malayalam:wght@400;600;700;800;900&display=swap" rel="stylesheet">
101
101
  <link rel="stylesheet" href="reel/engine.css">
102
102
  <style>
103
103
  /* Project-level overrides — edit here */
@@ -105,7 +105,7 @@ const indexHtml = `<!DOCTYPE html>
105
105
  --primary: #ffffff;
106
106
  --accent: #3b82f6;
107
107
  --bg: #0d1117;
108
- --font: 'Archivo', system-ui, sans-serif;
108
+ --font: 'Archivo', 'Nirmala UI', 'Noto Sans Malayalam', 'Malayalam Sangam MN', 'Kartika', system-ui, sans-serif;
109
109
  }
110
110
  </style>
111
111
  </head>
package/src/cli/doctor.js CHANGED
@@ -73,19 +73,26 @@ if (ffprobe.status === 0) {
73
73
  hasCriticalFailure = true;
74
74
  }
75
75
 
76
- // 4. Voice Engine (edge-tts or Cloud API)
76
+ // 4. Voice Engine (edge-tts, VoxForge, or Cloud API)
77
77
  const edgeTts = spawnSync('edge-tts', ['--version'], { encoding: 'utf8', timeout: 5000, shell: process.platform === 'win32' });
78
- const hasCloudTts = Boolean(process.env.ELEVENLABS_API_KEY || process.env.AZURE_SPEECH_KEY || process.env.OPENAI_API_KEY || process.env.CUSTOM_TTS_URL);
78
+ const hasCloudTts = Boolean(
79
+ process.env.ELEVENLABS_API_KEY ||
80
+ process.env.AZURE_SPEECH_KEY ||
81
+ process.env.OPENAI_API_KEY ||
82
+ process.env.CUSTOM_TTS_URL ||
83
+ process.env.WEBHOOK_TTS_URL ||
84
+ process.env.VOXFORGE_URL
85
+ );
79
86
 
80
87
  if (edgeTts.status === 0) {
81
88
  pass('Voice Engine', `edge-tts CLI available (${(edgeTts.stdout || '').trim()})`);
82
89
  } else if (hasCloudTts) {
83
- pass('Voice Engine', 'Cloud TTS API configured via environment');
90
+ pass('Voice Engine', 'TTS provider (VoxForge or Cloud API) configured via environment');
84
91
  } else {
85
92
  warn(
86
93
  'Voice Engine',
87
- 'Neither edge-tts CLI nor cloud TTS API detected',
88
- 'Run "pip install edge-tts" for free offline voiceover, or set OPENAI_API_KEY / ELEVENLABS_API_KEY in .env'
94
+ 'Neither edge-tts CLI nor configured TTS provider detected',
95
+ 'Run "pip install edge-tts" for free offline voiceover, set VOXFORGE_URL (VoxForge), or set OPENAI_API_KEY / ELEVENLABS_API_KEY in .env'
89
96
  );
90
97
  }
91
98
 
@@ -39,8 +39,19 @@ const extras = [];
39
39
  for (let i = 1; i < argv.length; i++) {
40
40
  const arg = argv[i];
41
41
  if (arg.startsWith('--')) {
42
- const [k, v] = arg.slice(2).split('=');
43
- flags[k] = v ?? true;
42
+ const eqIdx = arg.indexOf('=');
43
+ if (eqIdx !== -1) {
44
+ const k = arg.slice(2, eqIdx);
45
+ const v = arg.slice(eqIdx + 1);
46
+ flags[k] = v;
47
+ } else {
48
+ const k = arg.slice(2);
49
+ if (i + 1 < argv.length && !argv[i + 1].startsWith('--')) {
50
+ flags[k] = argv[++i];
51
+ } else {
52
+ flags[k] = true;
53
+ }
54
+ }
44
55
  } else {
45
56
  extras.push(arg);
46
57
  }
@@ -56,7 +67,7 @@ function resolveProjectFile(filename, fallback) {
56
67
  const HTML_FILE = flags.html ? path.resolve(CWD, flags.html) : resolveProjectFile('index.html', resolveProjectFile('studio.html'));
57
68
  const OUT_DIR = flags.outDir ? path.resolve(CWD, flags.outDir) : path.join(CWD, 'out');
58
69
  const CHECK_DIR = path.join(OUT_DIR, 'check');
59
- const FRAMES_DIR = path.join(OUT_DIR, 'frames');
70
+ const FRAMES_DIR = flags.frames ? path.resolve(CWD, flags.frames) : flags.out ? path.resolve(CWD, flags.out) : path.join(OUT_DIR, 'frames');
60
71
  const PURITY_LOG = path.join(CHECK_DIR, 'purity_report.json');
61
72
 
62
73
  fs.mkdirSync(OUT_DIR, { recursive: true });
@@ -214,17 +225,19 @@ async function cmdFrames() {
214
225
  const fps = parseInt(flags.fps || '30', 10);
215
226
  const workers = parseInt(flags.workers || '4', 10);
216
227
  const duration = flags.duration ? parseFloat(flags.duration) : 2.0;
217
- const totalFrames = Math.round(duration * fps);
228
+ const first = flags.first !== undefined ? parseInt(flags.first, 10) : 0;
229
+ const last = flags.last !== undefined ? parseInt(flags.last, 10) : (Math.round(duration * fps) - 1);
230
+ const totalFrames = last - first + 1;
218
231
 
219
- console.log(`📦 Rendering Frame Range [0..${totalFrames - 1}] (${duration}s @ ${fps}fps, workers=${workers})`);
232
+ console.log(`📦 Rendering Frame Range [${first}..${last}] (${totalFrames} frames @ ${fps}fps, workers=${workers})`);
220
233
  const { browser } = await launchHarnessBrowser();
221
234
 
222
235
  const res = await renderFrameJobs({
223
236
  browser,
224
237
  htmlPath: HTML_FILE,
225
238
  framesDir: FRAMES_DIR,
226
- first: 0,
227
- last: totalFrames - 1,
239
+ first,
240
+ last,
228
241
  fps,
229
242
  workers,
230
243
  width: parseInt(flags.width || '1920', 10),
@@ -1372,7 +1372,7 @@ Operations (used with action="edit"):
1372
1372
 
1373
1373
  const SERVER_INFO = {
1374
1374
  name: 'video-pipeline',
1375
- version: '2.3.3',
1375
+ version: '2.3.5',
1376
1376
  };
1377
1377
 
1378
1378
  const CAPABILITIES = {