mirror of
https://github.com/eggent-ai/eggent.git
synced 2026-04-28 13:00:25 +00:00
3.6 KiB
3.6 KiB
Remotion Composition Patterns
Project Structure
my-video/
├── src/
│ ├── index.ts # registerRoot entry point
│ ├── Root.tsx # <Composition> declarations
│ └── MyVideo/
│ ├── index.tsx # Main component
│ └── styles.ts # Optional styles
├── public/ # Static assets (images, fonts, audio)
├── remotion.config.ts # Remotion config
├── package.json
└── tsconfig.json
Basic Composition (Root.tsx)
import { Composition } from "remotion";
import { MyVideo } from "./MyVideo";
export const RemotionRoot = () => (
<>
<Composition
id="MyVideo"
component={MyVideo}
durationInFrames={300} // 10s at 30fps
fps={30}
width={1920}
height={1080}
defaultProps={{ title: "Hello World" }}
/>
</>
);
Common Aspect Ratios
- 16:9 landscape (YouTube): 1920x1080 or 1280x720
- 9:16 vertical (Reels/TikTok/Shorts): 1080x1920
- 4:5 Instagram feed: 1080x1350
- 1:1 square: 1080x1080
Key Remotion APIs
import {
useCurrentFrame, // Current frame number
useVideoConfig, // { fps, width, height, durationInFrames }
interpolate, // Map frame ranges to values
spring, // Physics-based spring animation
Sequence, // Time-offset children
AbsoluteFill, // Full-frame container
Img, // Image component (preloads)
Audio, // Audio component
Video, // Video component
staticFile, // Reference files in public/
delayRender, // Hold render until async ready
continueRender, // Resume after delayRender
} from "remotion";
Animation Example
import { useCurrentFrame, interpolate, spring, useVideoConfig, AbsoluteFill } from "remotion";
export const FadeInText: React.FC<{ text: string }> = ({ text }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const opacity = interpolate(frame, [0, 30], [0, 1], { extrapolateRight: "clamp" });
const scale = spring({ frame, fps, config: { damping: 200 } });
return (
<AbsoluteFill className="items-center justify-center bg-black">
<h1
style={{ opacity, transform: `scale(${scale})` }}
className="text-white text-7xl font-bold"
>
{text}
</h1>
</AbsoluteFill>
);
};
Sequences (Timing)
<AbsoluteFill>
<Sequence from={0} durationInFrames={60}>
<Intro />
</Sequence>
<Sequence from={60} durationInFrames={120}>
<MainContent />
</Sequence>
<Sequence from={180}>
<Outro />
</Sequence>
</AbsoluteFill>
Input Props (Dynamic Data)
Pass data via --props flag or defaultProps:
// Component
export const MyVideo: React.FC<{ title: string; items: string[] }> = ({ title, items }) => { ... };
// Render with props
// npx remotion render MyVideo --props='{"title":"Demo","items":["a","b"]}'
Audio
import { Audio, staticFile, Sequence } from "remotion";
<Sequence from={0}>
<Audio src={staticFile("bgm.mp3")} volume={0.5} />
</Sequence>
Fetching Data (delayRender)
const [data, setData] = useState(null);
const [handle] = useState(() => delayRender());
useEffect(() => {
fetch("https://api.example.com/data")
.then((r) => r.json())
.then((d) => { setData(d); continueRender(handle); });
}, []);
TailwindCSS
Remotion supports Tailwind out of the box when scaffolded with --tailwind. Use className as normal on any element.