| name | remotion |
| description | Use when generating or modifying Remotion video code, creating demo videos, or working with the demo-video/ directory |
| disable-model-invocation | false |
| user-invocable | true |
| allowed-tools | Read, Grep, Glob, Edit, Write, Bash |
Remotion Video Generation Skills
App Factory includes an integrated Remotion video pipeline for generating demo videos of built applications.
When This Skill Applies
- Working with files in
demo-video/ directory
- Running
/factory video command
- Creating or modifying Remotion compositions
- Debugging video rendering issues
- Understanding frame-based animations
Project Structure
demo-video/
├── src/
│ ├── index.ts # Remotion entry point
│ ├── Root.tsx # Composition registry
│ ├── compositions/
│ │ └── AppFactoryDemo.tsx # Main demo video (10s, 1920x1080)
│ └── components/
│ ├── Title.tsx # Animated title
│ ├── BulletPoints.tsx # Staggered highlights
│ ├── VerificationBadge.tsx # PASS badge
│ └── Footer.tsx # UTC timestamp
├── remotion.config.ts # Remotion configuration
└── package.json # Dependencies (Remotion v4.x)
Critical Rules (MUST FOLLOW)
1. Frame-Based Animations ONLY
const frame = useCurrentFrame();
const opacity = interpolate(frame, [0, 30], [0, 1], {
extrapolateRight: 'clamp',
});
2. Interpolate with Clamping
const value = interpolate(frame, [0, 60], [0, 100], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
3. Spring Animations
const springValue = spring({
fps,
frame,
config: { damping: 200, stiffness: 100 },
durationInFrames: 40,
});
4. Determinism Requirements
- Timestamps MUST be input props, never
new Date()
- Use
timeZone: 'UTC' for all date formatting
- No
Math.random() or non-deterministic values
- Same props must produce identical video output
5. Component Structure
export const MyComposition: React.FC<Props> = (props) => {
const frame = useCurrentFrame();
const { fps, width, height, durationInFrames } = useVideoConfig();
return (
<AbsoluteFill style={{ backgroundColor: '#000' }}>
{/* Sequenced content */}
<Sequence from={0} durationInFrames={60}>
<Scene1 />
</Sequence>
<Sequence from={60} durationInFrames={60}>
<Scene2 />
</Sequence>
</AbsoluteFill>
);
};
Pipeline Integration
Auto-Generation Flow
- Local Run Proof verification runs
RUN_CERTIFICATE.json created with status: "PASS"
- Hook triggers
post-run-certificate-video.mjs
- Demo video rendered to
demo/out/<slug>.mp4
Manual Rendering
node scripts/render-demo-video.mjs --cwd ./my-app --slug my-app
node scripts/render-demo-video.mjs \
--cwd ./my-app \
--slug my-app \
--title "My Amazing App" \
--highlights '["Feature 1", "Feature 2", "Feature 3"]'
Props Schema
interface AppFactoryDemoProps {
title: string;
slug: string;
verifiedUrl: string;
timestamp: string;
highlights: string[];
certificateHash: string;
}
Debugging
cd demo-video && npm run studio
npx remotion render src/index.ts AppFactoryDemo output.mp4
npx tsc --noEmit
Common Patterns
Fade In/Out
const fadeIn = interpolate(frame, [0, 30], [0, 1], {
extrapolateRight: 'clamp',
});
const fadeOut = interpolate(frame, [duration - 30, duration], [1, 0], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
const opacity = fadeIn * fadeOut;
Staggered Animation
items.map((item, index) => {
const delay = index * 10;
const itemOpacity = interpolate(
frame,
[delay, delay + 20],
[0, 1],
{ extrapolateLeft: 'clamp', extrapolateRight: 'clamp' }
);
return <Item key={index} style={{ opacity: itemOpacity }} />;
});
Scale with Spring
const scaleSpring = spring({
fps,
frame: frame - startFrame,
config: { damping: 80, stiffness: 200 },
});
const scale = interpolate(scaleSpring, [0, 1], [0.8, 1]);
Error Codes
| Code | Meaning | Resolution |
|---|
| FAC-006 | Video render failed | Check Remotion logs, verify ffmpeg installed |
| FAC-007 | Certificate missing | Run Local Run Proof first |
| FAC-008 | Props validation failed | Check prop types match schema |
Reference