demo
Record a narrated demo video of a web app. Opens the URL, explores it while screencast recording, writes narration, and renders a polished video.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Record a narrated demo video of a web app. Opens the URL, explores it while screencast recording, writes narration, and renders a polished video.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
| name | demo |
| description | Record a narrated demo video of a web app. Opens the URL, explores it while screencast recording, writes narration, and renders a polished video. |
| disable-model-invocation | true |
| argument-hint | <url> [--login <email:password>] [--brief <"what to show">] [--name <name>] [--duration <seconds>] |
| allowed-tools | Bash, Read, Write, Glob, Grep, Agent, mcp__chrome-devtools__new_page, mcp__chrome-devtools__navigate_page, mcp__chrome-devtools__click, mcp__chrome-devtools__fill, mcp__chrome-devtools__type_text, mcp__chrome-devtools__press_key, mcp__chrome-devtools__hover, mcp__chrome-devtools__wait_for, mcp__chrome-devtools__take_screenshot, mcp__chrome-devtools__take_snapshot, mcp__chrome-devtools__screencast_start, mcp__chrome-devtools__screencast_stop, mcp__chrome-devtools__evaluate_script, mcp__chrome-devtools__list_pages, mcp__chrome-devtools__select_page, mcp__chrome-devtools__resize_page |
You are creating a narrated demo video of a web application. The entire flow — exploration, recording, narration, and rendering — happens in this single command.
Parse from $ARGUMENTS:
--login <credentials>: Login credentials in email:password format. If provided, log in before recording.--brief <"what to show">: Natural language description of what the demo should cover. Can be very short — "show the dashboard and create a project" is enough. If omitted, explore freely.--name <name>: Output name (default: derived from URL hostname)--duration <seconds>: Target video duration (default: 60)--voice <voice>: TTS voice (default: en-US-GuyNeural)--preset <draft|production>: Quality preset (default: draft)Arguments can also be passed as natural language after the URL. All of these are equivalent:
/demo https://app.com --login admin@test.com:pass123 --brief "show the billing page and add a payment method"
/demo https://app.com — log in as admin@test.com / pass123, show billing and add a payment method
/demo https://app.com login: admin@test.com pass123. Show the billing page.
Parse what you can. If the user gives you credentials and instructions in plain English, use them.
Before recording, understand what you're working with:
new_page or navigate_page--login), find the login form and sign in first. Look for common patterns: /login, /sign-in, a "Sign In" link, etc. Use fill for email/password fields, then click submit. Wait for the dashboard/home page to load before continuing.logo.png (or .svg/.webp). During scouting, save it to a temp location first, then move it into the final output dir once the unique name is resolved. Use evaluate_script to find the logo <img> src URL, then use Bash curl or wget to save it. The pipeline will auto-detect it and use it in the intro card.accentColor in narration.json (rgba format).--brief), use it to guide your exploration. The brief tells you what the user cares about — prioritize those features. If no brief, explore freely.duration seconds of narrationThink about what makes a compelling demo:
screencast_startSet up the output directory and start recording:
Output dir: screencast-output/<name>/
Recording: screencast-output/<name>/recording.mp4
screencast-output/<name>/ already exists. If it does, append an incrementing suffix: <name>-v2, <name>-v3, etc. Use the first available name. For example:
# Check and find next available name
NAME="trafficstores"
DIR="screencast-output/$NAME"
if [ -d "$DIR" ]; then
V=2; while [ -d "screencast-output/${NAME}-v${V}" ]; do V=$((V+1)); done
NAME="${NAME}-v${V}"
DIR="screencast-output/$NAME"
fi
mkdir -p "$DIR"
Use the resolved <name> (with suffix if needed) for ALL subsequent paths in this run — recording, narration.json, composition, render output, etc.screencast_start with path screencast-output/<name>/recording.mp4screencast_stop when doneRecording tips:
Write screencast-output/<name>/narration.json based on what you just recorded. You know exactly what happened because you did it.
{
"introTagline": "Short punchy headline",
"introSubtitle": "Product or company name",
"outroHeading": "Call to action question",
"outroUrl": "website.com",
"outroCtaText": "Get Started",
"accentColor": "rgba(59, 130, 246, 1)",
"captionStyle": "pop",
"voice": "en-US-AndrewNeural",
"introLogoSrc": "screencast-output/<name>/logo.png",
"segments": [
{
"text": "Narration for this segment. Write conversationally, like a human presenting.",
"sceneIndex": 0,
"sceneLabel": "Feature Name"
}
],
"fullText": "All segment texts joined with spaces."
}
Narration guidelines:
--duration targetaccentColor should match the app's brand color (pick from what you saw)sceneLabel becomes an animated lower third in the video — keep them short (2-3 words max): "Sign Up", "AI Builder", "Live Website"introLogoSrc to the logo file you downloaded in Phase 1 — it shows with a spring animation in the intro cardcaptionStyle to match the app's feel: "pop" (bouncy, playful), "clean" (frosted glass, elegant), "bold" (large, punchy), "minimal" (subtle), "karaoke" (no background), or "outline" (glow shadow)voice that matches the app's tone:
en-US-AndrewNeural — Warm, confident (good default)en-US-BrianNeural — Approachable, casual (startups, friendly apps)en-US-ChristopherNeural — Reliable, authoritative (enterprise, fintech)en-US-AriaNeural — Positive, confident (marketing, consumer apps)en-US-EmmaNeural — Cheerful, clear (e-commerce, social)en-US-AvaNeural — Expressive, caring (health, wellness, community)en-US-JennyNeural — Friendly, considerate (education, support)en-US-EricNeural — Rational (analytics, data tools)en-US-GuyNeural — Passionate (creative tools, media)en-GB-RyanNeural / en-GB-SoniaNeural — British (international, luxury)Write a custom Remotion composition for this specific video. Save it as screencast-output/<name>/composition.tsx. The pipeline will use it instead of the default MarketingDemo template.
Load the Remotion skills first: Read the rules from demo-render/.agents/skills/remotion-best-practices/rules/ — especially animations.md, timing.md, text-animations.md, transitions.md, and sequencing.md.
Your composition must:
VideoComposition (the React component) and calculateMarketingDemoDuration (duration function)MarketingDemoProps type (re-export from ./MarketingDemo)Available building blocks (import from ./components/):
DeviceMockup — Screen recording in browser chrome (videoSrc, accentColor, displayUrl, zoomRegions, layout)IntroCard / OutroCard — Default intro/outro templates (tagline, subtitle, accentColor, logoSrc)WordHighlightCaptions — Word-by-word captions (wordTimings, style, accentColor)LowerThird — Scene label overlay (label, accentColor, leftOffset)ProgressBar — Progress indicator (accentColor)AudioWaveform — Audio-reactive visualizer (variant, accentColor, samples)FeatureCallout — Annotation callout (label, side, y, accentColor)ChapterCard — Scene divider card (chapterNumber, title, accentColor)Presenter — 2D character with lip sync (mouthCues, side)AvatarPip — Avatar picture-in-pictureSceneBreak — Brief visual flash at scene boundariesYou can also write custom components inline in the composition file.
Design decisions to make per video:
Template literal example for composition.tsx:
import React from "react";
import { AbsoluteFill, Audio, Sequence, interpolate, staticFile } from "remotion";
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
// Import building blocks
import { DeviceMockup } from "./components/DeviceMockup";
import { WordHighlightCaptions } from "./components/WordHighlightCaptions";
import { ProgressBar } from "./components/ProgressBar";
// Import your custom intro/outro (write them inline or as separate components)
// Import types
import type { MarketingDemoProps } from "./MarketingDemo";
export type { MarketingDemoProps };
export function calculateMarketingDemoDuration(props: MarketingDemoProps) {
return props.introDurationFrames + props.videoDurationFrames + props.outroDurationFrames - 20;
}
// Your custom intro component (inline)
const MyIntro: React.FC<{...}> = (...) => { ... };
export const VideoComposition: React.FC<MarketingDemoProps> = (props) => {
// Your unique composition layout here
};
Remotion rules to follow:
useCurrentFrame() — NO CSS transitions/animationsinterpolate() for keyframes, spring() for physics motionstaticFile() for assets in demo-render/public/<Sequence from={frame}> to delay elements<TransitionSeries> for scene transitionsTemplate mode: For a series of consistent videos (e.g. how-to series), save the composition to a shared template folder and set "template": "path/to/template-folder" in narration.json. Every video in the series will use that composition.
Run the autodemo pipeline to produce the final video:
node scripts/autodemo.mjs \
--script /dev/null \
--narration screencast-output/<name>/narration.json \
--output final-output/<name>.mp4 \
--output-dir screencast-output/<name> \
--skip-record \
--voice <voice>
Note: --skip-record tells the pipeline to use existing recordings in the output dir. The pipeline handles:
Report to the user:
final-output/<name>.mp4final-output/<name>-compressed.mp4 (auto-generated by pipeline)screencast-output/<name>/bundle-*/The pipeline prints a summary table with all of this. Just relay it to the user.
introVideoSrc/outroVideoSrc in narration.json to override.