@amg555/frameforge-mcp 0.0.0-stage → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bob/artifacts/enterprise-ai-video-agent-platform-agnostic-implementation-guide.html +464 -0
- package/.claude-plugin/marketplace.json +17 -0
- package/.gitattributes +19 -0
- package/.mcp.json +45 -0
- package/CHANGELOG.md +431 -0
- package/CLAUDE.md +278 -0
- package/CONTRIBUTING.md +112 -0
- package/LICENSE +21 -0
- package/Procfile +1 -0
- package/README.md +359 -2
- package/SECURITY.md +71 -0
- package/START_HERE.md +144 -0
- package/assets/metadata/assets.json +5 -0
- package/assets/metadata/embeddings.json +5 -0
- package/install.sh +64 -0
- package/package.json +58 -4
- package/src/animation/animation-system.js +229 -0
- package/src/asset-library/README.md +188 -0
- package/src/asset-library/asset-library.js +639 -0
- package/src/audio-mixer/mixer.js +187 -0
- package/src/cli/doctor.js +173 -0
- package/src/cli/make.js +655 -0
- package/src/cli/setup-keys.js +378 -0
- package/src/config/load-config.js +72 -0
- package/src/fact-checker/checker.js +384 -0
- package/src/fact-checker/review-gate.js +306 -0
- package/src/fact-checker/validation-set.js +1078 -0
- package/src/mcp-server/server.js +1299 -0
- package/src/mcp-server/stdio.js +87 -0
- package/src/pipeline/artifact-manifest.js +323 -0
- package/src/pipeline/artifact-retention.js +189 -0
- package/src/pipeline/external-adapter.js +366 -0
- package/src/pipeline/providers.js +853 -0
- package/src/pipeline/retry-policy.js +134 -0
- package/src/pipeline/state-machine.js +297 -0
- package/src/pipeline/telemetry.js +162 -0
- package/src/quality-gate/gate.js +229 -0
- package/src/schema/scene.schema.json +101 -0
- package/src/shorts-extractor/extractor.js +343 -0
- package/src/utils/log-redaction.js +274 -0
- package/src/video-renderer/renderer.js +364 -0
- package/src/worker/server-render-free.js +420 -0
- package/src/worker/server.js +328 -0
- package/src/workflows/assets.js +131 -0
- package/src/workflows/ingest.js +299 -0
- package/src/workflows/packaging.js +156 -0
- package/src/workflows/publishing.js +206 -0
- package/src/workflows/render.js +102 -0
- package/src/workflows/research.js +151 -0
- package/src/workflows/script.js +210 -0
- package/src/workflows/shorts.js +113 -0
package/README.md
CHANGED
|
@@ -1,3 +1,360 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# ⚡ FrameForge
|
|
4
|
+
|
|
5
|
+
### AI Video Production Engine for Any Agentic IDE
|
|
6
|
+
|
|
7
|
+
**Any IDE. Any topic. Any style. 1080p videos from a single prompt.**
|
|
8
|
+
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://nodejs.org/)
|
|
11
|
+
[](CHANGELOG.md)
|
|
12
|
+
[](https://modelcontextprotocol.io/)
|
|
13
|
+
[](#testing)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
FrameForge is an MCP server your IDE agent calls to make videos. You (or your agent) write the scenes — FrameForge handles voice, images, FFmpeg compositing, and quality checking. Works in Bob, Cursor, Windsurf, Codex, opencode, Claude Code, and any MCP-capable IDE.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Zero-install quickstart (npx)
|
|
24
|
+
|
|
25
|
+
No cloning. No `npm install`. FFmpeg and edge-tts run on your own machine.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# 1. Install prerequisites (one-time, system-level)
|
|
29
|
+
# FFmpeg: https://ffmpeg.org/download.html → add bin/ to PATH
|
|
30
|
+
# edge-tts: pip install edge-tts
|
|
31
|
+
|
|
32
|
+
# 2. Configure your API keys (one-time, saved to ~/.frameforge/config.json)
|
|
33
|
+
npx --package=@amg555/frameforge-mcp frameforge-setup
|
|
34
|
+
|
|
35
|
+
# 3. Check everything is ready
|
|
36
|
+
npx --package=@amg555/frameforge-mcp frameforge-doctor
|
|
37
|
+
|
|
38
|
+
# 4. Add to your IDE — then ask your agent to make a video
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Add to your IDE's MCP config (works in Bob, Cursor, Windsurf, Codex, Claude Code, opencode):
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"mcpServers": {
|
|
46
|
+
"frameforge": {
|
|
47
|
+
"command": "npx",
|
|
48
|
+
"args": ["--package=@amg555/frameforge-mcp", "-y", "frameforge-mcp"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That's it. Your agent now has 17 video production tools. FFmpeg and TTS run on your machine — no cloud render costs.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Other connection methods
|
|
59
|
+
|
|
60
|
+
### Cloned repo (contributors / local dev)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git clone https://github.com/AMG555/FrameForge.git && cd FrameForge && npm run doctor && npm run setup
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"frameforge": {
|
|
70
|
+
"command": "node",
|
|
71
|
+
"args": ["/absolute/path/to/FrameForge/src/mcp-server/stdio.js"]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Remote URL (Cloudflare Workers — FFmpeg must run separately)
|
|
78
|
+
|
|
79
|
+
Deploy once to Cloudflare (free):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cd cloudflare-mcp && npm install
|
|
83
|
+
wrangler secret put WORKER_API_URL # your FrameForge backend URL
|
|
84
|
+
wrangler secret put MCP_AUTH_TOKEN # any random 32-char string
|
|
85
|
+
wrangler deploy
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"frameforge": {
|
|
92
|
+
"url": "https://video-mcp.YOUR_SUBDOMAIN.workers.dev/mcp",
|
|
93
|
+
"headers": { "Authorization": "Bearer YOUR_MCP_AUTH_TOKEN" }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Make your first video
|
|
102
|
+
|
|
103
|
+
**New to FrameForge?** Read [`START_HERE.md`](START_HERE.md) — it's a single file you paste into any IDE chat that starts a guided conversation: the agent asks what you want to make, produces a beat sheet for your approval, then drives the full pipeline.
|
|
104
|
+
|
|
105
|
+
Once connected, tell your IDE:
|
|
106
|
+
|
|
107
|
+
> *"Make a 60-second explainer video about how GPS works"*
|
|
108
|
+
|
|
109
|
+
Or call the tool directly:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
create_video_from_script({
|
|
113
|
+
scenes: [
|
|
114
|
+
{
|
|
115
|
+
narration: "GPS works by triangulating signals from at least four satellites.",
|
|
116
|
+
caption: "GPS TRIANGULATION",
|
|
117
|
+
visual_description: "satellite orbiting earth, flat illustration, bold colors"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
narration: "Your phone measures tiny timing differences to pinpoint your location.",
|
|
121
|
+
caption: "YOUR LOCATION",
|
|
122
|
+
visual_description: "phone with pin on map, white background, minimal"
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
title: "How GPS Works"
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Output lands in `.frameforge-files/`:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
final_video_<id>.mp4 → 1080p landscape master
|
|
133
|
+
short_1_<id>.mp4 → auto-extracted 9:16 vertical Short
|
|
134
|
+
video_meta.json → title, description, tags, chapters
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**No API keys required for this path.** `edge-tts` (voice) and `pollinations` (images) are both free with no account. If Pollinations is slow, add `FALAI_API_KEY` and set `PROVIDER_IMAGE=falai`.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Two ways to use it
|
|
142
|
+
|
|
143
|
+
### Your IDE writes the script — no LLM key needed
|
|
144
|
+
|
|
145
|
+
Your IDE's model writes the scenes. FrameForge only runs FFmpeg, TTS, and image generation. Use `create_video_from_script`. This is the fastest path and what most people want.
|
|
146
|
+
|
|
147
|
+
### FrameForge researches and scripts itself
|
|
148
|
+
|
|
149
|
+
For batch runs or when running without an IDE. Requires a free LLM key (Groq or Gemini both have free tiers).
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm run make -- --topic "How does GPS actually work?"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Bring your own media
|
|
158
|
+
|
|
159
|
+
Skip AI generation for any scene by supplying your own files:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"narration": "Here is the sorting algorithm running step by step.",
|
|
164
|
+
"caption": "ALGORITHM",
|
|
165
|
+
"video_path": "/recordings/screen_capture.mp4",
|
|
166
|
+
"audio_path": "/recordings/my_voice.mp3"
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Any combination of `image_path`, `video_path`, `audio_path` works — FrameForge only generates what you don't supply.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Tools
|
|
175
|
+
|
|
176
|
+
17 tools, grouped by what you're doing:
|
|
177
|
+
|
|
178
|
+
**Make a video from your own script (no LLM key)**
|
|
179
|
+
|
|
180
|
+
| Tool | What it does |
|
|
181
|
+
|------|-------------|
|
|
182
|
+
| `create_video_from_script` | Full render from scenes you provide — voice, images, FFmpeg, quality gate |
|
|
183
|
+
| `ingest_media` | Import your own clips, images, and audio into a scenes manifest |
|
|
184
|
+
| `edit_scenes` | Update captions, swap media files, or append scenes to a manifest |
|
|
185
|
+
| `render_from_scenes` | Re-render from an existing manifest, skipping research and scripting |
|
|
186
|
+
| `assemble_video` | FFmpeg render + quality gate — produces the master MP4 |
|
|
187
|
+
| `render_tts` | Generate voice audio for one scene |
|
|
188
|
+
| `multi_voice_tts` | Override TTS provider per call without touching `.env` |
|
|
189
|
+
| `generate_scene_image` | Generate one scene image via the configured image provider |
|
|
190
|
+
| `publish_video` | Deliver the finished video via file copy or HTTP webhook |
|
|
191
|
+
| `external_platform_call` | HTTP bridge to ElevenLabs, Runway, Replicate, or any custom platform |
|
|
192
|
+
|
|
193
|
+
**Auto-research pipeline (needs a free LLM key)**
|
|
194
|
+
|
|
195
|
+
| Tool | What it does |
|
|
196
|
+
|------|-------------|
|
|
197
|
+
| `research_topic` | Research any topic and extract fact-checked claims |
|
|
198
|
+
| `write_script` | Generate a structured scene script from research claims |
|
|
199
|
+
| `queue_full_pipeline` | Queue a full research → render → publish run; returns `{ jobId }` immediately |
|
|
200
|
+
| `get_job_status` | Poll a queued job for `{ status, stage, result }` |
|
|
201
|
+
|
|
202
|
+
**Code-driven animated video (Playwright + FFmpeg)**
|
|
203
|
+
|
|
204
|
+
| Tool | What it does |
|
|
205
|
+
|------|-------------|
|
|
206
|
+
| `scaffold_animation_project` | Create a project where every frame is a pure function of time `t` |
|
|
207
|
+
| `validate_storyboard` | Check `STORYBOARD.md` against the 4-gate beat-sheet contract |
|
|
208
|
+
| `render_animation` | Run the Playwright renderer: sheet / strip / storyboard / crop / full |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Providers
|
|
213
|
+
|
|
214
|
+
Switch any provider with one `.env` change — no code changes.
|
|
215
|
+
|
|
216
|
+
**Voice (TTS)**
|
|
217
|
+
|
|
218
|
+
| Provider | Free? | Key needed |
|
|
219
|
+
|----------|-------|------------|
|
|
220
|
+
| `edge-tts` | ✅ free, offline | none — **default** |
|
|
221
|
+
| `elevenlabs` | paid | `ELEVENLABS_API_KEY` |
|
|
222
|
+
| `azure` | paid | `AZURE_SPEECH_KEY` + `AZURE_SPEECH_REGION` |
|
|
223
|
+
| `openai` | paid | `OPENAI_API_KEY` |
|
|
224
|
+
| `webhook` | — | `WEBHOOK_TTS_URL` |
|
|
225
|
+
|
|
226
|
+
Set `PROVIDER_TTS=<name>`.
|
|
227
|
+
|
|
228
|
+
**Images**
|
|
229
|
+
|
|
230
|
+
| Provider | Free? | Key needed |
|
|
231
|
+
|----------|-------|------------|
|
|
232
|
+
| `pollinations` | ✅ free, no account | none — **default** |
|
|
233
|
+
| `falai` | ✅ free tier | `FALAI_API_KEY` at fal.ai |
|
|
234
|
+
| `replicate` | paid | `REPLICATE_API_KEY` |
|
|
235
|
+
| `dalle` | paid | `OPENAI_API_KEY` |
|
|
236
|
+
| `webhook` | — | `WEBHOOK_IMAGE_URL` |
|
|
237
|
+
|
|
238
|
+
Set `PROVIDER_IMAGE=<name>`.
|
|
239
|
+
|
|
240
|
+
**LLM — only for the auto-research path**
|
|
241
|
+
|
|
242
|
+
> Skip entirely when using `create_video_from_script`.
|
|
243
|
+
|
|
244
|
+
| Provider | Free? | Key needed |
|
|
245
|
+
|----------|-------|------------|
|
|
246
|
+
| `groq` | ✅ free tier | `GROQ_API_KEY` at console.groq.com |
|
|
247
|
+
| `gemini` | ✅ free tier | `GEMINI_API_KEY` at aistudio.google.com |
|
|
248
|
+
| `ollama` | ✅ fully local | none — set `OLLAMA_MODEL` |
|
|
249
|
+
| `openrouter` | pay per use | `OPENROUTER_API_KEY` |
|
|
250
|
+
| `anthropic` | paid | `ANTHROPIC_API_KEY` |
|
|
251
|
+
| `openai` | paid | `OPENAI_API_KEY` |
|
|
252
|
+
|
|
253
|
+
Set `PROVIDER_LLM=<name>`.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Quality gates
|
|
258
|
+
|
|
259
|
+
Every video passes 7 checks before delivery. Any failure blocks the output.
|
|
260
|
+
|
|
261
|
+
| Check | Requirement |
|
|
262
|
+
|-------|------------|
|
|
263
|
+
| Resolution | 1920×1080 landscape or 1080×1920 portrait |
|
|
264
|
+
| Video codec | H.264, high profile, yuv420p |
|
|
265
|
+
| Loudness | −14 LUFS ± 1.5 LU (broadcast standard) |
|
|
266
|
+
| True peak | ≤ −0.5 dBTP |
|
|
267
|
+
| Black frames | None longer than 0.5 s |
|
|
268
|
+
| Frozen frames | None longer than 0.5 s |
|
|
269
|
+
| File integrity | > 1 MB, valid video + audio streams |
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## CLI commands
|
|
274
|
+
|
|
275
|
+
| Command | What it does |
|
|
276
|
+
|---------|-------------|
|
|
277
|
+
| `npm run doctor` | Check Node, FFmpeg, edge-tts, and env vars |
|
|
278
|
+
| `npm run setup` | Interactive key wizard — writes `.env` |
|
|
279
|
+
| `npm run mcp` | Start MCP server on port 3210 |
|
|
280
|
+
| `npm run mcp:stdio` | stdio MCP server for direct IDE connection |
|
|
281
|
+
| `npm run make -- --topic "..."` | Full pipeline: research → render → deliver |
|
|
282
|
+
| `npm run validate` | Deep structural validation (113 checks) |
|
|
283
|
+
| `npm test` | Test suite (512 tests) |
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Architecture
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
YOUR IDE (Bob / Codex / opencode / Cursor / Windsurf / Claude Code)
|
|
291
|
+
│
|
|
292
|
+
│ HTTPS + SSE (Cloudflare Remote MCP — optional)
|
|
293
|
+
▼
|
|
294
|
+
[Cloudflare Worker] proxies tool calls, keeps IDE context lean
|
|
295
|
+
│
|
|
296
|
+
│ HTTP + INTERNAL_API_TOKEN
|
|
297
|
+
▼
|
|
298
|
+
[FrameForge Node] runs on VPS / Pi / your machine / Render.com
|
|
299
|
+
│
|
|
300
|
+
├─ src/mcp-server/ 17 MCP tools
|
|
301
|
+
├─ src/workflows/ research → script → assets → render → publish
|
|
302
|
+
├─ src/pipeline/ state machine, retry, telemetry, manifest
|
|
303
|
+
├─ src/video-renderer/ FFmpeg scene render + concat
|
|
304
|
+
├─ src/audio-mixer/ LUFS normalise, sidechain ducking
|
|
305
|
+
└─ src/quality-gate/ 7-point output validation
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Security
|
|
311
|
+
|
|
312
|
+
- **Timing-safe auth** — all token comparisons use `crypto.timingSafeEqual`
|
|
313
|
+
- **SSRF protection** — webhook and pipeline URLs validated against RFC-1918 / loopback / link-local blocklist
|
|
314
|
+
- **Path traversal guards** — `productionId`, `audioPath`, `localPath` validated before any file I/O
|
|
315
|
+
- **CLI injection guards** — animation timestamps allowlisted before passing to `render.mjs`
|
|
316
|
+
- **Worker API auth** — `INTERNAL_API_TOKEN` Bearer check on all internal routes
|
|
317
|
+
- **Body size limits** — all HTTP servers reject requests > 4 MB with HTTP 413
|
|
318
|
+
- **Credential redaction** — 14+ regex patterns strip API keys from all logs
|
|
319
|
+
|
|
320
|
+
Report vulnerabilities: [SECURITY.md](SECURITY.md)
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Deployment
|
|
325
|
+
|
|
326
|
+
**VPS / Pi / local machine:**
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
git clone https://github.com/AMG555/FrameForge.git && cd FrameForge
|
|
330
|
+
cp docs/env.template .env # edit with your keys
|
|
331
|
+
npm run mcp
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
See [`docs/deployment.md`](docs/deployment.md) for Docker, systemd, and Render.com setup.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Testing
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
npm test # 512 tests, 0 failures
|
|
342
|
+
npm run validate # 113 structural checks
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Contributing
|
|
348
|
+
|
|
349
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
350
|
+
|
|
351
|
+
1. `npm run doctor` passes on your OS
|
|
352
|
+
2. `npm test` passes (512/512)
|
|
353
|
+
3. `npm run validate` passes (113/113)
|
|
354
|
+
4. FFmpeg commands keep `-nostdin` and cross-platform font paths
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## License
|
|
359
|
+
|
|
360
|
+
MIT — see [LICENSE](LICENSE).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|:--- |:---: |
|
|
7
|
+
| 2.x (current) | ✅ |
|
|
8
|
+
| 1.x | ✅ security fixes only |
|
|
9
|
+
| < 1.0 | ❌ |
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Reporting a Vulnerability
|
|
14
|
+
|
|
15
|
+
**Please do not open a public GitHub Issue for security vulnerabilities.**
|
|
16
|
+
|
|
17
|
+
Report security issues by emailing **amgt503@gmail.com** with:
|
|
18
|
+
|
|
19
|
+
1. A description of the vulnerability and its potential impact.
|
|
20
|
+
2. Steps to reproduce (minimal proof of concept if possible).
|
|
21
|
+
3. Affected versions.
|
|
22
|
+
4. Any suggested mitigation.
|
|
23
|
+
|
|
24
|
+
You will receive an acknowledgement within **48 hours** and a resolution
|
|
25
|
+
timeline within **7 days**. We will credit you in the release notes unless you
|
|
26
|
+
prefer to remain anonymous.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Security Model
|
|
31
|
+
|
|
32
|
+
### Secrets handling
|
|
33
|
+
- All credentials are loaded exclusively from environment variables (`.env`).
|
|
34
|
+
- No secrets are committed to git — the `.gitignore` excludes `.env` and all
|
|
35
|
+
`*secrets*` files.
|
|
36
|
+
- `src/utils/log-redaction.js` masks known credential patterns (API keys,
|
|
37
|
+
tokens, connection strings, Bearer tokens) from all log output.
|
|
38
|
+
|
|
39
|
+
### Authentication
|
|
40
|
+
- The Cloudflare Workers MCP endpoint requires a `Bearer` token
|
|
41
|
+
(`MCP_AUTH_TOKEN`) on every request.
|
|
42
|
+
- The internal render API (`server-render-free.js`) requires
|
|
43
|
+
`INTERNAL_API_TOKEN` on all non-health routes.
|
|
44
|
+
- Tokens are compared with `crypto.timingSafeEqual` to prevent timing attacks.
|
|
45
|
+
|
|
46
|
+
### Shell injection prevention
|
|
47
|
+
- All external process calls use `spawnSync(cmd, [args, as, array])` — never
|
|
48
|
+
template string interpolation into shell commands.
|
|
49
|
+
|
|
50
|
+
### Network
|
|
51
|
+
- FFmpeg calls use `-nostdin` to prevent interactive prompts from blocking.
|
|
52
|
+
- All outbound HTTP calls (Pollinations, search APIs, webhook endpoints) use
|
|
53
|
+
Node.js `https` with explicit timeouts and no silent redirects beyond 5 hops.
|
|
54
|
+
|
|
55
|
+
### Cloudflare Workers
|
|
56
|
+
- The CF Workers MCP proxy does not store any credentials. `WORKER_API_URL`,
|
|
57
|
+
`MCP_AUTH_TOKEN`, and `INTERNAL_API_TOKEN` are set as Wrangler secrets
|
|
58
|
+
(encrypted at rest by Cloudflare).
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Known Limitations
|
|
63
|
+
|
|
64
|
+
- The LLM fallback in `FactChecker._querySources()` produces synthesized
|
|
65
|
+
sources when no `SEARCH_API_KEY` is set. These are not real citations and
|
|
66
|
+
should not be presented as authoritative without a real search provider.
|
|
67
|
+
- Pollinations.ai image requests are unauthenticated — do not include
|
|
68
|
+
private or sensitive content in image prompts.
|
|
69
|
+
- `PUBLISH_WEBHOOK_URL` and `REVIEW_NOTIFY_URL` receivers are trusted
|
|
70
|
+
endpoints; ensure they are authenticated on your side before deploying
|
|
71
|
+
to production.
|
package/START_HERE.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# FrameForge — Start Here
|
|
2
|
+
|
|
3
|
+
> **Paste this file's path into your agent IDE chat to start a guided video session.**
|
|
4
|
+
> The agent will read this file, ask you what you want to make, and drive the full pipeline.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## For the Agent
|
|
9
|
+
|
|
10
|
+
You are a video producer powered by FrameForge. Your job is to have a short conversation
|
|
11
|
+
with the user to understand what video they want, then use the FrameForge MCP tools to
|
|
12
|
+
produce it — from research through render to final MP4.
|
|
13
|
+
|
|
14
|
+
**Do not assume anything. Ask first. Produce second.**
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Opening Message (say this verbatim to the user)
|
|
19
|
+
|
|
20
|
+
> 👋 I'm your FrameForge video studio. I can make short-form reels, YouTube explainers,
|
|
21
|
+
> documentary clips, tutorials, or any video you describe — using AI research, voiceover,
|
|
22
|
+
> animated scenes, and a full render pipeline.
|
|
23
|
+
>
|
|
24
|
+
> Let's start with a few quick questions so I know exactly what to build:
|
|
25
|
+
>
|
|
26
|
+
> 1. **What's the topic or idea?** (e.g. "How black holes form", "5 tips for sourdough bread", "A travel reel about Tokyo")
|
|
27
|
+
> 2. **What style?** Pick one: `educational` · `comedic` · `documentary` · `vlog` · `cinematic` · `tutorial` · or describe your own
|
|
28
|
+
> 3. **How long?** `Short (15–60s)` · `Medium (1–3 min)` · `Long (5–10 min)`
|
|
29
|
+
> 4. **Orientation?** `Landscape 16:9 (YouTube/desktop)` · `Portrait 9:16 (Reels/TikTok/Shorts)`
|
|
30
|
+
> 5. **Voice?** `Auto-select` · or name a style: `professional narrator`, `friendly teacher`, `energetic host`
|
|
31
|
+
> 6. **Any images or clips you want included?** (paste file paths, or say "no — generate everything")
|
|
32
|
+
>
|
|
33
|
+
> Answer as many or as few as you like. I'll fill in the rest.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## After the User Answers — Agent Instructions
|
|
38
|
+
|
|
39
|
+
Once you have the user's answers, proceed as follows. Never skip the beat-sheet gate.
|
|
40
|
+
|
|
41
|
+
### Step 1 — Beat Sheet Gate (MANDATORY, no exceptions)
|
|
42
|
+
|
|
43
|
+
Before calling any render tool, produce a **beat sheet** in this exact format and
|
|
44
|
+
**stop** — wait for the user to approve it before continuing:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
BEAT SHEET — "<title>"
|
|
48
|
+
Duration: Xs | Style: <style> | Format: <orientation>
|
|
49
|
+
|
|
50
|
+
Scene 1 [0:00–0:08] <what happens + what the viewer learns> → TRANSITION
|
|
51
|
+
Scene 2 [0:08–0:18] <what happens + what the viewer learns> → TRANSITION
|
|
52
|
+
...
|
|
53
|
+
Scene N [X:XX–X:XX] <what happens + what the viewer learns> → FADE OUT
|
|
54
|
+
|
|
55
|
+
Voice: <voice description>
|
|
56
|
+
Visual style: <1-sentence description>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Gate rules — reject and revise the beat sheet if ANY of these are true:
|
|
60
|
+
- A scene has no event (action that changes something)
|
|
61
|
+
- Two scenes share the same timestamp range
|
|
62
|
+
- Any seam is missing a transition label
|
|
63
|
+
- The total duration doesn't match the user's requested length ±10%
|
|
64
|
+
|
|
65
|
+
Only proceed to Step 2 after the user says **"looks good"**, **"go ahead"**, or equivalent.
|
|
66
|
+
|
|
67
|
+
### Step 2 — Research (if the topic needs facts)
|
|
68
|
+
|
|
69
|
+
Use `research_topic` to gather verified claims. Skip this for pure creative/style videos.
|
|
70
|
+
|
|
71
|
+
### Step 3 — Script
|
|
72
|
+
|
|
73
|
+
Use `write_script` with the beat sheet as the outline. Pass `style`, `format`, and
|
|
74
|
+
`voice` from the user's answers. The script must match the beat sheet scene-for-scene.
|
|
75
|
+
|
|
76
|
+
### Step 4 — Assets
|
|
77
|
+
|
|
78
|
+
For each scene, call `generate_scene_image` with a prompt that matches the scene's
|
|
79
|
+
visual description. If the user supplied their own files, use `ingest_media` instead.
|
|
80
|
+
|
|
81
|
+
Call `render_tts` for each scene's narration line.
|
|
82
|
+
|
|
83
|
+
### Step 5 — Render
|
|
84
|
+
|
|
85
|
+
Call `create_video_from_script` (IDE-driven path) or `assemble_video` (pipeline path)
|
|
86
|
+
to produce the final MP4.
|
|
87
|
+
|
|
88
|
+
After render, call `render_animation` with `mode: "sheet"` to produce a contact-sheet
|
|
89
|
+
preview. Show the user the sheet path and ask if they want any changes.
|
|
90
|
+
|
|
91
|
+
### Step 6 — Publish (optional)
|
|
92
|
+
|
|
93
|
+
Ask the user: "Do you want to publish this anywhere, or just save the file locally?"
|
|
94
|
+
|
|
95
|
+
If they want to publish, call `publish_video` with their chosen channel.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Quick Reference — MCP Tools
|
|
100
|
+
|
|
101
|
+
| Tool | What it does |
|
|
102
|
+
|------|-------------|
|
|
103
|
+
| `research_topic` | Research any topic, extract verified claims |
|
|
104
|
+
| `write_script` | Turn claims + beat sheet into a full narrated script |
|
|
105
|
+
| `generate_scene_image` | AI-generated scene image from a prompt |
|
|
106
|
+
| `render_tts` | Text-to-speech narration for a scene |
|
|
107
|
+
| `create_video_from_script` | **IDE path** — you write the scenes, FrameForge renders |
|
|
108
|
+
| `assemble_video` | Assemble rendered scenes into a master MP4 |
|
|
109
|
+
| `render_animation` | Render HTML animation scenes (code-driven videos) |
|
|
110
|
+
| `scaffold_animation_project` | Create a new code-driven animation project |
|
|
111
|
+
| `ingest_media` | Import user-supplied images, clips, or audio |
|
|
112
|
+
| `edit_scenes` | Re-render specific scenes with new prompts/captions |
|
|
113
|
+
| `get_job_status` | Check async job progress |
|
|
114
|
+
| `publish_video` | Upload to YouTube, push to webhook, or copy to folder |
|
|
115
|
+
| `get_pipeline_status` | Health check and current job queue |
|
|
116
|
+
| `external_platform_call` | Call any external API during production |
|
|
117
|
+
|
|
118
|
+
Full tool docs: [`src/mcp-server/server.js`](src/mcp-server/server.js)
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Setup Check
|
|
123
|
+
|
|
124
|
+
Before starting, confirm the server is running:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npm run doctor # checks ffmpeg, fonts, TTS, LLM key
|
|
128
|
+
npm run mcp # starts the MCP server on port 3210
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
If `npm run doctor` reports missing dependencies, fix them before proceeding.
|
|
132
|
+
See [`docs/env.template`](docs/env.template) for all environment variables.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Determinism Note (for code-driven animations)
|
|
137
|
+
|
|
138
|
+
If the user wants a **code-driven animation** (like the viral "Claude explains X" style),
|
|
139
|
+
use `scaffold_animation_project` to create a project, then use `render_animation` to
|
|
140
|
+
render it. Every frame is a pure function of time `t` — same input always produces the
|
|
141
|
+
same pixels, enabling parallel render, resume, and diff-based review.
|
|
142
|
+
|
|
143
|
+
See [`SKILL.md`](plugins/video-pipeline/skills/video-pipeline/SKILL.md) for the full
|
|
144
|
+
code-driven animation workflow.
|
package/install.sh
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install the video-pipeline skill into your Claude/Bob skills folder.
|
|
3
|
+
#
|
|
4
|
+
# ./install.sh copy into ~/.claude/skills (every project)
|
|
5
|
+
# ./install.sh --project copy into ./.claude/skills (this project only)
|
|
6
|
+
# ./install.sh --link symlink instead of copy (edits to repo are live)
|
|
7
|
+
# ./install.sh --bob copy into ~/.bob/skills (IBM Bob global)
|
|
8
|
+
#
|
|
9
|
+
# An existing skill with the same name is moved aside to <name>.bak.<ts>.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
13
|
+
SRC="$HERE/plugins/video-pipeline/skills"
|
|
14
|
+
DEST="$HOME/.claude/skills"
|
|
15
|
+
MODE=copy
|
|
16
|
+
|
|
17
|
+
for a in "$@"; do
|
|
18
|
+
case "$a" in
|
|
19
|
+
--link) MODE=link ;;
|
|
20
|
+
--project) DEST="$PWD/.claude/skills" ;;
|
|
21
|
+
--bob) DEST="$HOME/.bob/skills" ;;
|
|
22
|
+
-h|--help) sed -n 2,10p "$0"; exit 0 ;;
|
|
23
|
+
*) echo "unknown option: $a"; exit 1 ;;
|
|
24
|
+
esac
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
mkdir -p "$DEST"
|
|
28
|
+
|
|
29
|
+
for dir in "$SRC"/*; do
|
|
30
|
+
name=$(basename "$dir")
|
|
31
|
+
target="$DEST/$name"
|
|
32
|
+
if [ -e "$target" ] || [ -L "$target" ]; then
|
|
33
|
+
mv "$target" "$target.bak.$(date +%Y%m%d%H%M%S)"
|
|
34
|
+
echo " moved existing $name aside"
|
|
35
|
+
fi
|
|
36
|
+
if [ "$MODE" = link ]; then
|
|
37
|
+
ln -s "$dir" "$target"
|
|
38
|
+
else
|
|
39
|
+
cp -R "$dir" "$target"
|
|
40
|
+
fi
|
|
41
|
+
echo " installed $name → $target ($MODE)"
|
|
42
|
+
done
|
|
43
|
+
|
|
44
|
+
echo
|
|
45
|
+
echo "Dependencies (must be available in PATH):"
|
|
46
|
+
for t in ffmpeg ffprobe node npm; do
|
|
47
|
+
printf " %-10s %s\n" "$t" "$(command -v "$t" 2>/dev/null || echo 'MISSING — install it')"
|
|
48
|
+
done
|
|
49
|
+
# Optional: edge-tts for free TTS
|
|
50
|
+
if command -v edge-tts >/dev/null 2>&1; then
|
|
51
|
+
echo " edge-tts $(command -v edge-tts) (free TTS, no key)"
|
|
52
|
+
else
|
|
53
|
+
echo " edge-tts not found — run: npm install -g edge-tts"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
echo
|
|
57
|
+
echo "Next steps:"
|
|
58
|
+
echo " 1. cp docs/env.template .env"
|
|
59
|
+
echo " 2. Edit .env with your API keys (run 'npm run setup' for interactive wizard)"
|
|
60
|
+
echo " 3. Deploy Cloudflare Remote MCP (recommended): cd cloudflare-mcp && wrangler deploy"
|
|
61
|
+
echo " OR start local HTTP MCP: node src/mcp-server/server.js"
|
|
62
|
+
echo " 4. Register the MCP endpoint in your IDE:"
|
|
63
|
+
echo " Codex / opencode / Cursor / IBM Bob / Claude Code / Windsurf — see README.md"
|
|
64
|
+
echo " 5. Restart your IDE to load the skill."
|