Narrated, captioned product-demo MP4 from a storyboard.json; re-renders itself in CI at ~$0.
Narrated, captioned product-demo MP4 from a storyboard.json; re-renders itself in CI at ~$0. The server consolidates media generation for product demos using AI agents and tooling to produce looped, captioned videos with automated CI/CD.
๐ ๏ธ Key Features
Generates narrated, captioned MP4 demos from storyboard.json
Self-reevaluating CI-based rendering at low cost
Integrates AI agents, TTS, ffmpeg, and Playwright tooling
Rich metadata through topics: ai-agents, claude-code, demo-video, product-demo, screen-recording, tts
๐ Use Cases
Automated product demos for documentation and marketing
CI-driven video rendering pipelines for rapid iteration
Captioned video generation for accessibility
โก Developer Benefits
Clear data flow from storyboard.json to final MP4
Reproducible builds in CI with low-cost rendering
Extensible with common tooling (ffmpeg, Playwright, TTS)
โ ๏ธ Limitations
Based on provided storyboard and CI environment specifics; ensure input files exist
Video quality depends on underlying AI and TTS configurations
Tell your coding agent "record a 45s demo of the checkout flow" โ get back a
polished MP4 with voiceover, synced captions, and auto-zoom. Any MCP-capable
agent (Claude Code, Codex CLI, Gemini CLI) writes one storyboard.json; the
headless engine drives a real Chrome, records a deterministic replay, voices
it, captions it, and trims the dead time. Because the replay is deterministic,
the demo re-renders itself in CI when the product changes โ no re-recording,
no API key, about $0 a render. An open-source (MIT) alternative to Screen
Studio, Clueso, or Demosmith for when you'd rather your coding agent make the
demo.
Install: Claude Code /plugin marketplace add tandryukha/aidemo ยท CI uses: tandryukha/aidemo@stable ยท CLI npx -y @tandryukha/aidemo ยท Homebrew brew install tandryukha/aidemo/aidemo Published on the GitHub Marketplace, npm, a Homebrew tap, and the MCP Registry.
Real output โ a ~51 s self-narrated tour of Wikipedia (portal search โ
Ada Lovelace โ focus-zoom โ click through to the Analytical Engine โ glide
scroll), authored by Claude from one storyboard.json and recorded as a
deterministic replay. The preview GIF is silent;
watch the full version with narration โถ.
Three ways to use it
From your coding agent โ the fastest path. In Claude Code:
/plugin marketplace add tandryukha/aidemo then
/plugin install record-demo@aidemo (bundles the skill and the MCP
server). In Codex / Gemini / any MCP agent:
npx -y github:tandryukha/aidemo#stable repo-init. Then just say
"record a 45s demo of <flow>" and the agent authors + renders it.
Locally, free & offline โ
AIDEMO_TTS_PROVIDER=local aidemo render <dir> --headless. An in-process
voice model + script-timed captions mean no API key, ~$0, fully offline.
See docs/LOCAL_MODELS.md.
In CI, self-maintaining โ drop uses: tandryukha/aidemo@stable into a
workflow. When the product changes, it replays the committed storyboard and
commits fresh media โ no key, no LLM tokens, ~$0 on free runner minutes.
See docs/CI.md.
Free & open source. MIT-licensed. Runs on GitHub's free Actions tier, or
fully local at $0 with the in-process voice โ no API key, no cloud upload, no
telemetry. Works against localhost and auth-walled apps (your own Chrome).
From one sentence to a narrated MP4
You type a sentence, the agent writes an artifact you can read and edit, the
engine records and cuts it:
1 ยท What you type โ one line to any MCP-capable agent (Claude Code here):
code
claude "record a 45s demo touring Wikipedia: search for Ada Lovelace,
open the Analytical Engine, then glide down the article"
2 ยท What the agent authors โ a plain, editable storyboard.json (excerpt:
narration + a fixed browser action-spec, side by side โ no generated code):
jsonc
{"title":"A quick tour of Wikipedia","zoom":{},// Screen-Studio-style auto-zoom"scenes":[{"id":"search","narration":"Start at the Wikipedia portal and search for Ada Lovelace.","actions":[{"op":"goto","url":"https://www.wikipedia.org/"},{"op":"type","target":{"selector":"#searchInput"},"text":"Ada Lovelace"},{"op":"click","target":{"selector":"button[type=submit]"}}]},{"id":"engine","narration":"Her notes on Babbage's Analytical Engine hold the first computer program.","actions":[{"op":"focus","target":{"selector":"#firstHeading"}},{"op":"click","target":{"selector":"a[href*='Analytical_Engine']"}},{"op":"scrollBy","dy":900,"easing":"glide"}]}]}
3 ยท How it's recorded + cut โ aidemo render drives a real Chrome (smooth
animated cursor, human-cadence typing, auto-zoom), then trims the dead time and
syncs to the narration:
4 ยท What you get โ output/final-demo.mp4, plus a README-ready GIF
(aidemo gif) and named stills (aidemo stills) from the same take. UI changed?
Re-run against the same storyboard โ no re-recording by hand.
The design goal: demos that look human-made and snappy, not like an AI
clicking around and waiting between screenshots โ by separating authoring
(slow, one-time โ figure out the flow) from recording (a fast deterministic
replay with a smooth animated cursor).
What teams render with it
GitHub README demos โ aidemo gif demos/onboarding, drop the autoplaying
GIF into the readme (the GIFs on this page are exactly that).
Landing-page hero videos โ the muted-autoplay MP4 on
aidemo.top is a rendered demo, poster frame and all.
Release / what-shipped demos โ narrate the new feature, then
gh release upload v1.4.0 demos/whats-new/output/final-demo.mp4.
Customer & prospect demos โ personalized flows against your real app:
localhost, auth walls, your own logged-in Chrome; nothing leaves the machine.
Render in CI (self-maintaining demos)
Commit a storyboard and the aidemo GitHub Action keeps its
demo media in sync โ a fresh narrated, captioned MP4 (and GIF) on every relevant
change. Deterministic replay + a local voice mean no API key, no LLM tokens,
about $0 (just free runner minutes). It's the loop a screen recorder can't
run: your demo maintains itself.
yaml
# .github/workflows/demo.yml-uses:actions/checkout@v4-run:sudoapt-getupdate&&sudoapt-getinstall-yffmpeg# ubuntu ships Chrome, not ffmpeg-uses:tandryukha/aidemo@stablewith:demos:demos/*tts:local# in-process voice โ no keys, no tokensgif:"true"
A bundled fixture store (search โ results โ cart โ checkout) that renders a
finished demo with zero external dependencies:
bash
npm install # Node 20+, system Chrome, ffmpeg on PATH
node examples/local-demo/serve.mjs # terminal 1: fixture on :8787
node bin/aidemo.mjs render examples/local-demo --headless # terminal 2
open examples/local-demo/output/final-demo.mp4 # xdg-open on Linux, start on Windows
Voice/captions need OPENAI_API_KEY in .env โ orAIDEMO_TTS_PROVIDER=local
(no key, offline), orOPENAI_BASE_URL at a local server. See
docs/LOCAL_MODELS.md. No Playwright browser download is
needed โ the engine uses your system Chrome (channel: "chrome").
The bundled fixture rendered end-to-end โ narrated, captioned, auto-trimmed.
Silent preview; full version โถ.
CLI
Each step is independently runnable and re-runnable โ regenerate voice without
re-recording, recompose without re-transcribing, etc.
bash
aidemo init <name> # scaffold demos/<name>/ with a starter storyboard
aidemo voice <dir> # per-scene TTS โ narration.mp3 + voice.json
aidemo record <dir> # drive Chrome โ raw video + timeline.json
aidemo probe <dir> # record-only dry run (verify selectors), no key needed
aidemo captions <dir> # Whisper โ captions.{srt,vtt,cues.json} (--offline for no network)
aidemo compose <dir> # trim + sync + zoom + cards + caption + mux โ final-demo.mp4
aidemo gif <dir> # final-demo.mp4 โ README-ready GIF (autoplays on GitHub)
aidemo render <dir> # voice โ record โ captions โ compose
aidemo guide # print the canonical authoring guide
aidemo doctor # check Node, ffmpeg, Chrome, voice endpoint
Add --headless for CI/fixtures; omit it for real sites that need your
logged-in session. --profile <dir> picks the Chrome user-data dir;
--capture native|obs switches to high-fidelity screen capture. voice/renderskip TTS for unchanged scenes, and recordsalvages a failed take (keeps
the footage + drops a screenshot/frame-dump in logs/).
Agent interface (MCP)
aidemo mcp runs a stdio MCP server (no network listener) exposing the engine
to any MCP client. The Claude Code plugin bundles it; aidemo repo-init registers
it agent-neutrally (.mcp.json for Claude Code, .gemini/settings.json for
Gemini; codex mcp add aidemo -- npx -y github:tandryukha/aidemo#stable mcp for
Codex).
Authoring tools โ get_authoring_guide serves
docs/AUTHORING.md version-matched from the engine (can't go
stale); get_storyboard_schema, validate_storyboard, init_demo, doctor.
Pipeline tools run as jobs โ probe/record/render/voice/captions/
compose/gif return a jobId immediately; job_status reports stage,
per-scene progress, and (on failure) the screenshot/frame-dump paths.
Why it's built this way
Deterministic replay, not an LLM in the loop. The recording runs a fixed
action-spec at full speed, so the video is smooth. The agent only authors the
storyboard (and confirms selectors once), never during capture.
Declarative action-spec + fixed player (not generated spec.ts). Safer,
editable, and it emits a timeline for free โ compose fits each scene's video
to its narration by trimming/speeding only the idle parts, freeze-holding a
static page for any remainder instead of ugly slow-motion.
Captions via overlaid PNGs, not libass. Many ffmpeg builds lack
subtitles/drawtext; aidemo rasterizes each caption with headless Chrome and
overlays it with time-gated enable โ works on any ffmpeg with overlay.
Cinematic polish is compose-time, not record-time โ a bad zoom is a
recompose, never a re-record. See docs/POLISH.md.
Deeper docs
docs/AUTHORING.md โ the canonical storyboard schema,
action vocabulary, and demo-director principles (served by the engine).
Prereqs: Node 20+, Google Chrome, ffmpeg + ffprobe on PATH.
Developed and tested on macOS; Linux works for the default (Playwright) capture
and --capture obs. Run aidemo doctor to check your setup.
bash
npm install
cp .env.example .env# add OPENAI_API_KEY, or use AIDEMO_TTS_PROVIDER=local (no key)
Project layout (per demo)
code
demos/<name>/ โ your working area (untracked; scaffold with `aidemo init`)
input/ brief.md
generated/ storyboard.json timeline.json captions.{srt,vtt,cues.json}
recordings/ raw.webm (or raw.mp4 for native/OBS capture)
audio/ scene-*.mp3 narration.mp3 voice.json
output/ final-demo.mp4
logs/ <command>.log fail-<scene>-<n>.{png,json} (on a failed action)
Security & trust
No telemetry, no analytics, no install-time scripts (package.json has no
postinstall/preinstall).
Network is user-initiated only:api.openai.com (only voice/captions,
your key โ or a local server via OPENAI_BASE_URL), api.elevenlabs.io (opt-in),
huggingface.co (download-only, once, for AIDEMO_TTS_PROVIDER=local), and
github.com (your own gh, for aidemo feedback). Recording/composing are
fully local. The MCP server is stdio-only โ no listener.
Small, auditable surface: ~20 source files, 7 runtime deps, MIT. Pin an
immutable ref if you're wary of the moving #stable tag:
npx -y github:tandryukha/aidemo#v0.8.0.
Comments on the video (pause & comment) and in-place transcript editing:
captions map to scenes, so editing a line marks that scene dirty and
aidemo voice --scene <id> + compose regenerates only the delta.
Web UI, project history, brand kits, changelog integrations.
Shipped: the GitHub Action (CI re-render), cinematic polish (auto-zoom,
scroll easing, music ducking, intro/outro cards, motion blur, post-hoc cursor
control), native/OBS capture, the agent-neutral MCP server + authoring guide,
ElevenLabs and in-process local voice providers, and the Claude Code plugin.
Contributing
Issues and PRs welcome โ see CONTRIBUTING.md for dev setup, the
smoke test, and the DCO sign-off requirement. Recording-session feedback has a fast
path: aidemo feedback demos/<name> pre-fills a structured issue.