// Generate professional tutorial and introduction videos for projects using Remotion. Analyzes project workflows, creates structured video compositions with chapters, transitions, and annotations aligned with project architecture.
| name | remotion-tutorial-generator |
| description | Generate professional tutorial and introduction videos for projects using Remotion. Analyzes project workflows, creates structured video compositions with chapters, transitions, and annotations aligned with project architecture. |
This skill enables you to create professional tutorial and introduction videos for software projects using Remotion, a React-based video generation framework.
Before generating any video, thoroughly analyze the target project:
Read Project Documentation
Analyze Code Structure
Identify Demo-worthy Features
Create a structured video outline with chapters:
Chapter Breakdown
Timing Calculations
durationInFrames for each sceneVisual Planning
Initialize the Remotion project:
# Create new Remotion project
npx create-video@latest
# Or add to existing project
npm install remotion
Project Structure:
remotion-tutorial/
โโโ src/
โ โโโ Root.tsx # Register compositions
โ โโโ Video.tsx # Main video composition
โ โโโ scenes/
โ โ โโโ Intro.tsx
โ โ โโโ Overview.tsx
โ โ โโโ FeatureDemo.tsx
โ โ โโโ Architecture.tsx
โ โ โโโ Outro.tsx
โ โโโ components/
โ โ โโโ ChapterTitle.tsx # Reusable chapter headers
โ โ โโโ CodeSnippet.tsx # Syntax-highlighted code
โ โ โโโ Annotation.tsx # Text annotations
โ โ โโโ Transition.tsx # Transition effects
โ โโโ utils/
โ โโโ animations.ts # Custom animation helpers
โ โโโ theme.ts # Colors, fonts, spacing
โโโ public/
โ โโโ assets/
โ โ โโโ logo.png
โ โ โโโ screenshots/
โ โ โโโ audio/
โโโ package.json
// src/Video.tsx
import {Composition} from 'remotion';
import {Intro} from './scenes/Intro';
import {Overview} from './scenes/Overview';
import {FeatureDemo} from './scenes/FeatureDemo';
import {Architecture} from './scenes/Architecture';
import {Outro} from './scenes/Outro';
export const RemotionVideo: React.FC = () => {
const fps = 30;
return (
<>
{/* Intro Scene */}
<Sequence durationInFrames={fps * 8}>
<Intro />
</Sequence>
{/* Overview Scene */}
<Sequence from={fps * 8} durationInFrames={fps * 15}>
<Overview />
</Sequence>
{/* Feature Demos */}
<Sequence from={fps * 23} durationInFrames={fps * 45}>
<FeatureDemo />
</Sequence>
{/* Architecture Diagram */}
<Sequence from={fps * 68} durationInFrames={fps * 30}>
<Architecture />
</Sequence>
{/* Outro */}
<Sequence from={fps * 98} durationInFrames={fps * 10}>
<Outro />
</Sequence>
</>
);
};
Each scene should follow this pattern:
// src/scenes/FeatureDemo.tsx
import {useCurrentFrame, useVideoConfig, interpolate, spring} from 'remotion';
import {ChapterTitle} from '../components/ChapterTitle';
import {Annotation} from '../components/Annotation';
export const FeatureDemo: React.FC = () => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
// Fade in title
const titleOpacity = interpolate(frame, [0, 30], [0, 1], {
extrapolateRight: 'clamp'
});
// Animate annotation entrance
const annotationY = spring({
frame: frame - 60,
fps,
config: {
damping: 100,
stiffness: 200,
mass: 0.5
}
});
return (
<div style={{
width: '100%',
height: '100%',
backgroundColor: '#0f172a',
position: 'relative'
}}>
{/* Chapter Title */}
<ChapterTitle
title="Key Features"
subtitle="Real-time bidding and checkout"
opacity={titleOpacity}
/>
{/* Feature Demonstration */}
<div style={{
position: 'absolute',
top: '30%',
left: '10%',
right: '10%'
}}>
{/* Screenshot or animation here */}
</div>
{/* Annotation */}
{frame > 60 && (
<Annotation
text="Guests can place bids in real-time"
position={{
x: '20%',
y: `${50 + annotationY * 10}%`
}}
/>
)}
</div>
);
};
// src/components/ChapterTitle.tsx
import React from 'react';
interface ChapterTitleProps {
title: string;
subtitle?: string;
opacity?: number;
}
export const ChapterTitle: React.FC<ChapterTitleProps> = ({
title,
subtitle,
opacity = 1
}) => {
return (
<div style={{
position: 'absolute',
top: '10%',
left: '10%',
right: '10%',
opacity
}}>
<h1 style={{
fontSize: '4rem',
fontWeight: 'bold',
color: '#ffffff',
margin: 0,
textShadow: '0 4px 8px rgba(0,0,0,0.3)'
}}>
{title}
</h1>
{subtitle && (
<p style={{
fontSize: '2rem',
color: '#cbd5e1',
marginTop: '1rem'
}}>
{subtitle}
</p>
)}
</div>
);
};
// src/components/Transition.tsx
import {useCurrentFrame, interpolate} from 'remotion';
interface TransitionProps {
type: 'fade' | 'slide' | 'wipe';
durationInFrames: number;
direction?: 'in' | 'out';
children: React.ReactNode;
}
export const Transition: React.FC<TransitionProps> = ({
type,
durationInFrames,
direction = 'in',
children
}) => {
const frame = useCurrentFrame();
const progress = interpolate(
frame,
[0, durationInFrames],
direction === 'in' ? [0, 1] : [1, 0],
{extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}
);
const style: React.CSSProperties = (() => {
switch (type) {
case 'fade':
return {opacity: progress};
case 'slide':
return {transform: `translateX(${(1 - progress) * -100}%)`};
case 'wipe':
return {clipPath: `inset(0 ${(1 - progress) * 100}% 0 0)`};
default:
return {};
}
})();
return <div style={style}>{children}</div>;
};
// src/components/Annotation.tsx
interface AnnotationProps {
text: string;
position: {x: string; y: string};
arrow?: {from: string; to: string};
}
export const Annotation: React.FC<AnnotationProps> = ({
text,
position,
arrow
}) => {
return (
<div style={{
position: 'absolute',
left: position.x,
top: position.y,
backgroundColor: '#fbbf24',
color: '#1f2937',
padding: '0.5rem 1rem',
borderRadius: '0.5rem',
fontSize: '1.5rem',
fontWeight: '600',
boxShadow: '0 4px 12px rgba(0,0,0,0.2)',
zIndex: 100
}}>
{text}
{arrow && (
<svg
style={{
position: 'absolute',
width: '100%',
height: '100%',
pointerEvents: 'none'
}}
>
{/* Arrow implementation */}
</svg>
)}
</div>
);
};
// src/utils/animations.ts
import {interpolate, spring, SpringConfig} from 'remotion';
export const fadeIn = (frame: number, startFrame: number, duration: number) => {
return interpolate(
frame,
[startFrame, startFrame + duration],
[0, 1],
{extrapolateRight: 'clamp', extrapolateLeft: 'clamp'}
);
};
export const slideIn = (
frame: number,
fps: number,
delay: number = 0,
config?: SpringConfig
) => {
return spring({
frame: frame - delay,
fps,
config: config || {damping: 100, stiffness: 200, mass: 0.5}
});
};
export const staggeredAppearance = (
frame: number,
itemIndex: number,
staggerDelay: number
) => {
const startFrame = itemIndex * staggerDelay;
return interpolate(
frame,
[startFrame, startFrame + 20],
[0, 1],
{extrapolateRight: 'clamp', extrapolateLeft: 'clamp'}
);
};
Add background music and narration:
import {Audio, useCurrentFrame} from 'remotion';
// In your main composition
<Audio src="/audio/background-music.mp3" volume={0.3} />
// For narration synced to scenes
<Sequence from={fps * 8}>
<Audio src="/audio/narration-overview.mp3" />
</Sequence>
Render the video with appropriate settings:
# Preview in browser
npm run dev
# Render single frame for testing
npx remotion still src/index.ts MyVideo --frame=150 --output=preview.png
# Render full video
npx remotion render src/index.ts MyVideo output.mp4
# Render with custom settings
npx remotion render src/index.ts MyVideo output.mp4 \
--codec=h264 \
--scale=1 \
--quality=90
When generating a tutorial video, complete these steps:
For projects with multiple features, create a carousel effect:
const features = [
{title: 'Feature 1', description: '...', screenshot: '...'},
{title: 'Feature 2', description: '...', screenshot: '...'},
// ...
];
features.map((feature, index) => (
<Sequence
key={index}
from={fps * (23 + index * 15)}
durationInFrames={fps * 15}
>
<FeatureSlide feature={feature} />
</Sequence>
));
Show code snippets with syntax highlighting:
import {CodeSnippet} from './components/CodeSnippet';
<Sequence from={fps * 50} durationInFrames={fps * 20}>
<CodeSnippet
language="typescript"
code={`
const handleBid = async (itemId: string, amount: number) => {
await db.collection('bids').add({
itemId,
amount,
timestamp: serverTimestamp()
});
};
`}
highlights={[2, 3, 4]} // Highlight specific lines
/>
</Sequence>
Animate system architecture components:
<Sequence durationInFrames={fps * 30}>
<ArchitectureDiagram>
<Box label="React Frontend" delay={0} />
<Arrow from="frontend" to="firebase" delay={30} />
<Box label="Firebase" delay={30} />
<Arrow from="firebase" to="firestore" delay={60} />
<Box label="Firestore DB" delay={60} />
</ArchitectureDiagram>
</Sequence>
A successful tutorial video should: