--- name: remotion description: AI video production workflow using Remotion. Use when creating videos, short films, commercials, or motion graphics. Triggers on requests to make promotional videos, product demos, social media videos, animated explainers, or any programmatic video content. Produces polished motion graphics, not slideshows. --- # Video Generator (Remotion) ## Workflow 1. **Scaffold** the project in `output//`: ```bash cd output && npx --yes create-video@latest --template blank cd && npm install && npm install lucide-react @remotion/google-fonts ``` 2. **Copy the template library** into the project: ```bash cp -r /templates/src/lib/ src/lib/ ``` This gives the project `src/lib/utils.ts`, `palette.ts`, `backgrounds.tsx`, `text.tsx`, `ui.tsx`, `effects.tsx`, `transitions.tsx`, and `themes/` — all ready to import. 3. **Fix package.json scripts** — replace any `bun` references with `npx remotion`: ```json { "prepare:tts": "node scripts/generate-tts-manifest.mjs", "dev": "npx remotion studio", "build": "npx remotion bundle" } ``` 4. **Choose a theme** based on the video's tone (see Theme Guide below), then **customize `src/lib/palette.ts`** to match. 5. **Write the narration script** — one sentence per scene, sentence order = scene order. 6. **Generate TTS** — copy `scripts/generate-tts-manifest.mjs` from `references/inworld-tts.md`, update the `SENTENCES` array, then: ```bash npm run prepare:tts ``` This produces `public/audio/tts/*.mp3` and `src/tts-manifest.json` with measured durations. 7. **Build all scenes** — each scene imports from `src/lib/` and `src/tts-manifest.json`. Never hardcode durations. 8. **Start Remotion Studio**: ```bash cd output/ && npm run dev ``` User opens `http://localhost:3000` to preview. Hot-reloads on save. ### Fast iteration ```bash REUSE_EXISTING_AUDIO=1 npm run prepare:tts # skip re-synthesis ``` ### Render (only when user explicitly asks) ```bash npx remotion render CompositionName out/video.mp4 ``` ## Template Library (`src/lib/`) Every project gets these files copied in at scaffold time. **Import from them — do not rewrite the code inline.** | File | Exports | When to use | |---|---|---| | `utils.ts` | `lerp`, `EASE`, `SPRING` | Every scene. `lerp` replaces raw `interpolate`. `EASE.out` for entrances, `EASE.in` for exits, `EASE.inOut` for moves. | | `palette.ts` | `C` | Every scene. Never use inline hex colors — always `C.accent`, `C.muted`, etc. | | `backgrounds.tsx` | `BokehBackground`, `WaveBackground`, `Starfield`, `FloatingShapes` | Persistent layer outside `` blocks. Choose one per video. | | `text.tsx` | `TextReveal`, `WordReveal`, `NeonFlickerText`, `GlitchText`, `Typewriter` | Headlines use `TextReveal`. Subtitles use `WordReveal`. Tech scenes use `Typewriter` or `GlitchText`. Bold/edgy scenes use `NeonFlickerText`. | | `ui.tsx` | `FeatureCard`, `StatsDisplay`, `CTAButton`, `TerminalWindow`, `StaggeredList` | List scenes → `StaggeredList`. Enumeration → `FeatureCard` with staggered `delay`. Stats → `StatsDisplay`. Endings → `CTAButton`. Code → `TerminalWindow`. | | `effects.tsx` | `RadialExplosion`, `Blob`, `Scanlines`, `GridBackground`, `PerspectiveGrid` | Reveal moments → `RadialExplosion`. Liquid/organic → `Blob`. Retro/VHS → `Scanlines`. Tech/HUD → `GridBackground` or `PerspectiveGrid`. | | `layouts.tsx` | `FullscreenType`, `MultiColumn`, `SplitContrast`, `GiantNumber`, `Asymmetric`, `FrameInFrame` | Scene structure. Choose a layout first, then fill with content components. See Layout Guide. | | `transitions.tsx` | `CircleReveal`, `ColorWipe` | Wrap scene content for entrance transitions. | | `themes/*.tsx` | 12 visual themes (see Theme Guide) | Choose one per video based on tone. Use as scene backgrounds or style reference. | ## Theme Guide Choose one theme per video based on the content's tone. Import from `src/lib/themes/`. Each theme accepts `{ startDelay?: number }`. | Theme | Tone | Best for | Key visual | |---|---|---|---| | `ThemeDarkMode` | Professional, clean | SaaS, dev tools, product demos | Subtle purple glow, card UI, dark gradient | | `ThemeTech` | Clean, startup | Pitch videos, app launches, SaaS | Logo, CTA buttons, SVG line chart, light bg | | `ThemeCyberpunk` | Edgy, tech | Gaming, hacker, sci-fi | Neon cyan/magenta, perspective grid, scanlines, glitch text | | `ThemeNeon` | Bold, nightlife | Music, events, entertainment | Neon signs on brick wall, multi-glow text, flicker | | `ThemeMinimalist` | Restrained, elegant | Editorial, architecture, literary | White bg, thin type, single underline, maximum whitespace | | `ThemeMonochrome` | Dramatic, contrasty | Documentary, photography | Black/white split, animated block reveal | | `ThemeGlassmorphism` | Modern, polished | App promos, UI showcases | Frosted glass card, purple-pink gradient, blur | | `ThemeLuxury` | Premium, refined | High-end brands, luxury products | Black + gold, thin frame, extreme letter-spacing | | `ThemeNeobrutalism` | Bold, energetic | Startups, Gen-Z brands | Thick borders, hard shadows, bright fills, tilted | | `ThemeCosmic` | Expansive, wonder | Sci-fi, astronomy, futuristic | Stars, gradient planet with ring, shooting star | | `ThemeGradient` | Vibrant, dynamic | Social media, music, festivals | Rotating multi-stop gradient, large centered text | | `ThemeRetro` | Warm, nostalgic | Vintage brands, craft, artisan | Sepia, SVG noise texture, vignette, diamond ornament | **Usage:** Themes define the visual identity — background, typography treatment, color palette, decorative elements. Use a theme's style to inform scene design, or render the theme component directly as a background/intro layer. ```tsx import { ThemeCyberpunk } from "./lib/themes"; // As a background layer in a scene: {/* Scene content overlaid on top */} ``` ## Layout Guide Every scene needs a **layout** — the spatial arrangement of elements on screen. Choose a layout before choosing text/UI components. | Layout | Structure | Best for | Key props | |---|---|---|---| | `FullscreenType` | Staggered masked text lines filling the screen | Hook statements, bold claims, chapter titles | `lines: {text, color?}[]`, `fontSize`, `subtitle` | | `MultiColumn` | Header + N equal columns with spring stagger | Process steps, feature lists, pricing, timelines | `columns: {number?, title, desc}[]`, `heading`, `label`, `lightBg` | | `SplitContrast` | Two-panel clipPath reveal (dark left, light right) | Before/after, problem/solution, old/new | `left: {label, heading}`, `right: {label, heading, accentWord?}` | | `GiantNumber` | Oversized stat number + supporting text | KPIs, data highlights, statistics | `number`, `label`, `heading`, `accentWord`, `body`, `lightBg` | | `Asymmetric` | 70/30 split — giant text left, metadata right | Hero statements, title cards, bold openers | `line1`, `line2`, `line2Color`, `metadata: string[]` | | `FrameInFrame` | Nested animated borders with corner accents | Product reveals, chapter markers, premium intros | `heading`, `label`, `footnote` | All layouts accept `frame`, `startDelay`, and handle their own entrance animations. They render full-screen (`AbsoluteFill`) and include backgrounds. **Usage:** Import a layout, pass content props, and layer additional components (text animations, effects) on top if needed. ```tsx import { GiantNumber } from "./lib/layouts"; ``` ### Layout selection rules - **No two adjacent scenes should use the same layout** - Match layout to the sentence archetype (see mapping below) - Layouts handle backgrounds — don't stack a layout inside another background | Archetype | Primary layout | Alternative | |---|---|---| | Hook / bold claim | `FullscreenType` | `Asymmetric` | | Enumeration / process | `MultiColumn` | — | | Contrast / choice | `SplitContrast` | — | | Stats / data | `GiantNumber` | — | | Product reveal / intro | `FrameInFrame` | `Asymmetric` | | Title card / chapter | `Asymmetric` | `FullscreenType` | For archetypes not listed (list, code, CTA), use a neutral dark background and layer content components from `ui.tsx` and `text.tsx` directly. ## Scene Architecture ### Timing from TTS manifest ```tsx import manifest from "./tts-manifest.json"; const sceneDurationFrames = (i: number, fps: number) => Math.ceil((manifest[i].durationMs / 1000) * fps); ``` Set `durationInFrames` on the Composition from the manifest sum. Never hardcode frame counts. ### Video structure ```tsx ``` Use `Series` with negative `offset` for overlapping scene transitions. ### Scene component pattern Every scene should: 1. Import from `src/lib/` — not reimplement animation logic 2. Accept timing from the manifest — not hardcode durations 3. Include its own `