| name | product-demo-director |
| description | Turn raw screen recordings + a shot list into a finished, narrated, before/after product-demo video — voiceover, music, kinetic captions, motion, and an AI judge loop. Use when producing an investor or sales demo video from product footage. |
Product Demo Director
Give it raw footage and a JSON shot list; it directs the cut: ElevenLabs voiceover per shot,
a music bed sized to the runtime, kinetic captions that match the narration, continuous push-ins
and drift, a white-flash match-cut at the before→after pivot, then a Gemini judge that watches
and hears the result and scores it so an improve loop can push it to ship quality.
The motion engine is a single props-driven Remotion composition, so one pipeline renders many
cuts (teaser, walkthrough, race, full demo) from the same assets.
When to use
- Producing a before/after product demo from screen recordings (investor or sales).
- Re-cutting one set of footage into multiple lengths/formats.
- Any narrated, captioned, music-scored demo that needs to look directed, not screen-grabbed.
Not for: editing arbitrary cinematic footage, or anything where you don't control the shot list.
Setup (once)
cd engine && npm install && cd ..
python -m venv .venv && . .venv/bin/activate && pip install -r tools/requirements.txt
playwright install chromium
export ELEVENLABS_API_KEY=...
export GEMINI_API_KEY=...
Run the pipeline
A project is a folder with script.json + an assets/ dir of clips (and, ideally, a
brand.json and a product.json). Two runnable examples: examples/promo/ (the original
showcase) and examples/self/ (the skill demoing itself — brand-themed, brief-drafted,
footage it captured). The first three steps below are the new front of the pipeline — onboard a
brand, let the director capture the footage, and draft the script from the product brief — so you
don't have to pre-record or hand-write anything:
python tools/onboard.py --project examples/self --url https://yourproduct.com
python tools/shoot.py --project examples/self
python tools/script.py --project examples/self
python tools/vo.py --project examples/self
python tools/music.py --project examples/self
python tools/sfx.py
python tools/build.py --project examples/self
python tools/judge.py --video examples/self/out/demo.mp4 --fps 6 --context "what this demo is"
Steps 0a-0c are optional conveniences: every example ships a committed brand.json/script.json,
so the pipeline runs without any LLM key. brand.json is the brand source of truth — its palette,
font, and logo flow into the engine theme (not just the CTA wordmark), so the whole cut adopts
the brand. See docs/CAPTURE.md for autonomous shoot planning + terminal footage.
To iterate automatically, feed judge.py's specific_upgrades back into the script/engine and
re-render (pairs well with github.com/crimeacs/auto-improve as the keep/revert gate).
Script schema
script.json (canonical example: examples/promo/script.json). Each shot is one of
title | clip | split | stat | cta | score | bars | strip — score is an animated count-up to a
number, bars is the rejected-takes-clear-a-PASS-line visual, strip pans a filmstrip of shots:
{
"fps": 30,
"music": "calm confident minimal corporate underscore, soft pulse, no drums",
"brand": { "name": "Product Demo ", "accent": "Director" },
"pronounce": { "Foresyn": "Foreseen" },
"voice_settings": { "stability": 0.32, "style": 0.75, "similarity_boost": 0.85, "use_speaker_boost": true },
"shots": [
{ "n": 1, "kind": "title", "title": "Your demo is a flat screen recording.", "durSec": 2.6, "vo": "..." },
{ "n": 2, "kind": "clip", "src": "raw.mp4", "inSec": 2, "chapter": "BEFORE", "scale": 1.0, "vo": "..." },
{ "n": 3, "kind": "clip", "src": "raw.mp4", "chapter": "AFTER", "flash": true, "scale": 1.2, "vo": "..." },
{ "n": 4, "kind": "split", "srcL": "raw.mp4", "labelL": "Raw", "srcR": "directed.mp4", "labelR": "Directed", "durSec": 4, "vo": "..." },
{ "n": 5, "kind": "stat", "title": "Scored 92 / 100.", "durSec": 2.5, "vo": "..." },
{ "n": 6, "kind": "cta", "title": "the demo your product deserves", "durSec": 3, "vo": "..." }
]
}
Notes:
- When a shot has
vo, the on-screen caption defaults to that exact line (subtitles match the
narration). Override with an explicit caption.
accent on a shot fires a palette sound on that beat (click, data_tick, success_chime,
confirm_cash, pivot_boom); the pivot also gets a riser + boom automatically.
flash: true (or chapter: "AFTER") marks the pivot — the white-flash match-cut, the riser
before it, and the impact on the reveal all key off it.
pronounce rewrites spellings for the TTS audio only; captions keep the real spelling.
brand.name + brand.accent render the CTA wordmark (accent tail colored).
Craft rules
The methodology — each rule was a real mistake first — lives in docs/EDITING.md (the edit) and
docs/CAPTURE.md (capturing live-app footage). Read them before authoring a script. Highlights:
- Subtitles are the narration. Caption == the spoken line on every narrated shot.
- Kill dead air. Keep narration near-continuous on fast cuts; music-only > ~5s reads as dead.
- Show the work. Open from the real entry point; feature one click-to-evidence beat.
- Redact identifiers, never the value. Hide client marks; keep the proof sharp and legible.
- Be honest. Only verified numbers; no capability the product doesn't have.
Credit
Built at Foresyn. MIT licensed.