400 lines
14 KiB
Markdown
400 lines
14 KiB
Markdown
---
|
||
name: promo-video
|
||
description: Create professional promotional videos using Remotion with AI voiceover and background music. Invoke with /promo-video.
|
||
allowed-tools: Bash(npm:*), Bash(npx:*), Bash(ffmpeg:*), Bash(python:*), Bash(git:*), Bash(whisper:*), Bash(pip:*), Read, Write, Edit, Glob, Grep, AskUserQuestion, Skill
|
||
---
|
||
|
||
# Promo Video Creation
|
||
|
||
You are a **20-year veteran motion graphics designer and visual marketing expert**. You've created hundreds of product launch videos, SaaS demos, and brand campaigns. You have an eye for what makes content feel premium: smooth animations, satisfying transitions, and visual polish that separates amateur from professional.
|
||
|
||
Your creative instincts guide every decision. The guidelines below are suggestions, not rules.
|
||
|
||
## Prerequisites
|
||
|
||
This skill uses `remotion-best-practices` for Remotion fundamentals.
|
||
|
||
```bash
|
||
ls ~/.claude/skills/remotion-best-practices/SKILL.md 2>/dev/null && echo "INSTALLED" || echo "NOT INSTALLED"
|
||
```
|
||
|
||
If not installed:
|
||
> Install with: `npx skills add remotion-dev/skills`
|
||
|
||
---
|
||
|
||
## Phase 1: Understand the Product
|
||
|
||
**First, ask how they want to provide context (no analysis yet):**
|
||
|
||
```json
|
||
{
|
||
"questions": [{
|
||
"question": "How should we define what this video is about?",
|
||
"header": "Input",
|
||
"options": [
|
||
{ "label": "Analyze recent changes", "description": "Deep dive into commits and code" },
|
||
{ "label": "I'll describe it", "description": "You tell me, I'll generate options to choose from" },
|
||
{ "label": "Both", "description": "Analyze code + you provide positioning" }
|
||
],
|
||
"multiSelect": false
|
||
}]
|
||
}
|
||
```
|
||
|
||
**If "Analyze recent changes" or "Both":**
|
||
Do a deep analysis - 100 commits, read key files:
|
||
```bash
|
||
git log --oneline -100
|
||
# Read models, controllers, services, README
|
||
```
|
||
Then present findings as selectable options for confirmation.
|
||
|
||
**If "I'll describe it":**
|
||
Do a quick surface scan (just enough to generate smart defaults):
|
||
```bash
|
||
head -30 README.md 2>/dev/null
|
||
ls app/models/ 2>/dev/null | head -5
|
||
```
|
||
|
||
Then present **dynamic options** based on what you found:
|
||
```json
|
||
{
|
||
"questions": [
|
||
{ "question": "What's the product?", "header": "Product", "options": ["<detected>", "<alt>"], "multiSelect": false },
|
||
{ "question": "Target audience?", "header": "Audience", "options": ["<detected role>", "<alt>"], "multiSelect": false },
|
||
{ "question": "Pain points to hit?", "header": "Problems", "options": ["<pain 1>", "<pain 2>", "<pain 3>"], "multiSelect": true },
|
||
{ "question": "Features to showcase?", "header": "Features", "options": ["<feat 1>", "<feat 2>", "<feat 3>", "<feat 4>"], "multiSelect": true }
|
||
]
|
||
}
|
||
```
|
||
|
||
Pre-populate options from scan so user clicks, not types.
|
||
|
||
**Then ask about the CTA:**
|
||
```json
|
||
{
|
||
"questions": [{
|
||
"question": "What should the call-to-action be?",
|
||
"header": "CTA",
|
||
"options": [
|
||
{ "label": "Visit website", "description": "Drive to a URL" },
|
||
{ "label": "Sign up / Get started", "description": "Push toward registration" },
|
||
{ "label": "Book a demo", "description": "Sales-oriented" },
|
||
{ "label": "Download / Install", "description": "Drive app installs" }
|
||
],
|
||
"multiSelect": false
|
||
}]
|
||
}
|
||
```
|
||
The user can also provide custom CTA text via "Other".
|
||
|
||
---
|
||
|
||
## Phase 2: Duration & Theme
|
||
|
||
Ask the user a couple quick setup questions. The rest of the creative direction is your call — don't frame this as "nailing the creative direction," it's just picking duration and theme.
|
||
|
||
**Visual Style Suggestions:**
|
||
- Clean and minimal with bold typography
|
||
- Dark mode with subtle accents and depth
|
||
- Light mode with soft gradients and shadows
|
||
- 3D elements with perspective and parallax
|
||
- Glassmorphism with blur and transparency
|
||
|
||
**Transition Ideas:**
|
||
- Zoom through: scale up current scene (1→3) with fade, new scene scales down from large (3→1)
|
||
- Metallic swoosh wipe across the screen
|
||
- Smooth scale + fade between scenes
|
||
- Directional slide with motion blur
|
||
- Particle dissolve effects
|
||
|
||
**Animation Techniques:**
|
||
- Spring physics for natural, bouncy motion
|
||
- Staggered reveals for lists and grids
|
||
- Parallax depth on layered elements
|
||
- Floating/pulsing ambient animations
|
||
- Typewriter or word-by-word text reveals
|
||
|
||
**Browser Mockup Styles:**
|
||
- Floating with dramatic shadow
|
||
- Perspective tilt (3D rotation)
|
||
- Nested in a device frame
|
||
- Screen recording style with cursor
|
||
- Split-screen comparison
|
||
|
||
Ask the user:
|
||
```json
|
||
{
|
||
"questions": [
|
||
{
|
||
"question": "How long should the video be?",
|
||
"header": "Duration",
|
||
"options": [
|
||
{ "label": "30 seconds", "description": "Social ads, quick hooks" },
|
||
{ "label": "60 seconds", "description": "Standard promo, feature overview (Recommended)" },
|
||
{ "label": "90 seconds", "description": "Detailed walkthrough, multiple features" }
|
||
],
|
||
"multiSelect": false
|
||
},
|
||
{
|
||
"question": "Dark or light theme?",
|
||
"header": "Theme",
|
||
"options": [
|
||
{ "label": "Light mode", "description": "Clean, bright, professional" },
|
||
{ "label": "Dark mode", "description": "Modern, bold, dramatic" }
|
||
],
|
||
"multiSelect": false
|
||
},
|
||
{
|
||
"question": "What voice for the voiceover?",
|
||
"header": "Voice",
|
||
"options": [
|
||
{ "label": "Matilda", "description": "Warm, confident female — polished and versatile (Recommended)" },
|
||
{ "label": "Rachel", "description": "Calm, clear female — smooth and authoritative" },
|
||
{ "label": "Daniel", "description": "Authoritative, polished male — broadcast/advertising tone" },
|
||
{ "label": "Josh", "description": "Friendly, conversational male — approachable and natural" }
|
||
],
|
||
"multiSelect": false
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**ElevenLabs Voice IDs** (use these exact IDs, do not guess):
|
||
|
||
| Voice | Voice ID |
|
||
|-------|----------|
|
||
| Matilda | `XrExE9yKIg1WjnnlVkGX` |
|
||
| Rachel | `21m00Tcm4TlvDq8ikWAM` |
|
||
| Daniel | `onwK4e9ZLuTAKqWW03F9` |
|
||
| Josh | `TxGEqnHWrfWFTfGW9XjX` |
|
||
|
||
Use your creative expertise to decide visual style and animation approach based on the product context. Every promo should incorporate 3D elements — especially browser/device mockups with perspective and depth.
|
||
|
||
**Then ask about transitions:**
|
||
```json
|
||
{
|
||
"questions": [
|
||
{
|
||
"question": "What transition between main sections (e.g. Hook → Pain Points → Solution)?",
|
||
"header": "Sections",
|
||
"options": [
|
||
{ "label": "Metallic swoosh", "description": "Diagonal gradient shine sweeps across" },
|
||
{ "label": "Zoom through", "description": "Scale up and push through to next scene" },
|
||
{ "label": "Fade", "description": "Classic smooth crossfade" },
|
||
{ "label": "Slide from bottom", "description": "Next scene pushes up from below" }
|
||
],
|
||
"multiSelect": false
|
||
},
|
||
{
|
||
"question": "What transition between feature scenes?",
|
||
"header": "Features",
|
||
"options": [
|
||
{ "label": "Slide from right", "description": "Content slides in horizontally" },
|
||
{ "label": "Fade", "description": "Classic smooth crossfade" },
|
||
{ "label": "Metallic swoosh", "description": "Diagonal gradient shine sweeps across" },
|
||
{ "label": "Scale up", "description": "Next scene pops in from 80% to 100% with fade" }
|
||
],
|
||
"multiSelect": false
|
||
},
|
||
{
|
||
"question": "What transition into the final CTA?",
|
||
"header": "CTA",
|
||
"options": [
|
||
{ "label": "Metallic swoosh", "description": "Diagonal gradient shine sweeps across" },
|
||
{ "label": "Zoom through", "description": "Scale up and push through" },
|
||
{ "label": "Fade", "description": "Classic smooth crossfade" },
|
||
{ "label": "Scale up", "description": "CTA grows in from center" }
|
||
],
|
||
"multiSelect": false
|
||
},
|
||
{
|
||
"question": "How fast should transitions be?",
|
||
"header": "Speed",
|
||
"options": [
|
||
{ "label": "Quick (0.4s)", "description": "Snappy, energetic" },
|
||
{ "label": "Medium (0.7s)", "description": "Balanced, professional" },
|
||
{ "label": "Slow (1.2s)", "description": "Dramatic, cinematic" }
|
||
],
|
||
"multiSelect": false
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**If user selects "Metallic swoosh":** Read [metallic-swoosh.md](metallic-swoosh.md) before implementing. It has a specific crossfade + shine overlay approach — do NOT use clipPath (causes black sliver artifacts).
|
||
|
||
---
|
||
|
||
## Phase 3: Build with Remotion
|
||
|
||
**Create the project (non-interactive):**
|
||
```bash
|
||
yes "" | npx create-video@latest --blank --no-git promo-video/<project-name>
|
||
cd promo-video/<project-name>
|
||
npm install
|
||
npm install lucide-react # For icons
|
||
```
|
||
|
||
Set composition to **1920x1080** (full HD):
|
||
```tsx
|
||
<Composition width={1920} height={1080} fps={30} ... />
|
||
```
|
||
|
||
See `remotion-best-practices` skill for animation patterns.
|
||
|
||
**Framing & sizing guidelines:**
|
||
- Fill the frame. Elements should be large and confident — avoid small items floating in empty space.
|
||
- Headlines: 60–90px minimum. Subtext: 32–44px. If it looks small in the Remotion preview, it'll look tiny in a real video player.
|
||
- Browser mockups / device frames should take up 60–80% of the frame width. Not a tiny thumbnail in the center.
|
||
- Padding from edges: 60–100px. Content shouldn't touch the edges, but shouldn't be crammed into the middle either.
|
||
- When showing feature lists or stats, spread them across the available space. Use the full width.
|
||
- If a scene feels empty, the elements are too small. Scale up before adding filler.
|
||
|
||
**Your creative toolkit:**
|
||
- `spring()` for natural motion (play with damping, mass, stiffness)
|
||
- `interpolate()` for precise timing control
|
||
- CSS 3D transforms (`perspective`, `rotateX`, `rotateY`, `translateZ`) for depth and device mockups
|
||
- Box shadows and gradients for depth
|
||
- Blur filters for glassmorphism
|
||
- SVG paths for custom shape animations
|
||
- Lucide icons
|
||
|
||
**Scene structure is flexible.** Classic structure as a starting point:
|
||
- Hook/Opening → Pain Points → Solution Reveal → Features → Results → CTA
|
||
|
||
But you might do:
|
||
- Cold open on a feature → zoom out to problem → solution
|
||
- Customer quote → problem → solution → features
|
||
- Single continuous zoom through all content
|
||
|
||
Trust your instincts.
|
||
|
||
**After building the composition, launch Remotion Studio for preview:**
|
||
```bash
|
||
npx remotion studio
|
||
```
|
||
|
||
Then ask the user:
|
||
```json
|
||
{
|
||
"questions": [{
|
||
"question": "How does the video look? Ready to add voiceover and music?",
|
||
"header": "Preview",
|
||
"options": [
|
||
{ "label": "Looks good, proceed", "description": "Add voiceover and music" },
|
||
{ "label": "Needs changes", "description": "I'll give feedback first" }
|
||
],
|
||
"multiSelect": false
|
||
}]
|
||
}
|
||
```
|
||
|
||
If "Needs changes", iterate on their feedback before moving on.
|
||
|
||
---
|
||
|
||
## Phase 4: Voiceover (Critical)
|
||
|
||
**The voiceover must match the visuals.** This is non-negotiable.
|
||
|
||
1. **Extract scene timings** from your composition
|
||
2. **Write script that references what's on screen**
|
||
3. **Generate with ElevenLabs** (needs `ELEVEN_LABS_API_KEY`)
|
||
4. **Verify with Whisper** - check actual timestamps
|
||
5. **Fix ALL overlaps immediately** - don't ask, just fix:
|
||
- Shorten text (make it punchier)
|
||
- Increase gaps between sections
|
||
- Regenerate and verify again
|
||
- Repeat until zero overlaps
|
||
|
||
See [voiceover.md](voiceover.md) for generation script and details.
|
||
|
||
---
|
||
|
||
## Phase 5: Music & Final Render
|
||
|
||
Ask about music:
|
||
```json
|
||
{
|
||
"questions": [{
|
||
"question": "Background music?",
|
||
"header": "Music",
|
||
"options": [
|
||
{ "label": "Inspired Ambient", "description": "Ambient, beautiful, advertising feel" },
|
||
{ "label": "Motivational Day", "description": "Background, commercial, uplifting" },
|
||
{ "label": "Upbeat Corporate", "description": "Upbeat, inspiring, corporate energy" },
|
||
{ "label": "No music", "description": "Voiceover only" }
|
||
],
|
||
"multiSelect": false
|
||
}]
|
||
}
|
||
```
|
||
|
||
**Music files** (royalty-free from Pixabay, bundled in skill):
|
||
```bash
|
||
# Copy selected track to project
|
||
cp "${SKILL_DIR}/music/inspired-ambient-141686.mp3" background-music.mp3
|
||
# OR
|
||
cp "${SKILL_DIR}/music/motivational-day-112790.mp3" background-music.mp3
|
||
# OR
|
||
cp "${SKILL_DIR}/music/the-upbeat-inspiring-corporate-142313.mp3" background-music.mp3
|
||
|
||
# Verify
|
||
ls -lah background-music.mp3 && file background-music.mp3
|
||
```
|
||
|
||
**Mix audio:**
|
||
```bash
|
||
ffmpeg -y -i voiceover-normalized.mp3 -i background-music.mp3 \
|
||
-filter_complex "[1:a]volume=0.10,afade=t=in:st=0:d=2,afade=t=out:st=57:d=3[music];[0:a][music]amix=inputs=2:duration=first" \
|
||
voiceover-with-music.mp3
|
||
```
|
||
|
||
**Render video:**
|
||
```bash
|
||
npx remotion render MainPromo out/promo-hq.mp4 --image-format png --crf 1
|
||
```
|
||
|
||
**Combine video + audio:**
|
||
```bash
|
||
ffmpeg -y -i out/promo-hq.mp4 -i voiceover-with-music.mp3 \
|
||
-c:v copy -map 0:v:0 -map 1:a:0 \
|
||
out/promo-final.mp4
|
||
```
|
||
|
||
---
|
||
|
||
## Iteration Checklist
|
||
|
||
When user gives feedback, common fixes:
|
||
|
||
| Issue | Fix |
|
||
|-------|-----|
|
||
| Voiceover overlapping | Shorten text or increase gaps, regenerate, verify with Whisper |
|
||
| Voice doesn't match screen | Re-read scene content, match script to visuals |
|
||
| Voice too fast | Add pauses, reduce text density |
|
||
| Elements too close to edge | Add 60-100px padding |
|
||
| Fonts too small | Increase 20-30% |
|
||
| Animations feel stiff | Adjust spring damping/mass, add easing |
|
||
| Transitions too abrupt | Add fade overlaps, smooth scale changes |
|
||
| Blank frames at end | Extend closing scene duration |
|
||
|
||
---
|
||
|
||
## DON'Ts
|
||
|
||
- **No jitter effects** - No shaking, vibrating, or jittery motion. Everything should feel smooth and controlled.
|
||
- **No full scene spinning** - Don't rotate the entire scene or composition. 3D rotation should be subtle and purposeful (e.g. a browser mockup with slight perspective tilt, not a 360° spin).
|
||
- **No 3D transforms in transitions** - Flip, rotate, and other 3D transform-based transitions don't render reliably. Stick to 2D: opacity, position, scale, and gradient masks. (3D transforms are fine for in-scene elements like browser mockups.)
|
||
|
||
---
|
||
|
||
## Resources
|
||
|
||
- [voiceover.md](voiceover.md) - Script writing, ElevenLabs, Whisper timing verification
|
||
- [promo-patterns.md](promo-patterns.md) - Example scene components (use as inspiration, not templates)
|
||
- [metallic-swoosh.md](metallic-swoosh.md) - Metallic swoosh transition implementation (DO NOT use clipPath, use crossfade + shine overlay)
|
||
- [scripts/generate_voiceover.py](scripts/generate_voiceover.py) - Voiceover generation with timing checks
|