Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
AI-native Claude Code workspace for planning, recording, voicing, and rendering explainer videos.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
CLAUDE.md
1# claude-code-video-toolkit23This file provides guidance to Claude Code (claude.ai/code) when working with this video production toolkit.45## Overview67**claude-code-video-toolkit** is an AI-native video production workspace. It provides Claude Code with the skills, commands, and tools to create professional videos from concept to final render.89**Key capabilities:**10- Programmatic video creation with Remotion (React-based)11- AI voiceover generation with ElevenLabs or Qwen3-TTS12- AI music generation with ACE-Step 1.5 (text-to-music, vocals, covers, stems)13- Browser demo recording with Playwright14- Asset processing with FFmpeg1516## Directory Structure1718```19claude-code-video-toolkit/20├── .claude/21│ ├── skills/ # Domain knowledge for Claude22│ └── commands/ # Guided workflows23├── tools/ # Python CLI automation24├── templates/ # Video templates25│ ├── sprint-review/ # Sprint review video template26│ └── product-demo/ # Marketing/product demo template27├── brands/ # Brand profiles (colors, fonts, voice)28├── projects/ # Your video projects go here (gitignored)29├── examples/ # Curated showcase projects (shared)30├── assets/ # Shared assets (voices, images)31├── playwright/ # Browser recording infrastructure32├── docs/ # Documentation33└── _internal/ # Toolkit metadata & registry34```3536## Registry3738`_internal/toolkit-registry.json` is the canonical source for all skills, commands, tools, templates, components, transitions, and cloud endpoints — including their paths, status, options, presets, and env vars. Consult it for structured data. This file focuses on **workflow guidance, patterns, and knowledge** that the registry can't capture.3940## Quick Start4142**First-time setup (optional, ~5 minutes):**43```44/setup45```4647Walks through cloud GPU, file transfer (R2), and voice configuration. Most features are free. Skip this if you just want to render videos with Node.js.4849**Work on a video project:**50```51/video52```5354This command will:551. Scan for existing projects (resume or create new)562. Choose template (sprint-review, product-demo)573. Choose brand (or create one with `/brand`)584. Plan scenes interactively595. Create project with VOICEOVER-SCRIPT.md6061**Multi-session support:** Projects span multiple sessions. Run `/video` to resume where you left off. Each project tracks its phase, scenes, assets, and session history in `project.json`.6263**Or manually:**64```bash65cp -r templates/sprint-review projects/my-video66cd projects/my-video67npm install68npm run studio # Preview69npm run render # Export70```7172> **Note:** After creating or modifying commands/skills, restart Claude Code to load changes.7374## Templates7576Templates live in `templates/`. Most are standalone Remotion projects; concept-explainer-short is pure Python. See registry `templates` section for the full list.7778### sprint-review79Config-driven sprint review videos with theme system, config-driven content (`sprint-config.ts`), pre-built slides (Title, Overview, Summary, Credits), demo components (single video, split-screen), and audio integration.8081### product-demo82Marketing/product demo videos with dark tech aesthetic, scene-based composition (title, problem, solution, demo, stats, CTA), animated background, Narrator PiP, browser/terminal chrome, and stats cards with spring animations.8384### concept-explainer-short859:16 vertical concept-explainer shorts (TikTok/Reels/YouTube Shorts). **Python/moviepy, not Remotion** — the whole video derives from `scenes.json` (per-scene narration + visual asset). Pipeline: `gen_vo.py` (per-scene TTS via voiceover.py, clone or built-in, `--max-wpm` pacing clamp) → `gen_captions.py` (whisper word timing force-aligned to script text, needs `pip install openai-whisper`) → `build.py` (audio-anchored composite: Ken Burns on stills, boomerang-looped clips, burned karaoke caption pills, ducked music). Renders at every stage — placeholder cards before assets, silent before audio. Visuals follow the FLUX/Ideogram/LTX split: Ideogram cards at `1440x2560` for anything text-bearing, LTX b-roll at `576x1024` for motion.8687## Brand Profiles8889Brands live in `brands/`. Each defines visual identity:9091```92brands/my-brand/93├── brand.json # Colors, fonts, typography94├── voice.json # ElevenLabs voice settings95└── assets/ # Logo, backgrounds96```9798See `docs/creating-brands.md` for details.99100## Shared Components101102Reusable video components in `lib/components/`. See registry `components` section for the full list with descriptions. Import in templates via:103104```tsx105import { AnimatedBackground, SlideTransition, Label } from '../../../../lib/components';106```107108## Python Tools109110Audio, video, and image tools in `tools/`. See registry `tools` section for the full catalog with descriptions, options, presets, and env vars. Every tool supports `--help`.111112```bash113# Setup114pip install -r tools/requirements.txt115```116117**Important: always invoke tools from the toolkit root directory.** When working inside a project (`projects/my-video/`), tool paths like `python3 tools/upscale.py` will fail because `tools/` is relative. Always use:118```bash119cd /path/to/claude-code-video-toolkit && python3 tools/upscale.py ...120```121This is especially critical for background commands where the working directory may not be obvious.122123### Tool Categories124125| Type | Tools | When to Use |126|------|-------|-------------|127| **Project tools** | voiceover, music, music_gen, sfx, sync_timing | During video creation workflow |128| **Utility tools** | redub, addmusic, notebooklm_brand, locate_watermark | Quick transformations on existing videos |129| **Cloud GPU** | image_edit, upscale, dewatermark, sadtalker, qwen3_tts, music_gen, flux2 | AI processing via RunPod or Modal (`--cloud runpod\|modal`) |130131Utility tools work on any video file without requiring a project structure.132133### Voiceover Generation134135```bash136# Per-scene generation (recommended)137python tools/voiceover.py --scene-dir public/audio/scenes --json138139# Using Qwen3-TTS (self-hosted, free alternative to ElevenLabs)140python tools/voiceover.py --provider qwen3 --tone warm --scene-dir public/audio/scenes --json141142# Single file (legacy)143python tools/voiceover.py --script SCRIPT.md --output out.mp3144```145146### Timing Sync (after voiceover)147148```bash149python3 tools/sync_timing.py # Dry run comparison150python3 tools/sync_timing.py --apply # Update config (1s default padding)151python3 tools/sync_timing.py --apply --padding 1.5 # Custom padding152python3 tools/sync_timing.py --voiceover-json vo.json # Use voiceover.py output153python3 tools/sync_timing.py --json # Machine-readable output154```155156### Qwen3-TTS (Standalone)157158```bash159python tools/qwen3_tts.py --text "Hello world" --speaker Ryan --output hello.mp3160python tools/qwen3_tts.py --text "Hello world" --tone warm --output hello.mp3161python tools/qwen3_tts.py --text "Hello" --instruct "Speak enthusiastically" --output excited.mp3162python tools/qwen3_tts.py --text "Hello" --ref-audio sample.wav --ref-text "transcript" --output cloned.mp3163python tools/qwen3_tts.py --list-voices # 9 speakers: Ryan, Aiden, Vivian, etc.164python tools/qwen3_tts.py --list-tones # neutral, warm, professional, excited, etc.165```166167Temperature controls expressiveness: `--temperature 1.2` (more expressive) or `--temperature 0.4` (more consistent).168169### Cloud GPU Providers170171All cloud GPU tools support two providers via `--cloud runpod|modal`. RunPod is the default. Modal was added as a reliability fallback after RunPod outages, and offers faster cold starts.172173```bash174# --- RunPod setup (automated, one-time per tool) ---175echo "RUNPOD_API_KEY=your_key_here" >> .env176python tools/image_edit.py --setup177python tools/upscale.py --setup178python tools/qwen3_tts.py --setup179python tools/music_gen.py --setup180181# --- Modal setup (deploy each app you need) ---182pip install modal && python3 -m modal setup183modal deploy docker/modal-upscale/app.py # Then save URL to .env184modal deploy docker/modal-image-edit/app.py185# See docs/modal-setup.md for full guide186```187188### AI Image Generation (FLUX.2 vs Ideogram 4)189190The toolkit has **two** text-to-image generators. They barely overlap — the deciding factor is191**whether the image needs legible baked-in text**.192193```bash194# FLUX.2 — text-FREE backgrounds + image editing (self-hosted, free, Apache-2.0/commercial-OK)195python tools/flux2.py --preset title-bg --brand digital-samba # background for Remotion text overlay196python tools/flux2.py --prompt "Abstract tech background, no text"197198# Ideogram 4 — legible IN-IMAGE text + exact color/layout (hosted API, ~$0.03-0.09/img, commercial-OK)199python3 tools/ideogram4.py --json caption.json --output title.png # text baked into the image200python3 tools/ideogram4.py --prompt "Thumbnail: 'SHIP FASTER' bold" --output thumb.png201```202203**The key distinction — baked-in text vs. background-for-overlay:**204205- **FLUX.2 presets deliberately produce text-*free* backgrounds** (`title-bg`, `cta`, `thumbnail`206all end with "no text, no words, no letters"). The intended pattern is **FLUX background →207Remotion renders the text on top**, so the text stays editable, animatable per-letter, and208frame-accurate. This is the right default for sprint-review **title cards / lower-thirds**.209- **Ideogram 4 bakes legible designed text *into* a flat PNG.** Pixel-perfect typography + exact210hex colors in one shot, but static. Reach for it when **the text *is* the design**: YouTube/social211thumbnails (static anyway), quote/stat cards, in-scene signage/logos, stylized text effects that212Remotion overlays can't easily do. It fills a real gap — FLUX and LTX-2 both garble in-image text.213214| Need | Use |215|------|-----|216| Animated/editable title text, lower-thirds, sprint-review title cards | **FLUX.2 bg + Remotion text** |217| Atmospheric/abstract backgrounds, problem/solution illustrations, presenter backdrops | **FLUX.2** presets |218| Finished graphic where typography is the design — thumbnails, quote cards, in-scene signage | **Ideogram 4** |219| Edit an existing photo (clothing, reframe, style, background) | **image_edit** (neither generator edits) |220221Ideogram 4 chains with the processors like any generator: `ideogram4 → upscale.py` (crisp 4K),222`ideogram4 → ltx2.py --input` (animate the still), or drop the PNG straight into Remotion `<Img>`.223Ideogram 4 is generate-only here (no editing). See `.claude/skills/ideogram4/` for the JSON caption224format — Claude authors the caption as the "magic prompt" expander; needs `IDEOGRAM_API_KEY` in `.env`.225226### AI Image Editing227228```bash229230# Image editing (Qwen-Image-Edit)231python tools/image_edit.py --input photo.jpg --prompt "Add sunglasses"232python tools/image_edit.py --input photo.jpg --prompt "Add sunglasses" --cloud modal233python tools/image_edit.py --input photo.jpg --style cyberpunk234python tools/image_edit.py --input photo.jpg --background office235python tools/image_edit.py --list-presets # Full preset list236237# Upscaling (RealESRGAN)238python tools/upscale.py --input photo.jpg --output photo_4x.png --cloud runpod239python tools/upscale.py --input photo.jpg --scale 2 --model anime --face-enhance --cloud runpod240```241242See `docs/qwen-edit-patterns.md` and `.claude/skills/qwen-edit/` for prompting guidance.243244### AI Music Generation (ACE-Step 1.5)245246Default provider is **acemusic** (official cloud API, free key from [acemusic.ai/api-key](https://acemusic.ai/api-key)). Uses XL Turbo 4B model with 5Hz LM thinking mode. Falls back to Modal/RunPod for self-hosted 2B model.247248```bash249# Background music (acemusic cloud API by default)250python tools/music_gen.py --prompt "Upbeat tech corporate" --duration 60 --bpm 128 --key "G Major" --output music.mp3251252# Generate 4 variations, pick the best253python tools/music_gen.py --prompt "Subtle corporate tech" --duration 60 --variations 4 --output bg.mp3254255# Fast mode (disable thinking)256python tools/music_gen.py --no-thinking --prompt "Quick draft" --duration 30 --output draft.mp3257258# Scene presets for video production259python tools/music_gen.py --preset corporate-bg --duration 60 --output bg.mp3260python tools/music_gen.py --preset tension --duration 20 --output problem.mp3261python tools/music_gen.py --preset cta --brand digital-samba --output cta.mp3262263# Song with vocals and lyrics (use structure tags for sections)264python tools/music_gen.py \265--prompt "Indie pop anthem, male vocal, bright guitar, studio polish" \266--lyrics "[Verse]\nWalking through the morning light\nCoffee in my hand feels right\n\n[Chorus - anthemic]\nWE KEEP MOVING FORWARD\nThrough the noise and doubt\n\n[Outro - fade]\n(Moving forward...)" \267--duration 60 --bpm 128 --key "G Major" --output song.mp3268269# Cover / style transfer270python tools/music_gen.py --cover --reference theme.mp3 --prompt "Jazz piano version" --output cover.mp3271272# Repaint a weak section (acemusic only)273python tools/music_gen.py --repaint --input track.mp3 --repaint-start 15 --repaint-end 25 --prompt "Guitar solo" --output fixed.mp3274275# Continue from existing audio (acemusic only)276python tools/music_gen.py --continuation --input track.mp3 --prompt "Continue with jazz piano" --output extended.mp3277278# Stem extraction279python tools/music_gen.py --extract vocals --input mixed.mp3 --output vocals.mp3280281# Fall back to self-hosted282python tools/music_gen.py --cloud modal --prompt "Background music" --duration 60 --output bg.mp3283284# List presets285python tools/music_gen.py --list-presets286```2872888 scene presets: `corporate-bg`, `upbeat-tech`, `ambient`, `dramatic`, `tension`, `hopeful`, `cta`, `lofi`. See `.claude/skills/acestep/` for prompt engineering patterns and video production integration guide.289290### Watermark Removal291292```bash293# Locate watermark coordinates294python tools/locate_watermark.py --input video.mp4 --grid --output-dir ./review/295python tools/locate_watermark.py --input video.mp4 --preset notebooklm --verify296297# Remove watermark (RunPod)298python tools/dewatermark.py --input video.mp4 --region 1080,660,195,40 --output clean.mp4 --runpod299python tools/dewatermark.py --setup # One-time setup300```301302**Workflow:** grid overlay → note coordinates → verify with `--region` → remove with dewatermark.303304**Local mode** requires NVIDIA GPU (8GB+ VRAM). Mac users should use `--runpod`.305306### Talking Head Generation (SadTalker)307308```bash309# Basic usage310python tools/sadtalker.py --image portrait.png --audio voiceover.mp3 --output talking.mp4311312# For NarratorPiP integration (recommended settings)313# CRITICAL: --preprocess full preserves image dimensions (otherwise outputs square crop)314python tools/sadtalker.py \315--image presenter_16x9.png \316--audio voiceover.mp3 \317--preprocess full --still --expression-scale 0.8 \318--output narrator.mp4319```320321**Key flags for NarratorPiP:**322- `--preprocess full` — **Critical!** Preserves input dimensions (default `crop` outputs square)323- `--still` — Reduces head movement for professional look324- `--expression-scale 0.8` — Calmer expression (default 1.0)325326**Image requirements:** Face 30-70% of frame, front-facing, 16:9 for NarratorPiP, 512px+ recommended.327328See `docs/sadtalker.md` for detailed options and troubleshooting.329330### Redub Sync Mode331332```bash333python tools/redub.py --input video.mp4 --voice-id VOICE_ID --sync --output dubbed.mp4334```335336The `--sync` flag enables word-level time remapping — essential when TTS voice pacing differs from original. Without it, audio can drift 3-4+ seconds by the end.337338**How it works:** Scribe transcribes original → TTS generates new audio with timestamps → segment mapping (15 words/segment) → FFmpeg variable speed per segment.339340### NotebookLM Branding341342Post-processes NotebookLM videos with custom branding. Solves the problem where redubbed TTS audio extends beyond the safe visual trim point.343344```bash345python tools/notebooklm_brand.py \346--input video_synced.mp4 \347--logo assets/logo.png \348--url "mysite.com" \349--output video_final.mp4350```351352Trims NotebookLM visuals, keeps full audio, bridges with freeze frame, adds branded outro.353354## Video Production Workflow3553561. **Create/resume project** - Run `/video`, choose template and brand (or resume existing)3572. **Review script** - Edit `VOICEOVER-SCRIPT.md` to plan content3583. **Gather assets** - Record demos with `/record-demo` or add external videos3594. **Scene review** - Run `/scene-review` to verify visuals in Remotion Studio3605. **Design refinement** - Use `/design` or the "Refine" option in scene-review to improve slide visuals3616. **Generate audio** - Use `/generate-voiceover` for AI narration3627. **Sync timing** - Run `python3 tools/sync_timing.py --apply` to update config durations3638. **Preview** - `npm run studio` in project directory3649. **Iterate** - Adjust timing, content, styling with Claude Code36510. **Render** - `npm run render` for final MP4366367## Project Lifecycle368369Projects move through phases tracked in `project.json`:370371```372planning → assets → review → audio → editing → rendering → complete373```374375| Phase | Description |376|-------|-------------|377| `planning` | Defining scenes, writing script |378| `assets` | Recording demos, gathering materials |379| `review` | Scene-by-scene review in Remotion Studio (`/scene-review`) |380| `audio` | Generating voiceover, music |381| `editing` | Adjusting timing, previewing |382| `rendering` | Final render in progress |383| `complete` | Done |384385See `lib/project/README.md` for details on the project system.386387## Video Timing388389Timing is critical. Keep these guidelines in mind:390391### Pacing Rules392- **Voiceover drives timing** — Narration length determines scene duration393- **Reading pace** — ~150 words/minute (2.5 words/second) for standard narration394- **Demo pacing** — Real-time demos often need 1.5-2x speedup (`playbackRate`)395- **Transitions** — Add 1-2s padding between scenes396- **FPS** — All videos use 30fps (frames = seconds × 30)397398### Speaking Rate Tiers399400| Pace | WPM | Use When |401|------|-----|----------|402| Slow | 120-130 | Technical explanations, complex concepts |403| Standard | 140-160 | General narration, demos, overviews |404| Fast | 160-180 | Energetic intros, recaps, CTAs |405406### Narration Density by Scene Type407408| Scene Type | Duration | Narration Density | Notes |409|------------|----------|-------------------|-------|410| Title | 3-5s | 0-10% | Logo + headline, let visuals breathe |411| Overview | 10-20s | 70-90% | 3-5 bullet points, narration-heavy |412| Demo | 10-30s | 30-50% | Let the demo speak, narrate key moments only |413| Stats | 8-12s | 70-90% | Read out highlights, skip obvious numbers |414| Credits | 5-10s | 0-20% | Quick fade, maybe a closing line |415| Problem/Solution | 10-15s | 80-90% | Narration drives the story |416| CTA | 5-10s | 60-80% | Clear call to action, leave a beat at end |417418### Word Count Budgeting419420Before writing scripts, budget words per scene:421422```423Target duration × 2.5 = word budget (at standard pace)424Pause seconds × 2.5 = words to subtract from budget425426Example: 15s scene with a 1s pause42715 × 2.5 = 37 words budget4281 × 2.5 = 3 words for pause429Available: ~34 words of narration430```431432Use `[pause 1.0s]` markers in scripts. Each second of pause costs ~2-3 words from the budget.433434### Timing Calculations435```436Script words ÷ 150 = voiceover minutes (estimate)437Raw demo length ÷ playbackRate = demo duration438Sum of scenes + transitions = total video439```440441### When to Check Timing442- **During scene planning** — Budget word counts per scene before writing443- **After writing script** — Count words per scene, compare to budget444- **After generating audio** — Run `sync_timing.py` to compare actual vs estimated445- **Before rendering** — Ensure `durationInFrames` matches actual audio for each scene446447### TTS Duration Drift (The Real Timing Problem)448449TTS engines do NOT consistently produce 150 WPM output. In practice:450- **ElevenLabs** tends to compress pauses and speed through short sentences. A 50s script may produce 40-45s of audio.451- **Qwen3-TTS** varies by speaker and tone preset. Ryan at "professional" tone speaks ~10% faster than "warm."452- **Short scenes drift more** — a 5-second scene might be off by 30%, while a 30-second scene is off by 10%.453454**The feedback loop after TTS generation:**4554561. Generate per-scene audio files4572. Run `python3 tools/sync_timing.py` to compare actual vs config durations4583. Run `python3 tools/sync_timing.py --apply` to update config automatically4594. For demo scenes: recalculate `playbackRate = rawDemoDuration / actualNarrationDuration`4605. Re-preview in Remotion Studio before rendering461462**Common drift patterns and fixes:**463464| Problem | Symptom | Fix |465|---------|---------|-----|466| Audio shorter than scene | Dead air / awkward silence at end | Reduce `durationInFrames` to match audio |467| Audio longer than scene | Narration cut off | Increase `durationInFrames` or trim script |468| Demo too fast for narration | Viewer can't follow | Decrease `playbackRate` or cut narration |469| Demo too slow for narration | Waiting for demo to catch up | Increase `playbackRate` (1.5-2x typical) |470| Pauses lost in TTS | Script felt spacious, audio feels rushed | Add explicit `<break time="1s"/>` in SSML or extend scene padding |471| Cloned voice rushes | Scenes land >170 wpm; retakes also fast (temperature doesn't help) | Pace is inherited from the reference audio. Use `--max-wpm 165` (pitch-preserving atempo clamp, both voiceover.py and qwen3_tts.py), and record clone references as 12-25s of varied sentences *at narration pace* |472473**Pacing QC:** voiceover.py and qwen3_tts.py report `wpm` and a `pacing` label474(fast/slow/ok) per generated file — check these before composition. Comfortable475narration is 140-160 wpm; flag anything over ~170. `--max-wpm` turns the check476into an automatic fix.477478### Fixing Mismatches479- **Voiceover too long**: Speed up demos, trim pauses, cut content480- **Voiceover too short**: Slow demos, add scenes, expand narration481- **Demo too long**: Increase `playbackRate` (1.5x-2x typical)482- **Demo too short**: Decrease `playbackRate`, or loop/extend483484### Audio-Anchored Timelines (the prevention approach)485486`sync_timing.py` is reactive — it fixes drift after the fact. You can prevent drift entirely by **generating the audio first, then anchoring visuals to known timestamps** instead of estimating durations upfront.487488**The pattern:**4894901. Write the script and split into per-scene segments4912. Generate per-scene VO files: `voiceover.py --scene-dir public/audio/scenes --json`4923. Read the actual durations from the JSON output4934. Anchor every visual element to absolute timestamps in the timeline494495This is especially clean for Python/moviepy builds where each clip carries its own `start=` parameter:496497```python498# Audio-anchored scene timeline (25s total):499# Scene 1 tired 0.3 → 3.74 (audio 3.44s)500# Scene 2 worries 4.0 → 8.88 (audio 4.88s)501# Scene 3 introduce 9.1 → 11.90 (audio 2.80s)502503text_clip("TIRED OF", start=0.5, duration=1.2)504text_clip("THIRD-PARTY", start=1.0, duration=1.8)505vo_clip("01_tired.mp3", start=0.3)506vo_clip("02_worries.mp3", start=4.0)507```508509The comment block at the top is the source of truth. Every `start=` references it. Drift is impossible because durations aren't being estimated — they're being read from the rendered audio.510511**Trade-off vs. `<Series>`-style auto-chaining:**512513| Approach | Best for | Downside |514|----------|----------|----------|515| Audio-anchored absolute starts | Tight ad-style edits, sub-30s spots, anything with exact timing | Manual bookkeeping when re-timing a scene |516| `<Series>` / auto-chained durations | Long-form sprint reviews where adjacent scenes flex | Drift compounds across the timeline; needs `sync_timing.py` to recover |517518For Remotion projects you can mix the two: use `<Sequence from={...}>` with absolute frames for tight sections and let `<Series>` handle the rest. For pure-Python builds (`build.py` + moviepy), audio-anchored is the natural default.519520## Key Patterns521522### Animations (Remotion)523```tsx524const frame = useCurrentFrame();525const opacity = interpolate(frame, [0, 20], [0, 1], { extrapolateRight: 'clamp' });526```527528### Sequencing529```tsx530<Series>531<Series.Sequence durationInFrames={150}><TitleSlide /></Series.Sequence>532<Series.Sequence durationInFrames={900}><DemoClip /></Series.Sequence>533</Series>534```535536### Media537538**Never use a raw HTML `<video>` tag** — Remotion requires its own component for frame-accurate rendering.539540The toolkit's templates use `<OffthreadVideo>` and `<Audio>` from the `remotion` package. Stick with these for consistency with existing templates. Upstream Remotion now also documents `<Video>` and `<Audio>` from the newer `@remotion/media` package (see `.claude/skills/remotion-official/`) — those add trim props, pitch shifting via `toneFrequency`, and richer loop behavior. Migrate per-template only if you need those features; both APIs render correctly.541542```tsx543<OffthreadVideo src={staticFile('demo.mp4')} />544<Audio src={staticFile('voiceover.mp3')} volume={1} />545<Audio src={staticFile('music.mp3')} volume={0.15} />546```547548## Scene Transitions549550The toolkit includes a transitions library at `lib/transitions/`. See registry `transitions` section for the full list with options and best-use descriptions.551552### Using TransitionSeries553554```tsx555import { TransitionSeries, linearTiming } from '@remotion/transitions';556import { glitch, lightLeak, zoomBlur } from '../../../lib/transitions';557558<TransitionSeries>559<TransitionSeries.Sequence durationInFrames={90}>560<TitleSlide />561</TransitionSeries.Sequence>562<TransitionSeries.Transition563presentation={glitch({ intensity: 0.8 })}564timing={linearTiming({ durationInFrames: 20 })}565/>566<TransitionSeries.Sequence durationInFrames={120}>567<ContentSlide />568</TransitionSeries.Sequence>569</TransitionSeries>570```571572### Transition Options Examples573574```tsx575glitch({ intensity: 0.8, slices: 8, rgbShift: true }) // Tech/cyberpunk576lightLeak({ temperature: 'warm', direction: 'right' }) // Warm celebration577zoomBlur({ direction: 'in', blurAmount: 20 }) // High energy578rgbSplit({ direction: 'diagonal', displacement: 30 }) // Chromatic aberration579```580581### Timing Functions582583```tsx584linearTiming({ durationInFrames: 30 }) // Constant speed585springTiming({ config: { damping: 200 }, durationInFrames: 45 }) // Physics bounce586```587588### Transition Duration Guidelines589590| Type | Frames | Notes |591|------|--------|-------|592| Quick cut | 10-15 | Fast, punchy |593| Standard | 20-30 | Most common |594| Dramatic | 40-60 | Slow reveals |595| Glitch effects | 15-25 | Should feel sudden |596| Light leak | 30-45 | Needs time to sweep |597598Preview all transitions: `cd showcase/transitions && npm run studio`599600See `lib/transitions/README.md` for full documentation.601602## Design Refinement with frontend-design Skill603604The `frontend-design` skill elevates slide visuals from generic to distinctive.605606### Usage607- **During scene review** (`/scene-review`): Choose "Refine" for visual improvements608- **Focused sessions** (`/design`): Deep-dive on a specific scene — `/design title`, `/design cta`609610### When to Use611- Slide scenes that feel generic612- When building visual contrast between scenes (e.g., calm title → harsh problem)613- When animations feel too basic or too busy614615### Visual Narrative Arc616Consider how visual intensity builds across scenes:617- **Title**: Set the mood, plant visual seeds618- **Problem**: Create tension (harsh contrast)619- **Solution**: Relief and hope return620- **Demo**: Neutral, content-focused621- **Stats**: Build credibility622- **CTA**: Climax - maximum visual energy623624## Toolkit vs Project Work625626**Toolkit work** (evolves the toolkit itself):627- Skills, commands, templates, tools628- Tracked in `_internal/ROADMAP.md`629630**Project work** (creates videos):631- Lives in `projects/`632- Each project has `project.json` (machine-readable state) and auto-generated `CLAUDE.md`633634Keep these separate. Don't mix toolkit improvements with video production.635636## Documentation637638- `docs/getting-started.md` - First video walkthrough639- `docs/creating-templates.md` - Build new templates640- `docs/creating-brands.md` - Create brand profiles641- `docs/optional-components.md` - Setup for optional ML-based tools (ProPainter, etc.)642