Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use for CLI and terminal demo videos where synthetic rendering is better than live capture. Covers Remotion TerminalScene authoring, pacing to narration, and when to use real screen recording instead.
.claude/skills/video-production-buddy-synthetic-screen-recording/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 70% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 46% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 71% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 33% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 145% | 0% |
Decision this skill answers: When the user wants a screen-recording-looking demo of a terminal, CLI tool, or coding workflow — do I capture the real desktop (OS screen recording via screen_recorder, Windows-MCP, Cap, or Playwright), or do I synthesize it in Remotion with the TerminalScene component?
> Heuristic: If the agent can author the exact command/output sequence in advance, synthesize. Only capture live when the real behavior is unpredictable, needs a real app UI, or the user explicitly asked for a real recording.
v3 of the Video Production Buddy showcase tried to use Windows-MCP + screen_recorder to drive a Git-Bash window for the install walkthrough. It stalled on window positioning, focus races, and taskbar privacy concerns. We pivoted to pure Remotion rendering — a React component named TerminalScene that draws a fake terminal and types commands character-by-character. The output is visually indistinguishable from a real screen recording (same traffic-light window chrome, blinking cursor, scrolling output) but deterministic, privacy-safe, pixel-perfect at 1080p, and pace-controllable to the frame.
That component + pattern is the capability this skill makes discoverable.
YES, synthesize when:
make targets, git clone flowsNO, capture a real screen when:
For a browser demo → playwright-recording skill, not this one. For a real desktop → screen_recorder tool or Cap via cap_recorder.
TerminalSceneLocated at: remotion-composer/src/components/TerminalScene.tsx Exported from: remotion-composer/src/components/index.ts Wired in dispatch: remotion-composer/src/Explainer.tsx (if (cut.type === "terminal_scene"))
Props:
tsinterface TerminalSceneProps { title?: string; // shown in the window title bar steps: TerminalStep[]; // the timeline prompt?: string; // "$", ">", etc. accentColor?: string; // pill + prompt glow backgroundColor?: string; }
Step kinds:
ts{ kind: "cmd", text: string, typeSpeed?: number, holdSeconds?: number } { kind: "out", text: string, holdSeconds?: number } { kind: "pause", seconds: number } { kind: "pill", text: string, color?: string, durationSeconds?: number }
cmd — prints the prompt, types the text character-by-character (typeSpeed is seconds per character, default 0.035), then holds for holdSeconds (default 0.3)out — a line of program output, reveals instantly with a short fade-inpause — dead time. Terminal holds on last visible state. USE THIS TO SYNC WITH NARRATION.pill — non-blocking floating badge (top-right). Spring-in, hold, spring-out. Does NOT advance the cursor — the next step runs in parallel.Author a new scene by adding a cut to build_composition.py (or your equivalent props builder):
pythoninstall_steps = [ {"kind": "pause", "seconds": 7.0}, # wait for intro narration {"kind": "cmd", "text": "git clone https://github.com/calesthio/Video Production Buddy.git", "typeSpeed": 0.045, "holdSeconds": 0.3}, {"kind": "out", "text": "Cloning into 'Video Production Buddy'..."}, {"kind": "out", "text": "remote: Enumerating objects: 2847, done."}, {"kind": "pill", "text": "repo cloned", "color": "#34D399", "durationSeconds": 2.6}, {"kind": "pause", "seconds": 3.8}, # bridge to next narration cue # ... ] cuts.append({ "id": "install-terminal", "type": "terminal_scene", "terminalTitle": "bash — Video Production Buddy setup", "prompt": "$", "accentColor": "#22D3EE", "steps": install_steps, "in_seconds": 50.0, "out_seconds": 110.0, })
The #1 failure mode: steps run continuously and burn through all content in the first 40% of the scene, leaving the terminal frozen for the remaining 60%. This is what killed the v3 first pass — the capability menu rendered at t=80s but narration didn't announce it until t=92s.
Do this instead:
cmd should start typing the moment narration says its line, not before.Sanity-check your steps before rendering — every minute of Remotion render is precious. Sum the step durations and verify they equal scene duration:
pythonimport math def trace(steps, scene_start, fps=30): t = 0.0 for s in steps: k = s["kind"] if k == "cmd": tf = math.ceil(len(s["text"]) * s.get("typeSpeed", 0.035) * fps) t += tf / fps + s.get("holdSeconds", 0.3) elif k == "out": t += max(2, math.ceil(0.08 * fps)) / fps + s.get("holdSeconds", 0.15) elif k == "pause": t += s["seconds"] # "pill" is non-blocking — does NOT advance cursor print(f" {t + scene_start:6.2f}s {k}: {s.get('text', '')[:40]}") trace(install_steps, 50)
Look at the output column. Each narration cue's video-time must appear adjacent to the command/output it announces. If a command lands 10s before or after its cue, adjust pauses.
See lib/verify_scene_pacing.py for a reusable version of this script.
repo cloned immediately after the last Receiving objects line). Pills are your substitute for real-world UI notifications.holdSeconds ≥ 0.3 on every cmd so viewers register the completed command before the first output scrolls in.holdSeconds on output lines between 0.4 and 1.0. Output that flies too fast feels like a bug; output that crawls feels boring.ProviderChip (companion component)The .agents/skills/synthetic-screen-recording pattern also owns ProviderChip — a rotating badge overlay that cycles through a list of provider names at a fixed cadence. Used in the v3 showcase to cycle through all 11 AI video-gen providers during the "generated motion" section.
pythonoverlays.append({ "type": "provider_chip", "providers": ["Veo 3.1", "Seedance 2.0", "Kling 2.5", ...], "cycleSeconds": 2.5, "position": "bottom-right", "accentColor": "#22D3EE", "label": "generated with", "in_seconds": 195.0, "out_seconds": 222.5, })
Wired in dispatch at: remotion-composer/src/Explainer.tsx overlay renderer (overlay.type === "provider_chip").
The pattern generalizes. When you need to fake another UI surface (Claude Code chat bubbles, a Jira ticket view, a GitHub PR diff, a Slack message, a VS Code status bar):
TerminalScene.tsx as a template.steps interface for the relevant timeline primitives.frame against cumulative start/end times.Explainer.tsx's SceneRenderer dispatch with a new cut.type.Cut interface in Explainer.tsx and to components/index.ts.remotion-composer/SCENE_TYPES.md with the new cut type..agents/skills/remotion — general Remotion authoring (hooks, springs, sequences).agents/skills/playwright-recording — real browser-flow capture for web appstools/capture/screen_recorder — ffmpeg-based desktop capturetools/capture/cap_recorder — Cap.so polished desktop captureskills/pipelines/screen-demo/asset-director.md — chooses between synthetic and real for a screen-demo projectIntroduced: Video Production Buddy showcase v3 render (2026-04-16). Original motivation: the v3 setup walkthrough section needed a 60-second install demo where every command aligned to Chirp 3 HD narration cues, and Windows-MCP-driven real capture was too flaky in practice. See projects/video-production-buddy-showcase/build_composition.py for the reference implementation.
Other measured skills in the registry, with their headline benchmark lift.