Communitygithub.com

Demo to Promo Reel: Screen Studio-style web app demo

Turn your real web app into a smooth Screen Studio-style demo MP4: scripted headless 60 fps capture, spring auto-zoom camera, re-rendered cursor, padded stage, subtitles and callouts, plus a poster frame. One CLI, everything scripted in files, real footage instead of screenshots.

What is Demo to Promo Reel: Screen Studio-style web app demo?

Demo to Promo Reel recipe, step 1 (the real-footage demo), from dr-osmanovich/webapp-screencast. Install the CLI with pip from GitHub plus Playwright Chromium; Node 22+ and ffmpeg handle rendering, and `doctor` lists every failing check with its fix. The agent first reads the app's README and components to find the run command, seed data, test accounts, a reset path and stable selectors; it never records production or real customer data. It plans 3–5 beats (hook, action, result, detail, end; 15–30 s), writes scenario.py and plan.py, records a headless 60 fps take and edits it with spring auto-zoom, a re-rendered cursor, a padded stage, subtitles and callouts into OUT/<name>.mp4 (1920×1080) with a poster JPG. Every CLI call returns JSON, so the agent verifies each step instead of guessing.

Works with~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/dr-osmanovich/webapp-screencast/tree/HEAD/skills/webapp-screencast

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

webapp-screencast

You script the take, webapp-screencast records it and edits it. Output: OUT/<name>.mp4 (1920×1080, 60 fps) plus a poster .jpg. Everything is a file you write (scenario.py, plan.py) and one CLI. Always call the CLI with --json (before the subcommand): stdout is one JSON object (ok, error, paths, durations, warnings); progress goes to stderr. Exit 0 ok, 1 step failed, 2 bad input.

API and plan keys: reference.md. Read it before writing scenario.py / plan.py.

0. Setup (once per machine)

webapp-screencast --json doctor

If webapp-screencast is missing: pip install git+https://github.com/dr-osmanovich/webapp-screencast.git (use the project's venv if it has one), then python -m playwright install chromium. doctor lists each failing check with its fix. Node 22+ and ffmpeg are required for rendering.

1. Understand the app (before any recording)

  • Find how it runs locally (README, package.json scripts, Makefile, docker-compose) and its URL. A plain static folder can be served by webapp-screencast itself (make --serve DIR).
  • Find demo/seed data and test accounts in the repo (fixtures, seed scripts, .env.example). Never record production, real customer or patient data, or real credentials. If no safe demo data exists, stop and ask the user.
  • Find how to reset state (seed/reset script, clearing localStorage). Every take starts clean.
  • Pick 3–5 beats that show the value: hook → action → result → one detail → end. 15–30 s of footage.
  • Read the actual components to get stable selectors (ids, data-testid, roles). Don't guess.

2. Scaffold and script

webapp-screencast --json init video/ --base-url http://127.0.0.1:3000 --title "Product name"

Write video/scenario.py: CONFIG, optional login(page, cfg) and prepare(page, cfg), and run(take, page). Rules that save retakes:

  • take.mark("name") at every beat; take.box("name", selector) (or click(..., name=)) for everything the camera or a callout should frame. Always mark hook first and end last.
  • Wait for the app with page.wait_for_selector(...) after actions, then take.hold(0.3–0.8).
  • Park the pointer away from text before take.type(...); type at cps 25–35.
  • In prepare() hide toasts, cookie banners, dev overlays; close side panels.
  • Native title= tooltips never render headless — use a plan callout instead.

3. Record and inspect

webapp-screencast --json record video/scenario.py --out video/out/footage [--base-url URL]
webapp-screencast --json inspect video/out/footage

Check peak_fps ≥ 50 on busy beats (lower on macOS → GPU flags issue, see reference) and that every mark you planned is present. A failed selector raises a Playwright error on stderr: fix the scenario and record again — footage is cheap (≈ take length + 10 s).

4. Plan, compose, look

Write video/plan.py using the marks and boxes inspect printed (never hard-code seconds): camera segments that follow the action (zoom 1.4–1.7 on the beat, back to 1.0 between scenes), one short subtitle per beat (≥ 0.3 s per word, no overlaps), intro/outro cards.

webapp-screencast --json compose video/plan.py --footage video/out/footage --out video/out/composition
webapp-screencast --json snapshot video/out/composition --at 1,5,9,14 --out video/out/stills

Fix every warnings entry. Look at the stills (read the PNGs / contact sheet): text readable, camera on the action, nothing cropped, no subtitle covering the thing it describes. Iterate on plan.py with compose + snapshot only — no need to record again.

5. Render and deliver

Render takes ~4–5 min per 20 s on an M1 — run it in the background with a log file.

webapp-screencast --json render video/out/composition --out video/out/video.mp4
webapp-screencast --json poster video/out/video.mp4 --at 9.0

Confirm the JSON shows fps: 60 and the expected duration. Hand over the mp4 + poster paths. .gitignore the out/ dir; commit scenario.py + plan.py so the video can be re-made after UI changes.

One-shot when scenario and plan are already good: webapp-screencast --json make video/scenario.py video/plan.py --out video/out --base-url URL --poster-at 9 (--serve DIR for static sites, --skip-render to stop after the check).

With /brag (or another launch-video skill)

Brag decides the story; webapp-screencast supplies real footage.

  1. Run brag's own planning: concept, tone, beats, title, copy. Stop before it builds screenshot scenes.
  2. Turn brag's beats into scenario.py marks (one mark per beat) and record.
  3. Put brag's lines into plan.py: hook → intro.title, beat captions → subtitles, closing line / CTA → outro; map brag's tone to look (polished → graphite/ocean, playful → sunset/violet, accent = the app's brand colour from its CSS).
  4. Compose, snapshot, render as above into brag's output folder; then let brag write the share copy. Landscape 16:9 only for now; if brag asked for vertical, say so and render landscape.

Related Skills