Product Feature Video Skill
Plan and build a demo/feature video for a real, running product — captured on real screens via Playwright, narrated with real TTS, scored with a real (open-source, license-clean) music bed, and assembled in Remotion. This is a different discipline from a synthetic motion-graphics product trailer: the footage already exists and can't be redrawn to fit a plan, so the plan has to fit the footage.
The key difference from a synthetic motion-graphics trailer
Plenty of Remotion video workflows assume you control every pixel and can re-time anything — because the whole video is built from scratch: mockups, generated backgrounds, invented UI. That assumption doesn't hold here. A real screen recording runs on its own clock; a real click happens on one specific frame, not whenever a storyboard wants it to; some moments (a native OS window, a browser's own toolbar, an interaction that completes in half a second) can't be re-shot to fit a plan at all. This skill is built around that constraint from the ground up — motion-design craft (easing, transitions, motion density) still matters and is covered in Phase 8, but the pipeline's real backbone is what footage-driven video specifically requires: a prototype-fallback audit for the un-capturable moments, stability-verified targeting for zooms and click emphasis on real footage, and timing driven by actual asset durations rather than a plan.
Core principle: real footage first, prototype second, illustration last
For every scene, prefer in this order:
- Real footage — an actual Playwright recording of the actual running app.
- A reviewed HTML prototype, captured the same way, for anything real footage structurally cannot show (see Phase 2).
- An honest, clearly-illustrated placeholder — only when neither of the above is achievable yet, and only if it doesn't pretend to be real.
Never fake option 1 with option 3 dressed up to look real. A viewer trusts a demo video precisely because it's real; one fabricated-looking moment undermines all the genuine ones.
Phase 0: Brief
Ask once, together, before anything else:
- Product & repo — name, one-line description, URL/local path to the running app or repo.
- Audience & tone — who's watching, and what should they feel (impressed / reassured / excited)?
- Duration — 30s teaser, 60-90s walkthrough, or a fuller 2-3 min tour? Real footage runs long fast; be honest about scope.
- The one moment that must land — if the viewer remembers exactly one thing, what is it? This becomes the climax/hero beat.
- Login/test account — does capturing the app require an account? Can a disposable demo account be created, or does one already exist?
- Publishing context — landing page, YouTube, social feed (autoplay-muted matters a lot for caption/on-screen-text decisions).
If the product is a browser extension, also ask whether Manifest V3 is in play (changes the Playwright launch strategy — see Phase 6).
Phase 1: Recon — extract the real design system, don't invent one
Before any aesthetic decision, read the actual product:
- Pull the real color tokens, font stack, and spacing scale from the app's own CSS/theme file. Use them as-is, even if the accent color happens to resemble a "generic AI SaaS" cliché (indigo/purple on near-black is extremely common in real product palettes too — it's only a red flag when it's an invented default, not when it's the actual product). Authenticity beats novelty here.
- Note the product's actual UI copy, terminology, and information architecture — the video's captions and voiceover should use the app's own words, not marketing paraphrase.
- Run the app once, end to end, as a user would. Identify: what's the single best "hero" interaction? What's genuinely hard to demonstrate live (see Phase 2)?
Save the extracted tokens (colors, fonts) into a tokens.ts/tokens.css the whole video project imports from one place — every scene, real or code-built, should visibly belong to the same product.
Phase 2: Prototype-Fallback Audit (do this before the storyboard)
Walk the planned feature list and flag anything Playwright structurally cannot capture:
- OS-level browser chrome — the extension toolbar icon,
chrome://extensions, right-click context menus, native file pickers, native OS dialogs. Playwright'srecordVideoonly captures page content, never the browser's own UI. - Native desktop shells (Tauri, Electron once packaged, Qt, etc.) — these aren't a web page Playwright can attach to at all.
- Interactions too fast or too small to reliably showcase — a toggle flip that completes in under half a second of real footage is a poor target for a crop-zoom or a click-emphasis ring; both need a stable multi-frame window to land on (see Phase 8's ZoomCue/ClickRing pattern and its stability rule).
For each flagged moment, decide: real footage with a workaround (e.g., seed state via an API call instead of a real click, per Phase 6), a reviewed HTML prototype (Phase 7), or an honestly-labeled illustration (last resort, and say so in a code comment).
Doing this audit before the storyboard, not after, prevents the storyboard from committing to timing and coverage that the actual capture step can't deliver — this was the single biggest source of rework across TabNemo's own v1-v3.
Phase 3: Storyboard & Scene Plan
Narrative arc
Same shape works whether the footage is real or synthetic:
| Act | Purpose | Share of runtime |
|---|---|---|
| Hook | Cold open — the problem, or a striking moment, before the product name appears | 5-8% |
| Reveal | Brand/product name lands | 8-10% |
| Showcase | 3-5 real features, one beat each | 45-55% |
| Climax | The hero moment identified in Phase 0 — give it the most visual care | 8-12% |
| Close | Logo, tagline, CTA | 8-10% |
Per-scene spec
For every scene, decide up front and write down:
- Source: real clip / prototype capture / code-built b-roll (per Phase 2's audit).
- Narration: exact text, or
null. Narration length is a real constraint — TTS audio duration becomes the scene's minimum length (see Phase 4). - Real footage runs on its own clock — a scene's
durationInFramesismax(real clip length, narration length), probed from the actual rendered assets, never assumed from a plan. Where narration outlasts the clip, hold the clip's last frame rather than looping or cutting the line off. - Camera plan: any punch-in/zoom or click-emphasis, with real coordinates — decided from actual stills, not guessed (Phase 8).
Review checkpoint
Show the scene list + narration text before recording a single clip or generating a note of audio. A plan built on wrong assumptions about available footage is expensive to unwind once TTS and Playwright scripts exist.
Phase 4: Voiceover — script and generation
Write two documents, not one:
- A review script — one block per scene, with its planned timecode, so a human can read the whole narration arc and approve pacing before generation.
- A TTS input script — the same lines, split one-per-scene-file, pacing carried by punctuation only (or SSML
<break>/<emphasis>tags if the engine supports them), so each scene becomes its own audio clip placeable at its own offset.
Generation tooling
- ttsmp3.com — free, no signup, Amazon-Polly-backed. No public API, so generation is one clip at a time through the browser UI — budget a single focused session to do them all, and name output files by scene (
scene-03.mp3, nottts_export_1.mp3). - For a pipeline that needs to run unattended (CI, an agent with no browser-in-the-loop), prefer an actually scriptable open-source/local option instead: Piper (fully offline, MIT-licensed, fast, decent voices) or edge-tts (wraps Microsoft Edge's read-aloud voices, free, no key, scriptable, but depends on an external service staying available). Gemini TTS and ElevenLabs are strong non-open alternatives if API cost is acceptable. Whichever engine, if it doesn't guarantee voice consistency across separate calls, generate all segments in a single request with pause markers between them, then split on detected silence — that one trick fixes the "different voice per line" problem regardless of engine.
After generation — audio is the source of truth
Probe every generated file's real duration (don't trust an estimate). Propagate real durations back into the scene plan's timing. This one step prevented every timing bug in TabNemo's build — narration is what the viewer's ear measures a scene against, so it, not the plan, sets the clock.
Phase 5: Background Score — get a catchy one without a licensing landmine
A flat pad-and-drone loop reads as elevator hold music, not a "catchy" bed — the difference is almost always a repeating melodic hook, not just harmonic pads. Three real options, in order of "safest license" to "most reliably catchy":
Option A — Procedural synthesis (zero license risk, needs real effort to not sound flat)
Generate a short, seamlessly-loopable stereo WAV in plain Node/Python — no models, no dependencies, no licensing question at all, because you wrote every sample. The concrete recipe that worked:
- A short (8-16 bar) chord loop using simple oscillators (sine/triangle) with slow attack/release envelopes — this alone is the "elevator music" trap; it is NOT the hook.
- The actual hook: a Karplus-Strong plucked-string melody riding on top, in a fixed repeating rhythmic pattern, one octave above the pad — this is what makes a synthesized loop memorable rather than ambient wallpaper. Don't skip this layer.
- A soft kick + hat pulse underneath for forward motion, quiet enough to sit under narration.
- Normalize to leave headroom, loop-length chosen so the whole progression completes on a bar boundary (no audible seam).
This is completely safe to ship commercially, but the melodic-hook layer is what separates "catchy" from "generic" — budget real iteration on it, and get a listen-and-confirm from the user before wiring it into a full render (regenerating a 15-20s loop is cheap; re-rendering the whole video to audition a different one is not).
Option B — Open-weight generative music models (more "produced," check the license every time)
- Stability AI's Stable Audio Open — open weights, text-prompted, genuinely produces full arrangements with real melodic content. License terms are more permissive than most generative-audio models but do carry revenue-based conditions — re-read the current license before any commercial use, since these terms move.
- Meta's MusicGen (via the
audiocraftlibrary) — excellent quality, but its music-model weights are typically licensed CC-BY-NC (non-commercial) — do not use generated output in a monetized product's launch video without separately clearing that. - Either can run locally (GPU recommended) or via a hosted inference endpoint (Replicate, Hugging Face Spaces) if local compute isn't available.
Option C (recommended default) — use B for the idea, ship A for the asset
Prompt an open-weight model locally for inspiration only ("catchy synth-pop hook, ~110bpm, warm optimistic tech product feel"), listen to a few gen