Core Components of Remotion: The Building Blocks of Programmatic Video
The core components of Remotion include <Composition>, <Sequence>, <AbsoluteFill>, media wrappers like <Video> and <Audio>, and essential hooks such as useCurrentFrame() and useVideoConfig(), all exported from the @remotion/core package.
Remotion is a React-based framework that enables developers to author video programmatically using familiar web technologies. All public APIs for creating video compositions reside in the @remotion/core package within the remotion-dev/remotion repository. Understanding these core components is essential for building deterministic, frame-accurate video renders.
Composition: The Entry Point for Video Projects
The <Composition> component is the fundamental building block that registers a video composition with Remotion. Defined in packages/core/src/Composition.tsx, it specifies the canvas dimensions, frame rate, duration, and default props for a video scene.
When <Composition> mounts, it calls registerComposition via the CompositionSetters context. This populates a global CompositionManager that stores metadata including width, height, FPS, duration, and default props. The Studio UI, Player component, and render workers all consume this metadata to render the correct output.
import {Composition, AbsoluteFill} from 'remotion';
const MyVideo = () => (
<AbsoluteFill style={{backgroundColor: 'blue'}}>
<h1 style={{color: 'white'}}>Hello Remotion</h1>
</AbsoluteFill>
);
export const RemotionRoot = () => (
<Composition
id="MyVideo"
component={MyVideo}
durationInFrames={150}
fps={30}
width={1920}
height={1080}
/>
);
Timeline and Layout Components
Sequence for Time-Shifting Layers
The <Sequence> component, implemented in packages/core/src/Sequence.tsx, is Remotion's primary tool for building timelines. It time-shifts its children by a specified frame offset and optionally limits their duration.
Each <Sequence> calculates its absolute start frame (cumulatedFrom) based on its parent sequence. The SequenceContext propagates down the React tree, allowing nested sequences to offset their children correctly. This architecture enables complex, multi-layered video editing directly in React.
import {Sequence, AbsoluteFill} from 'remotion';
export const TimelineExample = () => (
<AbsoluteFill>
{/* Background runs from frame 0-300 */}
<Sequence from={0} durationInFrames={300}>
<BackgroundVideo />
</Sequence>
{/* Title appears 60 frames in, lasts 180 frames */}
<Sequence from={60} durationInFrames={180}>
<TitleText />
</Sequence>
{/* Logo overlay runs entire duration */}
<Sequence from={0} durationInFrames={Infinity}>
<Logo />
</Sequence>
</AbsoluteFill>
);
AbsoluteFill for Layer Positioning
<AbsoluteFill>, defined in packages/core/src/AbsoluteFill.tsx, is a layout helper that creates an absolutely-positioned <div> filling its parent container. It defaults to display: flex, making it ideal for stacking video layers, centering content, and creating full-screen compositions without manual CSS positioning.
Media Components for Video and Audio
Video Component with Timeline Sync
The <Video> component (and its alias <Html5Video>), located in packages/core/src/video/Video.tsx, wraps the native HTML5 <video> element. It synchronizes playback with Remotion's frame loop, supporting trimming via startFrom and endAt props, looping behavior, and pre-loading optimizations.
The component uses the current frame from useCurrentFrame() to calculate the exact playback position, ensuring frame-accurate rendering during export.
Audio Component
<Audio>, exported from packages/core/src/audio/index.js, provides the same timeline-synchronization capabilities for audio elements. It wraps the native <audio> tag and manages playback timing to match the video frame, ensuring lip-sync and audio alignment in the final render.
Loop and Series Utilities
<Loop> (packages/core/src/loop/index.js) repeats its children for a specified number of frames, used internally by <Video> when the loop prop is enabled. <Series> (packages/core/src/series/index.js) renders a series of identical <Composition> instances, useful for generating episodic content or batch variations.
Essential Hooks for Frame-Based Logic
useCurrentFrame for Animation Timing
The useCurrentFrame() hook, implemented in packages/core/src/use-current-frame.ts, returns the current frame number during rendering or preview. This is the primary driver for animations, allowing components to calculate positions, opacities, and transforms based on the exact frame index.
import {useCurrentFrame, useVideoConfig} from 'remotion';
export const AnimatedSquare = () => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
// Oscillate size over 2 seconds
const size = 100 + 50 * Math.sin((frame / fps) * Math.PI);
return (
<div style={{width: size, height: size, background: 'red'}} />
);
};
useVideoConfig for Composition Metadata
useVideoConfig() (packages/core/src/use-video-config.ts) exposes the global configuration of the active <Composition>, including width, height, fps, durationInFrames, and id. This hook provides the canvas constraints necessary for responsive layouts and timing calculations.
useRemotionEnvironment for Context Detection
useRemotionEnvironment() (packages/core/src/use-remotion-environment.ts) returns runtime flags indicating whether the code runs in the Studio UI, Player, CLI rendering, or Web-Renderer. Components use this to throw contextual errors or adjust behavior—for example, <Html5Video> prevents usage in the Web-Renderer where native video elements aren't supported.
Async Rendering and Asset Management
delayRender and continueRender for Data Fetching
The delayRender and continueRender APIs (packages/core/src/delay-render.ts) implement a promise-based gate system for asynchronous operations. delayRender returns a handle and pauses the frame loop until continueRender(handle) is called, enabling data fetching, font loading, or WebGL initialization before rendering proceeds.
import {useEffect, useState} from 'react';
import {delayRender, continueRender, Video} from 'remotion';
export const AsyncVideo = () => {
const [handle] = useState(() => delayRender('Loading video URL'));
const [videoUrl, setVideoUrl] = useState(null);
useEffect(() => {
fetch('https://api.example.com/video')
.then(r => r.json())
.then(data => {
setVideoUrl(data.url);
continueRender(handle);
});
}, [handle]);
return videoUrl ? <Video src={videoUrl} /> : null;
};
staticFile for Asset Registration
staticFile (packages/core/src/static-file.js) registers static assets (images, videos, fonts) with the Remotion bundler, ensuring deterministic URLs at runtime. getStaticFiles retrieves these URLs, enabling reliable asset loading even when deployed to CDNs.
How the Core Components Work Together
Remotion's architecture is React-centric: every visual or temporal feature is expressed as a component or hook, while a thin runtime layer handles timing logic and worker communication.
Composition Registration: When <Composition> mounts, it populates a global CompositionManager via the CompositionSetters context. This stores metadata (width, height, FPS, duration) used by the Studio UI, Player, and render workers.
Timeline Construction: Inside a composition, developers build timelines using <Sequence> to offset and clip layers. Each sequence calculates its absolute start frame (cumulatedFrom) based on parent sequences via SequenceContext, enabling nested time-shifting.
Frame-Driven Rendering: The rendering engine drives a frame loop where useCurrentFrame provides the current index and useVideoConfig supplies canvas constraints. Media components like <Video> and <Audio> use these values to seek native elements to the exact frame position, ensuring synchronization.
Environment Detection: useRemotionEnvironment provides runtime flags (Studio, Player, CLI, Web-Renderer) allowing components to validate their usage context and throw helpful errors when unsupported.
Asset and Async Handling: staticFile ensures assets are bundled correctly, while delayRender/continueRender enable asynchronous data fetching without breaking the frame loop.
Summary
<Composition>registers video metadata (dimensions, FPS, duration) and serves as the entry point for all Remotion projects.<Sequence>time-shifts and truncates child elements, enabling complex timeline construction with nested offsets.<AbsoluteFill>provides a full-canvas flex container for absolute positioning of visual layers.<Video>and<Audio>wrap native media elements with frame-accurate timeline synchronization.useCurrentFrame()anduseVideoConfig()provide the frame index and composition metadata necessary for animations.delayRender()andcontinueRender()enable asynchronous operations without blocking the render loop.staticFile()ensures static assets are correctly bundled and accessible at runtime.
Frequently Asked Questions
What is the difference between Composition and Sequence in Remotion?
<Composition> defines the global parameters of a video project—its resolution, frame rate, duration, and default props—and registers it with the Remotion Studio and rendering engine. <Sequence>, conversely, is a timeline utility that offsets its children by a specific frame number and optionally clips their duration. While a Composition defines what video to make, Sequences define when elements appear within that video.
How does Remotion synchronize video playback with the React timeline?
Remotion drives a frame loop that increments on every render cycle. The useCurrentFrame() hook returns the current frame index, which media components like <Video> (in packages/core/src/video/Video.tsx) and <Audio> use to calculate the exact playback position. By setting the currentTime property of native media elements to frame / fps, Remotion ensures frame-accurate synchronization between React state and media playback during both preview and export.
Can I use Remotion hooks outside of a Composition?
No, hooks like useCurrentFrame(), useVideoConfig(), and useRemotionEnvironment() rely on React context providers that are only available inside a registered <Composition>. Attempting to use these hooks outside the Remotion tree will result in runtime errors. For asynchronous initialization logic that must occur before rendering starts, use delayRender() and continueRender() within your component rather than outside the component tree.
What is the purpose of delayRender in Remotion?
delayRender() is a primitive that pauses the Remotion frame loop until continueRender() is called with the returned handle. This mechanism allows components to perform asynchronous operations—such as fetching remote data, loading fonts, or initializing WebGL contexts—before the first frame is rendered. Without this API, the render would begin immediately and potentially capture incomplete or loading states. The implementation in packages/core/src/delay-render.ts creates a promise gate that the rendering engine awaits before proceeding to the next frame.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →