Remotion Video Generator
by @zendenho7
AI video production workflow using Remotion. Use when creating videos, short films, commercials, or motion graphics. Triggers on requests to make promotional...
clawhub install remotion-video-generatorπ About This Skill
name: remotion-video-generator 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. version: "1.0.0" metadata: {"openclaw":{"emoji":"π¬","requires":{"bins":["node","npm","python3"]}, "tags":["video", "remotion", "motion-graphics", "production"]}}
Remotion Video Generator
> "Create professional motion graphics videos programmatically with React and Remotion."
Credits & References
Original Skill
Modifications
scrapling library instead of Firecrawl APICore Technologies
Tested With
Quick Usage Guide (Step-by-Step)
Step 1: Scrape Brand Data
# Run the scrapling script to get brand colors, logo, tagline
bash skills/remotion-video-generator/scripts/scrapling.sh "https://brand-website.com"
This extracts: brandName, tagline, logoUrl, faviconUrl, primaryColors, ogImageUrl, screenshotUrl
Step 2: Download Brand Assets
mkdir -p public/images/brand
curl -sL "https://brand.com/logo.svg" -o public/images/brand/logo.svg
curl -sL "https://brand.com/og-image.png" -o public/images/brand/og-image.png
curl -sL "https://image.thum.io/get/width/1200/crop/800/https://brand.com" -o screenshot.png
Step 3: Create Project Structure
mkdir -p my-video/src my-video/public/images/brand my-video/public/audio
Step 4: Create package.json
{
"name": "my-video",
"scripts": {
"dev": "npx remotion studio",
"build": "npx remotion bundle"
},
"dependencies": {
"@remotion/cli": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"remotion": "^4.0.0",
"lucide-react": "^0.300.0"
}
}
Step 5: Install Dependencies
cd my-video && npm install
Step 6: Create Video Component
Createsrc/MyVideo.tsx with:
Step 7: Create Entry Point (Remotion v4 API)
Createsrc/index.tsx - MUST use .tsx extension:import { registerRoot, Composition } from "remotion";
import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring } from "remotion";const MyVideo = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// Animations - ALWAYS pass fps to spring()
const scale = spring({ frame, fps, from: 0.8, to: 1 });
return (
Hello World
);
};
registerRoot(() => {
return (
);
});
β οΈ CRITICAL Remotion v4 Rules:
1. Use .tsx extension (NOT .ts) for files with JSX
2. MUST use registerRoot + Composition API
3. ALWAYS pass fps to spring(): spring({ frame, fps, from: 0.8, to: 1 })
4. Use useVideoConfig() to get fps: const { fps } = useVideoConfig()
5. Render with composition name: npx remotion render MyVideo out/video.mp4
Step 8: Start Dev Server
cd my-video && npm run dev
Server runs on http://localhost:3000Step 9: Preview & Iterate
Step 10: Render Final Video (when user asks)
npx remotion render index out/final-video.mp4
Credits
Installation
# Install Remotion globally
npm install -g remotionInstall dependencies for video projects
npm install lucide-reactInstall Scrapling (already in workspace skills)
pip install scrapling
Agent Instructions
When to Use Video Generator
Use this skill when:
Do NOT use for:
Default Workflow (ALWAYS follow this)
1. Scrape brand data (if featuring a product) using Scrapling (NOT Firecrawl)
2. Create the project in output/
3. Build all scenes with proper motion graphics
4. Install dependencies with npm install
5. Fix package.json scripts to use npx remotion (not bun):
"scripts": {
"dev": "npx remotion studio",
"build": "npx remotion bundle"
}
6. Start Remotion Studio as a background process:
cd output/ && npm run dev
7. Expose via Cloudflare tunnel so user can access:
bash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000
8. Send the user the public URL (e.g. https://xxx.trycloudflare.com)The user will preview in their browser, request changes, and you edit the source files. Remotion hot-reloads automatically.
Rendering (only when user explicitly asks to export)
cd output/
npx remotion render CompositionName out/video.mp4
Quick Start
# Scaffold project
cd output && npx --yes create-video@latest my-video --template blank
cd my-video && npm installAdd motion libraries
npm install lucide-reactFix scripts in package.json (replace any "bun" references with "npx remotion")
Start dev server
npm run devExpose publicly
bash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000
Fetching Brand Data with Scrapling
MANDATORY: When a video mentions or features any product/company, use Scrapling to scrape the product's website for brand data, colors, screenshots, and copy BEFORE designing the video. This ensures visual accuracy and brand consistency.
Using the Scrapling Script
# Run the brand data extraction script
bash skills/remotion-video-generator/scripts/scrapling.sh "https://example.com"
This returns structured brand data: brandName, tagline, headline, description, features, logoUrl, faviconUrl, primaryColors, ctaText, socialLinks, plus screenshot URL and OG image URL.
Manual Scrapling Extraction
If the script isn't available, use Python directly:
import json
from scrapling.fetchers import StealthyFetcher
from urllib.parse import urljoin
import reurl = 'https://brand.com'
page = StealthyFetcher.fetch(url, headless=True)
html = page.text
def resolve(u):
return urljoin(url, u) if u and not u.startswith('http') else u
colors = list(set(re.findall(r'#(?:[0-9a-fA-F]{3}){1,2}', html)))[:5]
data = {
'brandName': page.css('[property="og:site_name"]::text').get() or page.title(),
'tagline': page.css('[property="og:description"]::text').get(),
'headline': page.css('h1::text').get(),
'description': page.css('[property="og:description"]::text').get(),
'logoUrl': resolve(page.css('[rel="icon"]::attr(href)').get()),
'faviconUrl': resolve(page.css('[rel="icon"]::attr(href)').get()),
'primaryColors': colors,
'ctaText': page.css('a[href*="signup"]::text').get(),
'ogImageUrl': resolve(page.css('[property="og:image"]::attr(content)').get()),
'screenshotUrl': f"https://image.thum.io/get/width/1200/crop/800/{url}"
}
print(json.dumps(data, indent=2))
Download Assets After Scraping
mkdir -p public/images/brand
curl -s "https://example.com/favicon.ico" -o public/images/brand/favicon.ico
curl -s "${OG_IMAGE_URL}" -o public/images/brand/og-image.png
curl -sL "${SCREENSHOT_URL}" -o public/images/brand/screenshot.png
Note: Some S3 buckets block direct access. Use thum.io screenshot service as fallback.
Core Architecture
Scene Management
Use scene-based architecture with proper transitions:
const SCENE_DURATIONS: Record = {
intro: 3000, // 3s hook
problem: 4000, // 4s dramatic
solution: 3500, // 3.5s reveal
features: 5000, // 5s showcase
cta: 3000, // 3s close
};
Video Structure Pattern
import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring, Img, staticFile, Audio } from "remotion";export const MyVideo = () => {
const frame = useCurrentFrame();
const { fps, durationInFrames } = useVideoConfig();
return (
{/* Background music */}
{/* Persistent background layer - OUTSIDE sequences */}
{/* Scene sequences */}
);
};
Motion Graphics Principles
AVOID (Slideshow patterns)
PURSUE (Motion graphics)
npm install lucide-react) β never emojiTransition Techniques
| Technique | Description | |-----------|-------------| | Morph/Scale | Element scales up to fill screen, becomes next scene's background | | Wipe | Colored shape sweeps across, revealing next scene | | Zoom-through | Camera pushes into element, emerges into new scene | | Clip-path reveal | Circle/polygon grows from point to reveal | | Persistent anchor | One element stays while surroundings change | | Directional flow | Scene 1 exits right, Scene 2 enters from right | | Split/unfold | Screen divides, panels slide apart | | Perspective flip | Scene rotates on Y-axis in 3D |
Animation Timing Reference
// Timing values (in seconds)
const timing = {
micro: 0.1-0.2, // Small shifts, subtle feedback
snappy: 0.2-0.4, // Element entrances, position changes
standard: 0.5-0.8, // Scene transitions, major reveals
dramatic: 1.0-1.5, // Hero moments, cinematic reveals
};// Spring configs
const springs = {
snappy: { stiffness: 400, damping: 30 },
bouncy: { stiffness: 300, damping: 15 },
smooth: { stiffness: 120, damping: 25 },
};
Visual Style Guidelines
Typography
Colors
Layout
Remotion Essentials
Interpolation
const opacity = interpolate(frame, [0, 30], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp"
});const scale = spring({
frame,
fps,
from: 0.8,
to: 1,
durationInFrames: 30,
config: { damping: 12 }
});
Sequences with Overlap
Cross-Scene Continuity
Place persistent elements OUTSIDE Sequence blocks:
const PersistentShape = ({ currentScene }: { currentScene: number }) => {
const positions = {
0: { x: 100, y: 100, scale: 1, opacity: 0.3 },
1: { x: 800, y: 200, scale: 2, opacity: 0.5 },
2: { x: 400, y: 600, scale: 0.5, opacity: 1 },
}; return (
);
};
Quality Tests
Before delivering, verify:
Implementation Steps
1. Scrapling brand scrape β If featuring a product, scrape its site first
2. Director's treatment β Write vibe, camera style, emotional arc
3. Visual direction β Colors, fonts, brand feel, animation style
4. Scene breakdown β List every scene with description, duration, text, transitions
5. Plan assets β User assets + generated images/videos + brand scrape assets
6. Define durations β Vary pacing (2-3s punchy, 4-5s dramatic)
7. Build persistent layer β Animated background outside scenes
8. Build scenes β Each with enter/exit animations, 3-5 timed moments
9. Open with hook β High-impact first scene
10. Develop narrative β Content-driven middle scenes
11. Strong ending β Intentional, resolved close
12. Start Remotion Studio β npm run dev on port 3000
13. Expose via tunnel β bash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000
14. Send user the public URL β They preview and request changes live
15. Iterate β Edit source, hot-reload, repeat
16. Render β Only when user says to export final video
File Structure
my-video/
βββ src/
β βββ Root.tsx # Composition definitions
β βββ index.ts # Entry point
β βββ index.css # Global styles
β βββ MyVideo.tsx # Main video component
β βββ scenes/ # Scene components (optional)
βββ public/
β βββ images/
β β βββ brand/ # Scrapling-scraped assets
β βββ audio/ # Background music
βββ remotion.config.ts
βββ package.json
Common Components
See references/components.md for reusable:
Tunnel Management
# Start tunnel (exposes port 3000 publicly)
bash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000Check status
bash skills/cloudflare-tunnel/scripts/tunnel.sh status 3000List all tunnels
bash skills/cloudflare-tunnel/scripts/tunnel.sh listStop tunnel
bash skills/cloudflare-tunnel/scripts/tunnel.sh stop 3000
Troubleshooting
Common Issues & Fixes
| Issue | Solution |
|-------|----------|
| Expected ">" but found "schema" | Use .tsx extension for files with JSX, not .ts |
| useCurrentFrame() can only be called inside a component | Use registerRoot + Composition API (see Step 7) |
| "fps" must be a number, but you passed undefined to spring() | Pass fps to spring: spring({ frame, fps, from: 0.8, to: 1 }) |
| Could not find composition with ID index | Use composition name: npx remotion render MyVideo out.mp4 |
| Module build failed | Ensure react and react-dom are in dependencies |
| Remotion not found | Run npm install in project directory |
| Hot reload not working | Ensure running npm run dev, not npx remotion directly |
| Brand colors not extracting | Some sites use CSS variables - check page source manually |
File Extension Rules
.tsx for files with JSX (components with < tags >).ts for pure TypeScript files.tsx if it uses JSXTesting Your Video
1. Start dev server:npm run dev
2. Open http://localhost:3000
3. Make changes - auto-refreshes
4. Check composition in browserChangelog
v1.0.0 (2026-02-25)
v1.1.0 (2026-02-25)
registerRoot + Composition patternfps parameterPractical Example: OpenClaw Promo Video
Here's the actual project created during testing:
Location: skills/remotion-video-generator/openclaw-promo/
Brand Data Extracted:
Project Structure:
openclaw-promo/
βββ src/
β βββ index.tsx # Entry point
β βββ OpenClawPromo.tsx # Video component
βββ public/
β βββ images/
β βββ brand/
β βββ logo.svg
β βββ og-image.png
β βββ screenshot.png
βββ package.json
βββ tsconfig.json
Commands:
cd skills/remotion-video-generator/openclaw-promo
npm run dev # Start studio at localhost:3000
npm run build # Bundle for production
*Last updated: 2026-02-25*
π‘ Examples
# Scaffold project
cd output && npx --yes create-video@latest my-video --template blank
cd my-video && npm installAdd motion libraries
npm install lucide-reactFix scripts in package.json (replace any "bun" references with "npx remotion")
Start dev server
npm run devExpose publicly
bash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000
π Tips & Best Practices
Common Issues & Fixes
| Issue | Solution |
|-------|----------|
| Expected ">" but found "schema" | Use .tsx extension for files with JSX, not .ts |
| useCurrentFrame() can only be called inside a component | Use registerRoot + Composition API (see Step 7) |
| "fps" must be a number, but you passed undefined to spring() | Pass fps to spring: spring({ frame, fps, from: 0.8, to: 1 }) |
| Could not find composition with ID index | Use composition name: npx remotion render MyVideo out.mp4 |
| Module build failed | Ensure react and react-dom are in dependencies |
| Remotion not found | Run npm install in project directory |
| Hot reload not working | Ensure running npm run dev, not npx remotion directly |
| Brand colors not extracting | Some sites use CSS variables - check page source manually |
File Extension Rules
.tsx for files with JSX (components with < tags >).ts for pure TypeScript files.tsx if it uses JSXTesting Your Video
1. Start dev server:npm run dev
2. Open http://localhost:3000
3. Make changes - auto-refreshes
4. Check composition in browser