A reproducible video-tutorial factory for a web platform's mini-app
Onboarding videos that rebuild themselves: a browser walks the mini-app, ElevenLabs narrates, and one command produces three clips, a full film, thumbnails, and publish-ready copy.
Context
A consumer platform lives or dies on activation: a user who cannot figure out the mini-app in the first minutes churns before paying. Onboarding video is the standard answer, but the standard production chain — hand recording, booth narration, timeline editing — produces an artifact that goes stale the moment the interface changes. For a product in active development, that means re-hiring the whole chain every sprint.
The pedagogy is its own problem: a broad, non-technical audience means no product jargon, plain words, short sentences, a large caption for every line and framing cards on each clip. The real task was therefore not a video but a factory — a reproducible pipeline where the script is the source of truth and the entire deliverable regenerates on command.
The task
Produce a publish-ready onboarding kit: three topic clips — an overview, a how-to and a credits explainer — plus a stitched full film, all at 1080p, with thumbnails and YouTube copy, showing the real working mini-app rather than slides. The script needed a review pass from multiple perspectives — an older viewer, a non-native speaker, a fact-checker — so the language is genuinely clear rather than clear-to-the-author.
Above all, the deliverable is a capability, not a file: when the interface or the wording changes, the kit must re-shoot and re-assemble itself, ruling out manual editing and any timeline the next person would have to relearn.
Approach
One script file, videos.json, defines each clip as segments — narrator text, on-screen titles, what the frame shows — and everything downstream derives from it. Playwright walks the live mini-app in a phone-sized viewport with a visible cursor, recording raw footage and a scene map; where a live walk is fragile, HTML copies of the cabinet and operations screens are rendered with real data.
Voice and captions are generated, not performed: ElevenLabs synthesizes narration cached per file so unchanged lines are not re-billed; faster-whisper aligns the audio to word-level timings that drive the subtitle overlays; a cue pass renders a PNG per spoken line with the relevant buttons highlighted, plus intro and outro cards. An ffmpeg builder composites everything into the phone frame, normalizes loudness to −14 LUFS and stitches the film. Editing a line is a script edit and a re-run.
Architecture
The line is a chain of named stages, each its own command: record (Playwright capture), screens (data-filled HTML stills), tts (cached ElevenLabs narration), subs (faster-whisper word timings), cues (per-line highlight PNGs and cards), build (ffmpeg compositing, titles, subtitles, promo intro, loudnorm to −14 LUFS — three 1080p clips), film (MPEG-TS stitch), then thumbs and deliver (named videos, thumbnails and publish copy in one folder). npm run all runs the whole chain in order.
The pedagogy is enforced by the toolchain, not operator diligence: plain-language copy, per-line subtitles sourced from the actual audio alignment and framing cards are structural stages, so no clip ships without them; the multi-perspective script review happens upstream of any rendering.
Result
One script run produces the complete kit: three 1080p clips, a stitched 3:13 film — overview 0:45, how-to 1:42, credits 0:46 — thumbnails and publish copy, all normalized to −14 LUFS and named for delivery.
The asset for the client is the pipeline itself. When the mini-app changes, the kit rebuilds with a single command — no re-shoot, no editor, no timeline — and caching keeps re-runs cheap: an edit to one line re-bills only that line's narration. The deliverable is reproducible and always one command away from current.
What we built
Script as source of truth
videos.json defines each clip as segments — narrator text, on-screen titles, what the frame shows. Every downstream stage derives from it; editing a line is a script edit plus a re-run.
Browser-driven capture
Playwright walks the live mini-app in a phone viewport with a visible cursor and a load wait, producing raw footage and a scene map; fragile live states are stood in by HTML screen copies rendered with real data.
Cached voiceover
ElevenLabs synthesizes the narration, cached per file so unchanged lines aren't re-billed on a re-run.
Word-aligned subtitles
faster-whisper aligns the audio to word-level timings and exact text, driving precise per-line subtitle overlays.
Cue and card pass
A Playwright pass renders a PNG per spoken line with the relevant buttons highlighted in yellow, plus intro and outro framing cards.
Assembly as code
An ffmpeg builder composites footage and screens into a phone frame, adds branded backgrounds and titles, overlays subtitles, concatenates, and normalizes to −14 LUFS — outputting three 1080p clips.
Film, thumbnails, delivery kit
An MPEG-TS stitch joins the clips into one film; thumbnails and a delivery folder with named videos and YouTube copy are generated last. npm run all runs the whole chain.
Engineering challenges
A tutorial that goes stale on every sprint
A hand-recorded, hand-edited video is dead the moment the interface changes. The whole line is script-driven and reproducible: change videos.json, run one command, and the kit re-shoots and re-assembles itself.
Plain language for a broad audience
The audience is non-technical, so jargon like "generations" and "credits" is out. The copy uses plain words and is reviewed from several perspectives — an older viewer, a non-native speaker, a fact-checker — before any rendering.
Subtitles that match the actual audio
Hand-timed captions drift. faster-whisper aligns subtitles to the real narration at word level, so every line's caption matches what is actually said.
Cheap re-runs
Re-synthesizing all narration on every edit is slow and costly. ElevenLabs output is cached per file, so editing one line re-bills only that line and leaves the rest untouched.