Technical Documentation: remotion-dev/remotion
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (README.md)
Video tools for the agent era.
Video Creation
- Make videos agentically: Turn your idea into a video using your coding agent.
- Make videos interactively: Edit and animate using drag and drop.
- Make videos programmatically: Connect to data, and manage complexity with code.
React Code is the source of truth. Switch your workflow at any point.
Video Automation
- Design systems: Create a library of animated assets for your organization.
- Batch rendering: Render millions of videos on your own infrastructure.
- Applications: Publish a simple tool or a complex video editor.
Get started
If you already have Node.JS installed, type
npx create-video@latestto get started. Otherwise, read the installation page in the documentation.
Discover Remotion
Remotion is extensively documented over more than 1000 pages.
- Get Started
- Components
- Rendering
- Making apps
- Community
- Commercial
- Help
Documentation
Documentation: remotion.dev/docs
API Reference: remotion.dev/api
License
Be aware of that Remotion has a special license and requires obtaining a company license in some cases. Read the LICENSE page for more information.
Contributing
Please read CONTRIBUTING.md to learn about contributing to this project.
Packages Docs README (`packages/docs/README.md`)
@remotion/docs
Usage
This is an internal package and has no documentation.
Packages Docs Docs Getting Started (`packages/docs/docs/getting-started.mdx`)
image: /generated/articles-docs-getting-started.png id: getting-started title: Creating a new project sidebar_label: Installation slug: / crumb: "Let's begin!"
import {CreateWithChatGPTButton} from '../components/CreateWithChatGPTButton';
Using ChatGPT
If you have the ChatGPT desktop app, it can create a complete Remotion project that you can edit, run, and render locally using the Remotion plugin.
Coding Agent Prompt
Paste into a coding agent, such as Claude Code, Codex or OpenCode:
Ensure Node.js is installed.
Install Remotion Skills:npx -y skills@latest add remotion-dev/skills -g -y
Then use them to create a video.
From the command line
npx create-video@latest --yes --blank my-video
cd my-video
npx remotion skills add
npm run devCreates a video in the my-video directory using the blank template and Agent Skills, without TailwindCSS.
Planning to prompt a video using a coding agent?
Click here for more detailed beginner instructions.
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Templates
Choose the template that is most suitable for you.
For your first project, we recommend the Hello World template.
Wizard
Customize the creation of a Remotion project by selecting a package manager, a template and whether to install Agent Skills.
<Tabs
defaultValue="npm"
values={[
{ label: 'npm', value: 'npm', },
{ label: 'bun', value: 'bun', },
{ label: 'pnpm', value: 'pnpm', },
{ label: 'yarn', value: 'yarn', },
{ label: 'nub', value: 'nub', },
]
}>
npx create-video@latestpnpm create videoyarn create videonubx create-video@latestbun create video:::note
Bun as a runtime is mostly supported. Read more here.
:::
After the project has been scaffolded, start the local development server:
<Tabs
defaultValue="npm"
values={[
{ label: 'Regular templates', value: 'npm', },
{ label: 'Next.js + React Router 7', value: 'pnpm', },
]
}>
After the project has been scaffolded, we recommend to open the project in your text editor and starting the Remotion Studio:
npm run devAfter the project has been scaffolded, we recommend to open the project in your text editor and starting the app:
npm run devTo start the Remotion Studio:
npm run remotionESLint
Remotion templates include a recommended ESLint configuration. See @remotion/eslint-config to choose the config for your ESLint version or to add it to another project.
System requirements
To use Remotion, you need at least Node
🍎 macOS 15 (Sequoia) or later is required. Older versions are not supported.
🐧 Linux distros need at least version 2.35 of Libc.
They also need to install some additional packages.
Alpine Linux and nixOS are unsupported.
Installation in existing projects
Want to install Remotion in an existing project? Go here instead: Installation in existing projects
Packages Docs Elements Template Index (`packages/docs/elements-template/index.mdx`)
title: Element title image: /elements/category-element-title-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {ElementComponent} from './element';
export const elementDefinition = {
category: 'category',
component: ElementComponent,
contributors: [],
dependencies: [],
displayName: 'Element title',
durationInFrames: 120,
elementHeight: null,
elementWidth: null,
fps: 30,
height: 1080,
posterFrame: 60,
preview: {
posterUrl: '/elements/category-element-title-preview.png',
videoUrl: '/elements/category-element-title-preview.mp4',
},
safeArea: 0,
slug: 'category/element-title',
installationMode: 'component-owned-sequence',
width: 1920,
};
Element title
Packages Docs Elements Index (`packages/docs/elements/index.mdx`)
title: Remotion Elements sidebar_label: Overview hide_table_of_contents: true pagination_next: null pagination_prev: null
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Remotion Elements
Drop-in video building blocks. Make it yours, interactively or with an agent.
Browse the catalog here or directly inside Remotion Studio.
More Elements
Add third-party Element Libraries to browse and install Elements from other creators in Studio.
Have an Element idea? Contribute.
Packages Docs Docs Ai Index (`packages/docs/docs/ai/index.mdx`)
image: /generated/articles-docs-ai-index.png crumb: 'Artificial Intelligence' title: Building with Remotion and AI
import {TableOfContents} from './TableOfContents';
Here are a few ways you can use AI in your Remotion workflow today:
| Tella for boosting the development of @remotion/media-parser with $10.000! |
|---|
License
Packages Docs Docs Media Utils Index (`packages/docs/docs/media-utils/index.mdx`)
image: /generated/articles-docs-media-utils-index.png title: "@remotion/media-utils"
import {TableOfContents} from './table-of-contents';
A package providing utility functions for getting information about video and audio, and for visualizing audio.
Except for useAudioData(), all functions can also be used outside of Remotion.
Functions
| Record webcam and display as separate streams. Up to 4 sources can be recorded at the same time! | Ensure you are in the center of the video and you are not too close to the microphone. |
Different platforms require different formats
Each platform has its own conventions for how videos should look.
| WIP | ||
|---|---|---|
| Twitter, LinkedIn |
1:1
Muted by default
Captions burned in | **YouTube**
16:9
Audio by default
Captions as .srt file{" "}
Endcard with related videos | TikTok, Reels, Shorts{" "}
[planned](#tiktok-format)
9:16
Safe space at bottom required
Word-by-word captions |The goal of the Recorder: Edit once and feel native on each platform.
This has a measurable impact on the performance of your post: For example, a 1:1 video on X results in 30-35% higher video views and a 80-100% higher engagement rate.
Captions are essential
Generate captions locally using Whisper.cpp. The Recorder will automatically install it for you.
AI will make mistakes - so we make it easy to correct them.
| Captions have word-level timings | Orphan words are avoided by balancing the text layout | Use backticks to highlight technical terms |
|---|
| Fix captions quickly by clicking on a word | Write a JavaScript function to fix common misspellings | Captions are stored as editable JSON |
|---|
Agnostic endcards
Your viewer watched the entire video! Now don't make them forget about you.
| If you post on Twitter, the call-to-action is "Follow" and your other platforms
are linked. | If you post on YouTube, the call to action is "Subscribe" and cutouts for related
videos are made. |
| --- | --- |
The endcard is written with React and CSS, so can be easily customized.
Customization
Having access to the entire source code, you can use CSS to customize the look of the Recorder.
| Look of the built-in light theme | Look of the built-in dark theme | Use CSS to make it your own! |
|---|
The Recorder is built with TypeScript and React, and you can fully customize it's behavior.
It's a hackable video editor.
Silence removal
Automatically remove the silence at the start and end of your take.
Music
Add background music to your video and automatically fade between the different sections.
Three exclusive tracks are included that you may use for your video.
Layouting
Whether you only record your facecam, or also your display, the Recorder always finds the ideal layout - even if you mix landscape and portrait videos.
Transitions
Enable clean transitions between scenes - no matter if you change the layout during the video.
Chapters
Mark a scene as the beginning of a new chapter and automatically generate animated chapters.
B-Roll
Add images and videos on top of your facecam or display while your voiceover is playing to give the video more depth.
Exporting
Export your video with much control over the encoding options.
Render a video with a single click on a button, the CLI, Node.JS APIs, GitHub Actions, or even on AWS Lambda!
See also
1) 9:16 format is not yet implemented.
Packages Docs Docs Rive Index (`packages/docs/docs/rive/index.mdx`)
image: /generated/articles-docs-rive-index.png sidebar_label: Overview title: "@remotion/rive" crumb: Integrations
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import {TableOfContents} from './table-of-contents';
This package provides a component for rendering Rive animations in Remotion.
Installation
Install @remotion/rive
<Tabs defaultValue="npm" values={[
{ label: 'npm', value: 'npm', },
{ label: 'yarn', value: 'yarn', },
{ label: 'pnpm', value: 'pnpm', },
]
}>
npm i @remotion/riveyarn add @remotion/rivepnpm i @remotion/riveAPI
License
Packages Docs Docs Rough Notation Index (`packages/docs/docs/rough-notation/index.mdx`)
image: /generated/articles-docs-rough-notation-index.png id: rough-notation-api slug: /rough-notation/api title: '@remotion/rough-notation'
@remotion/rough-notation
Animated marker highlights, circles, boxes, underlines and other hand-drawn text annotations for Remotion videos.
import {TableOfContents} from './table-of-contents';
APIs
Common props
Every component wraps the text or element passed as children and accepts these props:
`children`
The text or element to annotate.
`style?`
CSS styles applied to the tracked content. Text and font styles can also be edited in Remotion Studio.
`progress`
Controls how much of the annotation is drawn. Use a value between 0 and 1.
`disabled?`
Set to true to temporarily hide the annotation while keeping the component and its other props in place. Default: false.
`seed?`
Controls the generated shape. Change the integer on every frame to animate the shape. Default: 1.
`color?`
The annotation color. Default: currentColor.
`roughness?`
Controls how rough the annotation looks. The default is 3 for <Highlight> and 1.5 for the other components.
`maxRandomnessOffset?`
Controls how far points may be randomly offset from their ideal position. Default: 5.
`bowing?`
Controls how much straight lines bow. Default: 1.
`disableMultiStroke?`
Set to true to prevent Rough.js from drawing multiple strokes for a line. Default: false.
`preserveVertices?`
Preserves vertices when roughening a shape. Default: false.
The components are interactive in Remotion Studio and support editable text and font controls.
Inherited props
Every annotation component inherits from, durationInFrames, trimBefore, playbackRate, freeze, hidden, name and showInTimeline from <Sequence>.
From premountFor, postmountFor, styleWhilePremounted and styleWhilePostmounted from <Sequence>.
License
MIT
Packages Docs Docs Rounded Text Box Index (`packages/docs/docs/rounded-text-box/index.mdx`)
image: /generated/articles-docs-rounded-text-box-index.png title: '@remotion/rounded-text-box'
@remotion/rounded-text-box
Create a TikTok-like multiline text box SVG path with rounded corners.
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {TableOfContents} from './table-of-contents';
<Tabs
defaultValue="npm"
values={[
{ label: 'npm', value: 'npm', },
{ label: 'pnpm', value: 'pnpm', },
{ label: 'yarn', value: 'yarn', },
]
}>
npm i @remotion/rounded-text-boxpnpm i @remotion/rounded-text-boxyarn add @remotion/rounded-text-boxFunctions
License
MIT
Packages Docs Docs Sdk Get Canvas Sequence Reorder Insertion Index (`packages/docs/docs/sdk/get-canvas-sequence-reorder-insertion-index.mdx`)
image: /generated/articles-docs-sdk-get-canvas-sequence-reorder-insertion-index.png title: getCanvasSequenceReorderInsertionIndex() crumb: '@remotion/sdk'
getCanvasSequenceReorderInsertionIndex()
Calculates where a dragged group lands after removing its selected siblings. Returns null for a drop on the selection, a negative or duplicate source index, or a move that leaves a contiguous group in place.
import {getCanvasSequenceReorderInsertionIndex} from '@remotion/sdk';
const insertionIndex = getCanvasSequenceReorderInsertionIndex({
sourceIndexes: [0, 2],
targetIndex: 4,
position: 'before',
});
// 2: after removing indexes 0 and 2, insert before the original index 4.
console.log(insertionIndex);Indexes must describe siblings in the same order. This helper does not check whether the JSX nodes are direct siblings; reorderNodes() validates that against source code.
Options
sourceIndexes
The indexes of the selected siblings to move.
targetIndex
The index of the drop target in the original sibling list.
position
Either 'before' or 'after' the target.
Return value
The insertion index in the sibling list after the selected items are removed, or null for an invalid or unchanged move.
Compatibility
See also
Packages Docs Docs Sdk Index (`packages/docs/docs/sdk/index.mdx`)
image: /generated/articles-docs-sdk-index.png sidebar_label: Overview title: '@remotion/sdk' crumb: '@remotion/sdk'
@remotion/sdk
Build a composition preview and layer list for a Remotion authoring interface. The package combines `` playback with registered sequence data, selection, and synchronized hover.
:::warning
Experimental API: This package is not stable. Its public API may change without a major version bump.
:::
Installation
Install @remotion/player as well. Keep the Remotion packages on the same version.
Basic example
Pass the same controller to <Canvas> and your layer list. showOutlines enables hover and selection on the composition.
/* Detailed source-code truncated for AI context efficiency. */The timeline contains registered <Sequence> and other sequence tracks from the mounted composition. The Canvas does not edit source files or provide timeline controls; your interface owns those actions.
For a timeline reorder gesture, getCanvasSequenceReorderSelection() chooses the dragged sequence group. getCanvasSequenceReorderInsertionIndex() identifies valid drop positions. Persist the result with reorderNodes().
Selection identity
The built-in getCanvasSequenceNodePathInfo() uses a source identity when available. Otherwise it falls back to a mounted sequence ID, which can change after a remount.
If your editor has the source code, register the source node of each sequence with setSequenceNodePaths(). For projects compiled with @remotion/browser-bundler, getCanvasSequenceSourceLocation() returns the file and position of each sequence's JSX element, which getNodes() maps to a node path. Alternatively, pass a custom resolveSequenceNodePathInfo to <Canvas> and use the same resolver for layer items. Return null for tracks that should not be selectable.
An outline requires a registered DOM element. A <Sequence layout="none"> has no outline of its own.
Editing
The Canvas exposes the controls of each mounted element: its interactivity schema and current prop values. Use them to build an inspector, and write changes to the source with @remotion/codemods.
While a value is being dragged, controller.overrides previews it on the canvas immediately. Persist the final value when the gesture ends, then clear the override.
Pass onSequencePropsChange to <Canvas> to let users move elements by dragging their outlines or pressing the arrow keys. The Canvas previews the movement itself and reports the final style.translate values to the callback. With getSequencePropStatuses, it respects how the source is written: computed values cannot be moved and keyframed values receive a keyframe.
Keyframes
Props animated with interpolate() are reported as keyframed by getNodeProps(). The package converts between the frame clock of the interpolation and the composition timeline, so a timeline can show and edit those keyframes like the Remotion Studio does.
getCanvasKeyframes() places the keyframes of a prop on the timeline. getCanvasKeyframeToggle() describes a keyframe button at the playhead and returns the change that adds or removes a keyframe there, while getCanvasPropValueAtFrame() reads the animated value for an inspector. startCanvasKeyframeDrag() moves keyframes with the pointer, previewing the result through controller.overrides. Every edit is a CanvasKeyframeChange whose operation you pass to updateNodeKeyframes().
Between two keyframes, getCanvasKeyframeEasingSegments() describes the segments a timeline can draw and select, and getCanvasKeyframeEasingChange() sets the easing of one, with canvasKeyframeEasingPresets for a picker. getCanvasKeyframeSettings() and getCanvasKeyframeSettingsChange() read and write the extrapolation, output mode and posterize of the interpolation. getCanvasKeyframeChangeOverride() turns any change into an override, so the canvas shows it before the source is updated.
APIs
import {TableOfContents} from './table-of-contents';
License
Packages Docs Docs Sfx Index (`packages/docs/docs/sfx/index.mdx`)
image: /generated/articles-docs-sfx-index.png crumb: API title: '@remotion/sfx'
@remotion/sfx
Sound effect URLs for general use.
Available as a package or from loading through a URL directly.
Normalized volume for the peak to be at -3dB.
All files can be used without attribution, but the attribution is available on the detail page of a sound.
import {TableOfContents} from './table-of-contents';
Exports
License
NPM package: MIT
See license of each sound effect by clicking on it.
Packages Docs Docs Shapes Index (`packages/docs/docs/shapes/index.mdx`)
image: /generated/articles-docs-shapes-index.png title: "@remotion/shapes" crumb: "SVG component library"
import {TableOfContents} from './table-of-contents';
A package providing utility functions for generate SVG shapes.
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs
defaultValue="npm"
values={[
{ label: 'npm', value: 'npm', },
{ label: 'pnpm', value: 'pnpm', },
{ label: 'yarn', value: 'yarn', },
]
}>
npm i @remotion/shapespnpm i @remotion/shapesyarn add @remotion/shapesFunctions
License
MIT
Packages Docs Docs Starburst Index (`packages/docs/docs/starburst/index.mdx`)
image: /generated/articles-docs-starburst-index.png id: starburst-api slug: /starburst/api title: '@remotion/starburst' crumb: API
~~@remotion/starburst~~
:::info Deprecated@remotion/starburst is deprecated and will no longer be published starting with Remotion 5.0. Migrate to starburst() from @remotion/effects/starburst. The <Starburst> component will not be moved to @remotion/effects.
:::
Starburst ray effect for Remotion videos.
import {TableOfContents} from './table-of-contents';
APIs
License
Packages Docs Docs Studio Protocol Index (`packages/docs/docs/studio-protocol/index.mdx`)
image: /generated/articles-docs-studio-protocol-index.png title: 'Remotion Studio Protocol' crumb: '@remotion/studio-protocol'
@remotion/studio-protocol
With this package, you can create payloads for passing content to Remotion Studio.
Capabilities
Installing Remotion Elements
Websites can provide Elements to a Studio either using drag-and-drop or using an installation dialog.
createElementPayload().setStudioDragData(), or send a signal to a Studio using installInStudio().
| Method | Benefits | Tradeoffs |
|---|---|---|
| Drag-and-drop | The user chooses the exact Studio tab, timeline position, and canvas position. | Studio labels the source as unverified. |
| Installation dialog | The requesting website is shown. Remotion attempts to bring the Studio to the foreground. | The most recently focused tab is selected, or the sole writable tab if none has been focused. |
Adding an Element Library
Using addElementLibraryToStudio() you can request to add an Element Library to the Studio.
Previewing Elements
Using buildOpenInRemotionNewUrl(), you can open your Element in remotion.dev/new.
APIs
import {TableOfContents} from './table-of-contents';
Security
Learn about the confirmation and origin policy.
License
See also
Packages Docs Docs Tailwind V4 Overview (`packages/docs/docs/tailwind-v4/overview.mdx`)
image: /generated/articles-docs-tailwind-v4-overview.png id: overview sidebar_label: Overview title: '@remotion/tailwind-v4'
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {ExperimentalBadge} from '../../components/Experimental';
import {TableOfContents} from './TableOfContents';
This package provides utilities useful for integrating TailwindCSS v4 with Remotion, as documented on our TailwindCSS page.
Installation
Install @remotion/tailwind-v4 as well as TailwindCSS dependencies.
Override the bundler config by using enableTailwind().
import {Config} from '@remotion/cli/config';
import {enableTailwind} from '@remotion/tailwind-v4';
Config.overrideBundlerConfig((currentConfiguration) => {
return enableTailwind(currentConfiguration);
});Then follow the remaining set up steps from the TailwindCSS page.
APIs
Packages Docs Docs Tailwind Overview (`packages/docs/docs/tailwind/overview.mdx`)
image: /generated/articles-docs-tailwind-overview.png id: tailwind sidebar_label: Overview title: '@remotion/tailwind'
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {ExperimentalBadge} from '../../components/Experimental';
import {TableOfContents} from './TableOfContents';
:::note
This is documentation for enabling Tailwind v3.
For the Tailwind v4 version of this site, see the Tailwind v4 documentation.
:::
This package provides utilities useful for integrating TailwindCSS with Remotion, as documented on our TailwindCSS page.
Installation
Install @remotion/tailwind as well as TailwindCSS dependencies.
Override the bundler config by using enableTailwind().
import {Config} from '@remotion/cli/config';
import {enableTailwind} from '@remotion/tailwind';
Config.overrideBundlerConfig((currentConfiguration) => {
return enableTailwind(currentConfiguration);
});Then follow the remaining set up steps from the TailwindCSS page.
APIs
Packages Docs Docs Timeline Index (`packages/docs/docs/timeline/index.mdx`)
image: /generated/articles-docs-timeline-index.png title: Remotion Timeline
import {TableOfContents} from './TableOfContents';
<Timeline>
A paid customizable timeline component that integrates seamlessly with Remotion Player.
It's perfect for builders who need a layer-based editing interface for their video editing app.
You can buy the timeline component on remotion.pro.
Key Features
Interface:
- Multiple track support with drag-and-drop functionality (between and within tracks)
- Timeline item selection and manipulation
- Keyboard shortcuts for common actions
CanvasCompositionfor rendering the timeline state in the Remotion Player- Zoomable timeline and
<ZoomSlider>component to control the zoom level
Customization:
- Theming with variables (Tailwind CSS V4 and V3)
- Extensible state management
License
The source code of the Remotion Timeline is governed by the Remotion License and its own specific license.
Remotion, as an underlying technology of the Remotion Timeline, is free to use for individuals and small companies. If you fall into this category, you can buy the Remotion Timeline as a one-time purchase. If you are a larger company, you must subscribe to the Company License. Read the Terms & Conditions.
The Remotion Timeline License can be seen in the Remotion Store Page as well as accessible through the dedicated GitHub repository after purchase.
Packages Docs Docs Transitions Index (`packages/docs/docs/transitions/index.mdx`)
image: /generated/articles-docs-transitions-index.png sidebar_label: Overview title: '@remotion/transitions'
@remotion/transitions
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {TableOfContents} from './table-of-contents';
This package provides the `` component for transitioning between two scenes as well as timing presets.
Installation
API
License
See also
Packages Docs Docs Vercel Index (`packages/docs/docs/vercel/index.mdx`)
id: vercel-api slug: /vercel/api title: '@remotion/vercel' crumb: 'API'
import {TableOfContents} from './table-of-contents';
@remotion/vercel
:::warning
Experimental package: We reserve the right to make breaking changes in order to correct bad design decisions until this notice is gone.
:::
Render Remotion videos on Vercel Sandbox.
This package requires @vercel/sandbox as a peer dependency.
APIs
License
Packages Docs Docs Video Matting Index (`packages/docs/docs/video-matting/index.mdx`)
image: /generated/articles-docs-video-matting-index.png title: '@remotion/video-matting' crumb: 'Separate a video into layers'
@remotion/video-matting
Separate a video into opaque base and transparent foreground layers, locally in the browser or Node.js using WebGPU.
import {TableOfContents} from './table-of-contents';
Installation
Studio
Remotion Studio offers Remove background for a selected video. It replaces the video's source with a transparent WebM. Duplicate the layer first if you want to keep the original alongside it.
For programmatic base and foreground outputs, see separateVideoLayers().
Model hosting
We noticed that hosting the models on R2 leads to faster downloading than through Hugging Face directly.
We mirrored the models to remotion.media, keeping them byte-identical.
We also notified Hugging Face and they are investigating the issue. We may migrate back to the official hosting in the future.
APIs
Requirements
A GPU is needed for this.
Use canUseVideoMatting() to check whether your system can use video matting.
The browser must also be able to decode the input video and encode VP9 with alpha through WebCodecs.separateVideoLayers() checks these media capabilities for the selected input.
License
The package is MIT licensed.
Models retain the licenses listed under getAvailableModels().
Packages Docs Docs Videos Index (`packages/docs/docs/videos/index.mdx`)
image: /generated/articles-docs-videos-index.png title: Embedding videos into Remotion sidebar_label: Adding a video crumb: 'How To'
You can embed existing videos into Remotion by using the <Video> from @remotion/media component.
import React from 'react';
import {Video} from '@remotion/media';
export const MyComp: React.FC = () => {
return <Video src="https://remotion.media/BigBuckBunny.mp4" />;
};Using a local file
Put a file into the public folder and reference it using staticFile().
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video src={staticFile('video.mp4')} />;
};Trimming
By using the trimBefore prop, you can remove the first few seconds of the video.
In the example below, the first two seconds of the video are skipped (assuming a composition FPS of 30).
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video src={staticFile('video.mp4')} trimBefore={60} />;
};Use durationInFrames to select how many source frames should play.
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video src={staticFile('video.mp4')} trimBefore={60} durationInFrames={60} />;
};Delaying
Use the from prop to delay the appearance of a video.
In the example below, the video will start playing at frame 60.
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video from={60} src={staticFile('video.mp4')} />;
};Size and Position
You can size and position the video using CSS.
You'll find the properties width, height, position, left, top, right, bottom, margin, aspectRatio and objectFit useful.
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return (
<Video
src={staticFile('video.mp4')}
style={{
width: 640,
height: 360,
position: 'absolute',
top: 100,
left: 100,
}}
/>
);
};Volume
You can set the volume of the video using the volume prop.
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video src={staticFile('video.mp4')} volume={0.5} />;
};You can also mute a video using the muted prop.
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video src={staticFile('video.mp4')} muted />;
};See Using Audio for more ways you can control volume.
Speed
You can use the playbackRate prop to change the speed of the video.
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video src={staticFile('video.mp4')} playbackRate={2} />;
};This only works if the speed is constant. See also: Changing the speed of a video over time.
Looping
Use the loop prop to restart the video when it reaches the end.
import React from 'react';
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
export const MyComp: React.FC = () => {
return <Video src={staticFile('video.mp4')} loop />;
};To learn how looping interacts with trimBefore and durationInFrames, see Timing and trimming.
GIFs
See: Using GIFs
See also
Packages Docs Docs Web Renderer Index (`packages/docs/docs/web-renderer/index.mdx`)
image: /generated/articles-docs-web-renderer-index.png sidebar_label: Overview title: '@remotion/web-renderer' crumb: API
This package allows you to render videos and stills directly in the browser, without requiring server-side infrastructure.
The API is stable from
Key differences from server-side rendering
Unlike server-side rendering with @remotion/renderer, client-side rendering:
- Runs in the browser instead of Node.js
- Encodes with WebCodecs using Mediabunny instead of FFmpeg
- Limited to a subset of tags and CSS properties - see limitations
- No bundling step - takes components and video config directly
Installation
API
import {TableOfContents} from './TableOfContents';
See also
- Client-side rendering overview
- How client-side rendering works
- Limitations
- Telemetry
- Server-side rendering
Packages Docs Docs Webcodecs Index (`packages/docs/docs/webcodecs/index.mdx`)
image: /generated/articles-docs-webcodecs-index.png sidebar_label: Overview title: '@remotion/webcodecs'
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {TableOfContents, WebCodecsGuide} from './TableOfContents';
@remotion/webcodecs
:::warning
We are phasing out Remotion WebCodecs and are moving to Mediabunny!
:::
This package provides APIs for converting videos in the browser.
It leverages @remotion/media-parser to parse the video and audio data, and then uses the WebCodecs API to encode the video.
import {LicenseDisclaimer} from './LicenseDisclaimer';
import {UnstableDisclaimer} from './UnstableDisclaimer';
What can you do with this package?
In browsers that implement WebCodecs, you can use this package to:
- Convert videos from one format to another (From .mp4, .webm, .mov, .mkv, .m3u8, .ts, .avi, .mp3, .flac, .wav, .m4a, .aac to .mp4, .webm, .wav)
- Rotate videos
- Efficiently extract frames from a video
- Extract audio from a video
- Manipulate the pixels of a video
- Fix videos that were recorded with
MediaRecorder - Soon: Compress, trim, crop videos
Is it fast?
Unlike solutions which leverage WebAssembly, WebCodecs have full access to GPU acceleration.
You can expect vastly faster processing than with online converters or WebAssembly-based processing.
See a comparison here.
💼 License Disclaimer
🚧 Unstable API Warning
Installation
Guide
APIs
The following APIs are available:
Packages Docs Docs Whisper Web Index (`packages/docs/docs/whisper-web/index.mdx`)
image: /generated/articles-docs-whisper-web-index.png title: '@remotion/whisper-web' crumb: 'Transcribe audio in browser'
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
~~@remotion/whisper-web~~
:::info Deprecated@remotion/whisper-web is deprecated and will no longer be published starting with Remotion 5.0. Migrate to @remotion/whisper-webgpu, which uses WebGPU and does not require cross-origin isolation. Existing 4.x versions remain available.
:::
Similar to @remotion/install-whisper-cpp but for the browser. Allows you to transcribe audio locally in the browser, with the help of WASM.
import {TableOfContents} from './whisper-web';
Installation
Required configuration
@remotion/whisper-web uses a WebAssembly (WASM) backend that requires SharedArrayBuffer support. To enable this functionality, you need to configure cross-origin isolation headers in your application. This is a security requirement for using SharedArrayBuffer in modern browsers.
Vite
To use @remotion/whisper-web with Vite, you need to make two important changes:
- Exclude the package from Vite's dependency optimization to prevent known issues
- Configure the required security headers for
SharedArrayBuffersupport
import {defineConfig} from 'vite';
export default defineConfig({
optimizeDeps: {
// turn off dependency optimization: https://github.com/vitejs/vite/issues/11672#issuecomment-1397855641
exclude: ['@remotion/whisper-web'],
},
// required by SharedArrayBuffer
server: {
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
},
},
// ...
});Example usage
import {transcribe, canUseWhisperWeb, resampleTo16Khz, downloadWhisperModel} from '@remotion/whisper-web';
const file = new File([], 'audio.wav');
const modelToUse = 'tiny.en';
const {supported, detailedReason} = await canUseWhisperWeb(modelToUse);
if (!supported) {
throw new Error(`Whisper Web is not supported in this environment: ${detailedReason}`);
}
console.log('Downloading model...');
await downloadWhisperModel({
model: modelToUse,
onProgress: ({progress}) => console.log(`Downloading model (${Math.round(progress * 100)}%)...`),
});
console.log('Resampling audio...');
const channelWaveform = await resampleTo16Khz({
file,
onProgress: (p) => console.log(`Resampling audio (${Math.round(p * 100)}%)...`),
});
console.log('Transcribing...');
const {transcription} = await transcribe({
channelWaveform,
model: modelToUse,
onProgress: (p) => console.log(`Transcribing (${Math.round(p * 100)}%)...`),
});
console.log(transcription.map((t) => t.text).join(' '));Functions
License
MIT
Packages Docs Docs Whisper Webgpu Index (`packages/docs/docs/whisper-webgpu/index.mdx`)
image: /generated/articles-docs-whisper-webgpu-index.png title: '@remotion/whisper-webgpu' crumb: 'Transcribe audio locally'
@remotion/whisper-webgpu
Transcribe audio locally in the browser or Node.js using timestamped Whisper models and WebGPU through Transformers.js, and convert the result to @remotion/captions.
import {TableOfContents} from './table-of-contents';
Installation
Example
import {clearStaleModels, downloadWhisperModel, resampleTo16Khz, toCaptions, transcribe} from '@remotion/whisper-webgpu';
export const transcribeFile = async (file: File) => {
await clearStaleModels();
await downloadWhisperModel({model: 'small.en'});
const channelWaveform = await resampleTo16Khz({file});
const transcription = await transcribe({
channelWaveform,
model: 'small.en',
language: 'en',
});
const {captions} = toCaptions({whisperWebGpuOutput: transcription});
return captions;
};Model hosting
We noticed that hosting the models on R2 leads to faster downloading than through Hugging Face directly.
We mirrored the models to remotion.media, keeping them byte-identical.
We also notified Hugging Face and they are investigating the issue. We may migrate back to the official hosting in the future.
On the server
See @remotion/whisper-webgpu in Node.js for a complete Node.js example.
APIs
Requirements
You obviously need a GPU.
Use canUseWhisperWebGpu() to determine if it is supported.
License
MIT
Packages Docs Docs Zod Types Index (`packages/docs/docs/zod-types/index.mdx`)
image: /generated/articles-docs-zod-types-index.png sidebar_label: Overview title: '@remotion/zod-types' crumb: Schema
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {ZodTypesTableOfContents} from './TableOfContents';
Includes utility types and Remotion-specific types for Zod.
:::note
Since Remotion v4.0.426, @remotion/zod-types is based on Zod v4.
If you want, you can now upgrade to Zod v4.
If you want to stay on Zod 3.22.3 as previously required by Remotion, use @remotion/zod-types-v3 instead of @remotion/zod-types.
:::
Installation
API
License
Packages Docs Elements Audio Index (`packages/docs/elements/audio/index.mdx`)
title: Audio
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Audio
Packages Docs Elements Backgrounds Index (`packages/docs/elements/backgrounds/index.mdx`)
title: Backgrounds
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Backgrounds
Packages Docs Elements Captions Index (`packages/docs/elements/captions/index.mdx`)
title: Captions
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Captions
How to use
Transcribing in the Studio
Style selection is available from
Importing captions into Studio
Supported formats:
- Remotion
Caption[]JSON - SRT
- ElevenLabs Speech-to-Text or segmented JSON
- OpenAI Whisper JSON transcript (verbose mode must be on)
Packages Docs Elements Commerce Index (`packages/docs/elements/commerce/index.mdx`)
title: Effects
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Effects
Packages Docs Elements Data Index (`packages/docs/elements/data/index.mdx`)
title: Charts & Data
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Charts & Data
Packages Docs Elements Layouts Index (`packages/docs/elements/layouts/index.mdx`)
title: Layouts
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Layouts
Packages Docs Elements Maps Index (`packages/docs/elements/maps/index.mdx`)
title: Maps
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Maps
Packages Docs Elements Overlays Index (`packages/docs/elements/overlays/index.mdx`)
title: Overlays
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Overlays
Packages Docs Elements Storytelling Index (`packages/docs/elements/storytelling/index.mdx`)
title: Storytelling
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Storytelling
Packages Docs Elements Text Index (`packages/docs/elements/text/index.mdx`)
title: Text Effects
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
Text Effects
Packages Docs Elements Youtube Index (`packages/docs/elements/youtube/index.mdx`)
title: YouTube
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';
YouTube
Packages Docs Docs Cli Browser Index (`packages/docs/docs/cli/browser/index.mdx`)
image: /generated/articles-docs-cli-browser-index.png title: npx remotion browser crumb: '@remotion/cli' sidebar_label: 'browser'
import {TableOfContents} from './table-of-contents';
npx remotion browser
Commands for managing the browser used by Remotion.
Commands
See also
Packages Docs Docs Lambda Without Iam Index (`packages/docs/docs/lambda/without-iam/index.mdx`)
image: /generated/articles-docs-lambda-without-iam-index.png title: Using Lambda with IAM roles sidebar_label: 'With IAM Roles' crumb: 'Lambda without IAM'
import {UserPolicy} from '../../../components/lambda/user-permissions.tsx';
As documented on the Permissions page, the default way of using Remotion Lambda involves creating a Remotion user and assign it policies.
These policies give permission to Lambda to render a video with renderMediaOnLambda(). These credentials are considered long-term which is less secure and are disallowed in some companies.
Additionally, there might be requirements to execute renderMediaOnLambda() on services such as Lambda, EC2, and other computing services where the use of long-term credentials is not an option.
AWS offers the concept of IAM Roles as a solution to the problem above. When a role is assigned to an AWS service, AWS gives any elevated privileges based on the attached policies and the role is empowered to execute activities such as putting a file to an S3 bucket.
The role is given temporary AWS credentials such as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN to generate the video. This approach enhances security as there are no long-term credentials lingering around and the need to keep track of their rotation is eliminated.
The steps below provide authorization for the Lambda function to execute renderMediaOnLambda() without permission issues.
Prerequisites
- A deployed Lambda function running on AWS. An example using
CDKis availablehere. It gives you an idea how to callrenderMediaOnLambda()inside another Lambda function. The function is triggered by API Gateway. The example assumes that you have knowledge of usingCDK, a write up is also available. - An execution role that is assigned to the Lambda function.
- A user policy with the necessary user permissions.
Setup
1. Create role policy
Go to the IAM policies section in the AWS Management Console
Click on "Create policy"
Click on JSON
Copy the JSON policy template below:
Show full role permissions JSON file for latest Remotion Lambda version
Click next. On the tags page, you don't need to fill in anything. Click next again.
Give the policy the name
remotion-executionrole-policy. The other fields can be left as they are.
2. Assign the policy to the Lambda execution role
- Go to the AWS Management Console
- Navigate to Lambda (change to your function region)
- Select Functions
- Select your Lambda function
- Select the "Configuration" tab
- Select the "Permissions" tab
- Click the role under
Execution role - When redirected, click "Permissions" tab
- Click on
Add permissions - Attach policy
- Find the policy, i.e.
remotion-executionrole-policy - Select the policy
- Click the
Attach policiesbutton.
With the assignment of the policy to the Lambda execution role, it is now empowered to execute the renderMediaOnLambda() API without permission issues.
In the background, when the Lambda function is executed, it is provided with environment variables such as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN that has temporary permission to AWS resources that renderMediaOnLambda() requires to render the video. The elevated powers come from the policy statements in remotion-executionrole-policy.
:::note
This procedure can be also applied to other AWS compute services such as EC2, Fargate etc..
:::
Render into a different bucket
Optionally, if you want to move the video to another S3 bucket after it is rendered, the Lambda function also needs permission to do so. The process is similar to the previous steps, but you will need to create a new policy statement that defines the bucket that Lambda needs to transfer the rendered video to.
Example
Use the outName property to select a different bucket. See: Custom output destination
import {renderMediaOnLambda} from '@remotion/lambda/client';
const {bucketName, renderId} = await renderMediaOnLambda({
region: 'us-east-1',
functionName: 'remotion-render-bds9aab',
composition: 'MyVideo',
serveUrl: 'https://remotionlambda-qg35eyp1s1.s3.eu-central-1.amazonaws.com/sites/bf2jrbfkw',
codec: 'h264',
privacy: 'no-acl',
outName: {
key: 'my-output',
bucketName: 'output-bucket',
},
});In the example above, renderMediaOnLambda() is configured to output the rendered video to the output-bucket bucket. The following steps grant the Remotion Lambda execution role access to this bucket.
Steps
- Again we assign the policy to the Lambda execution role. Go to the AWS Management Console and:
- Navigate to Lambda (change to your function region)
- Functions
- Select your Lambda function
- Configuration tab
- Permissions tab
- Click the role under
Execution role - When redirected, click Permissions tab
- Click on
Add permissions - Click "Create inline policy"
- Click the "JSON" tab
Add the policy below to grant s3:PutObject on the destination bucket's objects. This is the minimum destination policy for the example above with Remotion 4.0.535 or later. See write-only AWS S3 buckets.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:PutObject"],
"Resource": ["arn:aws:s3:::{bucketname}/*"],
"Effect": "Allow"
}
]
}- Replace
{bucketname}with the name of the bucket where you want to move the rendered video to. - Click on
Review policy - Click
Save changes
The Lambda function can now move the rendered video to the other bucket when the render process is completed.
Optionally grant s3:GetObject on arn:aws:s3:::{bucketname}/* and s3:ListBucket on arn:aws:s3:::{bucketname} to detect existing output before rendering and recover completion if the final progress update is missing. For compatibility with earlier Remotion versions, grant both permissions.
If you set privacy to "public" or "private" instead of "no-acl", also grant s3:PutObjectAcl on arn:aws:s3:::{bucketname}/*.
See also
Packages Docs Docs Player Drag And Drop Index (`packages/docs/docs/player/drag-and-drop/index.mdx`)
image: /generated/articles-docs-player-drag-and-drop-index.png sidebar_label: 'Drag & Drop' title: 'Drag & Drop in the Remotion Player' crumb: '@remotion/player' no_ai: true
import {DragAndDropDemo} from './Demo';
The Remotion Player supports reacting to mouse events allowing for building interactions on the canvas.
Try to drag and resize the elements below.
General considerations
Pointer events work mostly just like in regular React.
Disable the controls prop to disable any obstructing elements. You can render Playback controls outside of the Player.
The Player might have CSS scale() applied to it.
If you measure elements, you need to divide by the scale obtained by useCurrentScale().
You can pass state update functions via inputProps to the Player.
Alternatively, wrapping the Player in React Context also works.
Example
export type Item = {
id: number;
durationInFrames: number;
from: number;
height: number;
left: number;
top: number;
width: number;
color: string;
isDragging: boolean;
};/* Detailed source-code truncated for AI context efficiency. */import React, {useMemo} from 'react';
import {Interactive} from 'remotion';
import type {Item} from './item';
export const Layer: React.FC<{
item: Item;
}> = ({item}) => {
const style: React.CSSProperties = useMemo(() => {
return {
backgroundColor: item.color,
position: 'absolute',
left: item.left,
top: item.top,
width: item.width,
height: item.height,
};
}, [item.color, item.height, item.left, item.top, item.width]);
return (
<Interactive.Div
from={item.from}
durationInFrames={item.durationInFrames}
style={style}
/>
);
};/* Detailed source-code truncated for AI context efficiency. */import React from 'react';
import {SelectionOutline} from './SelectionOutline';
import type {Item} from './item';
const displaySelectedItemOnTop = (
items: Item[],
selectedItem: number | null,
): Item[] => {
const selectedItems = items.filter((item) => item.id === selectedItem);
const unselectedItems = items.filter((item) => item.id !== selectedItem);
return [...unselectedItems, ...selectedItems];
};
export const SortedOutlines: React.FC<{
items: Item[];
selectedItem: number | null;
changeItem: (itemId: number, updater: (item: Item) => Item) => void;
setSelectedItem: React.Dispatch<React.SetStateAction<number | null>>;
}> = ({items, selectedItem, changeItem, setSelectedItem}) => {
const itemsToDisplay = React.useMemo(
() => displaySelectedItemOnTop(items, selectedItem),
[items, selectedItem],
);
const isDragging = React.useMemo(
() => items.some((item) => item.isDragging),
[items],
);
return itemsToDisplay.map((item) => {
return (
<SelectionOutline
key={item.id}
changeItem={changeItem}
item={item}
setSelectedItem={setSelectedItem}
selectedItem={selectedItem}
isDragging={isDragging}
/>
);
});
};import React, {useCallback} from 'react';
import {AbsoluteFill} from 'remotion';
import type {Item} from './item';
import {Layer} from './Layer';
import {SortedOutlines} from './SortedOutlines';
export type MainProps = {
readonly items: Item[];
readonly setSelectedItem: React.Dispatch<React.SetStateAction<number | null>>;
readonly selectedItem: number | null;
readonly changeItem: (itemId: number, updater: (item: Item) => Item) => void;
};
const outer: React.CSSProperties = {
backgroundColor: '#eee',
};
const layerContainer: React.CSSProperties = {
overflow: 'hidden',
};
export const Main: React.FC<MainProps> = ({
items,
setSelectedItem,
selectedItem,
changeItem,
}) => {
const onPointerDown = useCallback(
(e: React.PointerEvent) => {
if (e.button !== 0) {
return;
}
setSelectedItem(null);
},
[setSelectedItem],
);
return (
<AbsoluteFill style={outer} onPointerDown={onPointerDown}>
<AbsoluteFill style={layerContainer}>
{items.map((item) => {
return <Layer key={item.id} item={item} />;
})}
</AbsoluteFill>
<SortedOutlines
selectedItem={selectedItem}
items={items}
setSelectedItem={setSelectedItem}
changeItem={changeItem}
/>
</AbsoluteFill>
);
};/* Detailed source-code truncated for AI context efficiency. */Let's build the demo above.
The following features have been defined as goals:
- Ability to freely position and resizing the squares with the mouse.
- One item can be selected at a time. Clicking on an empty space will deselect the item.
- Items can not overflow the container, however the blue outlines can overflow the container.
1 Data structure
Create a TypeScript type that describes the shape of your item.
In this example we store an identifier id, start and end frame from anddurationInFrames, the position left, top, width and height, a
background color as well as a boolean isDragging to fine-tune the behavior while dragging.
// @filename: item.ts
// ---cut---
// @include: itemIf you like to support different types of items (solid, video, image),
see here.
2 Item rendering
Declare a React component that renders the item.
// @filename: item.ts
// @include: item
// @filename: Layer.tsx
// ---cut---
// @include: LayerBy passing from and durationInFrames to Interactive.Div, the item is only displayed from from until from + durationInFrames.
Interactive.Div renders the draggable `` directly, without an additional layout wrapper.
3 Outline rendering
Create a React component that renders an outline when an item isselected or hovered.
// @filename: ResizeHandle.tsx
// @include: ResizeHandle
// @filename: item.ts
// @include: item
// @filename: SelectionOutline.tsx
// ---cut---
// @include: SelectionOutline// @filename: item.ts
// @include: item
// @filename: ResizeHandle.tsx
// ---cut---
// @include: ResizeHandleZ-indexing: These elements will later in this tutorial be rendered on top of all layers so that they are able to accept mouse events.
Clicking on one of these elements will select the underlying item.
Scaling: The `` has a CSS scale transform applied to it.
Since we consume the coordinates of the pointer events, we need to divide them by useCurrentScale() to get the correct position.
The thickness of the borders will also be affected by the scale, so we need to divide them by the scale too.
Pointer event handling: On any pointerdown event, we call e.stopPropagation() prevent the event from bubbling up.
Later, we will treat any event that bubbles up as an click on an empty space and deselect the item.
We also don't do any action if e.button !== 0. This prevents a bug where the item moves after a right click.
We add userSelect: 'none' to disable the native selection and drag behavior of the browser.
We also add touchAction: 'none' to disable scrolling the page on mobile while dragging.
We keep track if the item is being dragged by using the isDragging property and disable the hover effect while an item is being dragged.
4 Sorting outlines
Let's create a component that renders all outlines.
The item which gets rendered as last element will be on top of all other items.
The item that is selected should be rendered on top of all other items because it is the item that is responsive to mouse events.
We render the selected outlines last. This ensures that the resize handles are always on top.
This logic only applies to the outlines, not the actual layers.
// @filename: item.ts
// @include: item
// @filename: ResizeHandle.tsx
// @include: ResizeHandle
// @filename: SelectionOutline.tsx
// @include: SelectionOutline
// @filename: SortedOutlines.tsx
// ---cut---
// @include: SortedOutlines5 Putting it together
Next, we create a main component that renders the items and the outlines.
// @filename: item.ts
// @include: item
// @filename: ResizeHandle.tsx
// @include: ResizeHandle
// @filename: SelectionOutline.tsx
// @include: SelectionOutline
// @filename: SortedOutlines.tsx
// @include: SortedOutlines
// @filename: Layer.tsx
// @include: Layer
// @filename: Main.tsx
// ---cut---
// @include: MainZ-indexing: We render the layers first and then the outlines. This means the outlines get rendered on top the items.
Overflow behavior: Note that we apply a different overflow behavior to the layers and the outlines.
We hide the overflow of the layers, but show the overflow of the outlines.
This is a UI behavior that is similar to Figma frames.
Click handling: We also listen to pointerdown events on the canvas.
Any event that was not stopped using e.stopPropagation() before will be treated as a click on an empty space and results in deselecting the item.
6 Rendering the Player
We can now render the Main component that we created in the Remotion Player.
// @filename: item.ts
// @include: item
// @filename: ResizeHandle.tsx
// @include: ResizeHandle
// @filename: SelectionOutline.tsx
// @include: SelectionOutline
// @filename: SortedOutlines.tsx
// @include: SortedOutlines
// @filename: Layer.tsx
// @include: Layer
// @filename: Main.tsx
// @include: Main
// @filename: Demo.tsx
// ---cut---
// @include: DemoWe omit the controls prop to disable the built-in controls.
You can add custom controls outside the Player.
We add the overflowVisible prop to make the outlines visible if they go outside the canvas.
Remember that we've hidden the overflow of the layers itself because it would also not be visible in the final video.
We've now implemented thoughtful drag and drop interactions!
See also
Packages Docs Docs Recorder Record Index (`packages/docs/docs/recorder/record/index.mdx`)
image: /generated/articles-docs-recorder-record-index.png title: Record using the interface sidebar_label: Using the interface crumb: Recorder
import {RecordingButton} from '../../../components/recorder/RecordButton';
The Recorder ships with its own recording interface.
From it, you can record a clip and add it as a scene to your project.
If you haven't done so, start the Remotion Recorder:
bun run devA Vite app will listen on http://localhost:4000.
Open this URL in the browser.
Give the page access to the webcam and microphone.
Select the composition
Recordings need to be stored in a subfolder of public named after the composition ID.
For example, if you want to record for the composition my-video, recordings will be stored under public/my-video.
In the top right corner, use the dropdown to "Create a new folder".
Use the ID of the composition you want to record for as the folder name.
The folder will be created and your subsequent recordings will be saved in this folder.
Select sources
In the top left panel, select your webcam and microphone.
In the top right panel, optionally select the screen you want to record.
You can record more sources, but out of the box, the Remotion Recorder does not do anything with them.
Before starting
Say "Test One Two Three" and ensure the volume meter is not going into the red zone.
Make sure you are centered in the video. You can enable the crop target overlay to see how the video will crop when miniaturized.
Prefer making short recordings. You're less likely to make a mistake and it's easy to stitch them together.
There is no countdown – The recording will start immediately.
However, the Recorder will later automatically trim away the silence in the beginning.
Take a deep breath and think of what you are about to say and show.
You're ready to record!
Start the recording
To start recording, press <kbd>R</kbd> or click{' '} Once you are done with the scene, click
.
Selecting a take
After you have recorded a scene and you are happy with your take, click "Use this take".
The server will then do the following:
- Convert the videos from WebM to MP4
- Put them into your project under
public/[composition-id]. - Caption the files with Whisper.cpp
Discard a take
If you have taken a recording that you don't want to use, click "Discard and retake" to clear the existing recording from memory.
record.remotion.dev
You can also use the hosted version of the recoding interface at record.remotion.dev.
It will not allow you to select a save destination, but instead download the recordings to your Downloads folder.
They will have names like webcam171234567890.mp4 and display171234567890.mp4.
To copy the recordings to your Remotion project, first open copy.ts in your code editor. Set the prefix at the top of your file to the ID of the composition that you gave when you first created a new video.
const prefix = '<id-of-your-composition>';Then run the copy.ts script whenever you want to save a take and immediately generate captions:
bun copy.ts
bun sub.tsIf you want to not use a take, just make another recording. The copy.ts script will only take the recordings with the latest timestamp.
Packages Docs Docs Transitions Presentations Index (`packages/docs/docs/transitions/presentations/index.mdx`)
image: /generated/articles-docs-transitions-presentations-index.png title: Presentations crumb: "@remotion/transitions"
A presentation together with a timing forms a transition.
Remotion provides certain presentations out of the box, but you can also create your own.
Table of contents
import { Presentations } from "../../../components/TableOfContents/transitions/presentations";
Packages Docs Docs Transitions Timings Index (`packages/docs/docs/transitions/timings/index.mdx`)
image: /generated/articles-docs-transitions-timings-index.png title: Timings crumb: "@remotion/transitions"
A timing together with a presentation forms a transition.
Remotion provides certain timings out of the box, but you can also create your own.
Available timings
import { Timings } from "../../../components/TableOfContents/transitions/timings";
Getting the duration of a timing
You can get the duration of a transition by calling getDurationInFrames() on the timing:
import { springTiming } from "@remotion/transitions";
springTiming({ config: { damping: 200 } }).getDurationInFrames({ fps: 30 }); // 23Packages Docs Elements Audio Mirrored Spectrum Index (`packages/docs/elements/audio/mirrored-spectrum/index.mdx`)
title: Mirrored Spectrum image: https://remotion.media/elements/audio-mirrored-spectrum-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Mirrored Spectrum
<ElementPage definition={getElementDefinition('audio/mirrored-spectrum')} sourceFile="./mirrored-spectrum.tsx" />
Packages Docs Elements Audio Oscilloscope Index (`packages/docs/elements/audio/oscilloscope/index.mdx`)
title: Oscilloscope image: https://remotion.media/elements/audio-oscilloscope-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Oscilloscope
<ElementPage definition={getElementDefinition('audio/oscilloscope')} sourceFile="./audio-oscilloscope.tsx" />
Packages Docs Elements Audio Waveform Progress Index (`packages/docs/elements/audio/waveform-progress/index.mdx`)
title: Voice Note image: https://remotion.media/elements/audio-waveform-progress-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Voice Note
<ElementPage definition={getElementDefinition('audio/waveform-progress')} sourceFile="./audio-waveform-progress.tsx" />
Packages Docs Elements Backgrounds Liquid Contours Index (`packages/docs/elements/backgrounds/liquid-contours/index.mdx`)
title: Liquid Contours image: https://remotion.media/elements/backgrounds-liquid-contours-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Liquid Contours
<ElementPage definition={getElementDefinition('backgrounds/liquid-contours')} sourceFile="./liquid-contours.tsx" />
Packages Docs Elements Backgrounds Moving Waves Index (`packages/docs/elements/backgrounds/moving-waves/index.mdx`)
title: Moving Waves image: https://remotion.media/elements/backgrounds-moving-waves-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Moving Waves
<ElementPage definition={getElementDefinition('backgrounds/moving-waves')} sourceFile="./moving-waves.tsx" />
Packages Docs Elements Backgrounds Moving Zigzags Index (`packages/docs/elements/backgrounds/moving-zigzags/index.mdx`)
title: Moving Zigzags image: https://remotion.media/elements/backgrounds-moving-zigzags-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Moving Zigzags
<ElementPage definition={getElementDefinition('backgrounds/moving-zigzags')} sourceFile="./moving-zigzags.tsx" />
Packages Docs Elements Backgrounds Notebook Paper Index (`packages/docs/elements/backgrounds/notebook-paper/index.mdx`)
title: Notebook Paper image: https://remotion.media/elements/backgrounds-notebook-paper-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Notebook Paper
<ElementPage definition={getElementDefinition('backgrounds/notebook-paper')} sourceFile="./notebook-paper.tsx" />
Packages Docs Elements Backgrounds Paper Texture Index (`packages/docs/elements/backgrounds/paper-texture/index.mdx`)
title: Paper Texture image: https://remotion.media/elements/backgrounds-paper-texture-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Paper Texture
<ElementPage definition={getElementDefinition('backgrounds/paper-texture')} sourceFile="./paper-texture.tsx" />
Packages Docs Elements Backgrounds Rotating Starburst Index (`packages/docs/elements/backgrounds/rotating-starburst/index.mdx`)
title: Rotating Starburst image: https://remotion.media/elements/backgrounds-rotating-starburst-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Rotating Starburst
<ElementPage definition={getElementDefinition('backgrounds/rotating-starburst')} sourceFile="./rotating-starburst.tsx" />
Packages Docs Elements Captions Basic Captions Index (`packages/docs/elements/captions/basic-captions/index.mdx`)
title: Basic Captions sidebar_label: Basic image: https://remotion.media/elements/captions-basic-captions-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Basic Captions
<ElementPage definition={getElementDefinition('captions/basic-captions')} sourceFile="./basic-captions.tsx" />
Packages Docs Elements Captions Moving Pill Captions Index (`packages/docs/elements/captions/moving-pill-captions/index.mdx`)
title: Moving Pill Captions sidebar_label: Moving Pill image: https://remotion.media/elements/captions-moving-pill-captions-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Moving Pill Captions
<ElementPage definition={getElementDefinition('captions/moving-pill-captions')} sourceFile="./moving-pill-captions.tsx" />
Packages Docs Elements Captions Popping Word Captions Index (`packages/docs/elements/captions/popping-word-captions/index.mdx`)
title: Popping Word Captions sidebar_label: Popping Word image: https://remotion.media/elements/captions-popping-word-captions-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Popping Word Captions
<ElementPage definition={getElementDefinition('captions/popping-word-captions')} sourceFile="./popping-word-captions.tsx" />
Packages Docs Elements Captions Rounded Captions Index (`packages/docs/elements/captions/rounded-captions/index.mdx`)
title: Rounded Captions sidebar_label: Rounded image: https://remotion.media/elements/captions-rounded-captions-preview-694426c4-721c-484f-8a33-79f21d54da5d.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Rounded Captions
Based on the @remotion/rounded-text-box demo.
<ElementPage definition={getElementDefinition('captions/rounded-captions')} sourceFile="./rounded-captions.tsx" />
Packages Docs Elements Captions Word Highlight Captions Index (`packages/docs/elements/captions/word-highlight-captions/index.mdx`)
title: Word Highlight Captions sidebar_label: Word Highlight image: https://remotion.media/elements/captions-word-highlight-captions-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Word Highlight Captions
<ElementPage definition={getElementDefinition('captions/word-highlight-captions')} sourceFile="./word-highlight-captions.tsx" />
Packages Docs Elements Commerce Peel Index (`packages/docs/elements/commerce/peel/index.mdx`)
title: Peel image: https://remotion.media/elements/commerce-peel-preview-57fbe8da-01d3-405c-82f9-84707b1ce6fa.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Peel
<ElementPage definition={getElementDefinition('commerce/peel')} sourceFile="./peel.tsx" />
Packages Docs Elements Commerce Product Collection Index (`packages/docs/elements/commerce/product-collection/index.mdx`)
title: Rotating Cards image: https://remotion.media/elements/commerce-product-collection-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Rotating Cards
<ElementPage definition={getElementDefinition('commerce/product-collection')} sourceFile="./product-collection.tsx" />
Packages Docs Elements Commerce Product Discount Callout Index (`packages/docs/elements/commerce/product-discount-callout/index.mdx`)
title: Wiggling Callout image: https://remotion.media/elements/commerce-product-discount-callout-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Wiggling Callout
<ElementPage definition={getElementDefinition('commerce/product-discount-callout')} sourceFile="./product-discount-callout.tsx" />
Packages Docs Elements Commerce Shine Index (`packages/docs/elements/commerce/shine/index.mdx`)
title: Shine image: https://remotion.media/elements/commerce-shine-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Shine
<ElementPage definition={getElementDefinition('commerce/shine')} sourceFile="./shine.tsx" />
Packages Docs Elements Commerce Tear Index (`packages/docs/elements/commerce/tear/index.mdx`)
title: Tear apart image: https://remotion.media/elements/commerce-tear-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Tear apart
<ElementPage definition={getElementDefinition('commerce/tear')} sourceFile="./tear.tsx" />
Packages Docs Elements Data Horizontal Bar Chart Index (`packages/docs/elements/data/horizontal-bar-chart/index.mdx`)
title: Horizontal Bar Chart image: https://remotion.media/elements/data-horizontal-bar-chart-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Horizontal Bar Chart
<ElementPage definition={getElementDefinition('data/horizontal-bar-chart')} sourceFile="./horizontal-bar-chart.tsx" />
Packages Docs Elements Data Line Chart Index (`packages/docs/elements/data/line-chart/index.mdx`)
title: Line Chart image: https://remotion.media/elements/data-line-chart-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Line Chart
<ElementPage definition={getElementDefinition('data/line-chart')} sourceFile="./line-chart.tsx" />
Packages Docs Elements Data Number Counter Index (`packages/docs/elements/data/number-counter/index.mdx`)
title: Number Counter image: https://remotion.media/elements/data-number-counter-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Number Counter
<ElementPage definition={getElementDefinition('data/number-counter')} sourceFile="./number-counter.tsx" />
Packages Docs Elements Data Pie Chart Index (`packages/docs/elements/data/pie-chart/index.mdx`)
title: Pie Chart image: https://remotion.media/elements/data-pie-chart-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Pie Chart
<ElementPage definition={getElementDefinition('data/pie-chart')} sourceFile="./pie-chart.tsx" />
Packages Docs Elements Data Vertical Bar Chart Index (`packages/docs/elements/data/vertical-bar-chart/index.mdx`)
title: Vertical Bar Chart image: https://remotion.media/elements/data-vertical-bar-chart-preview.png
import {ElementPage} from '@site/src/components/Elements/ElementPage';
import {getElementDefinition} from '@site/src/components/Elements/element-utils';
Vertical Bar Chart
<ElementPage definition={getElementDefinition('data/vertical-bar-chart')} sourceFile="./vertical-bar-chart.tsx" />
--- METRICS ---
- Files Extracted: 101
- Estimated Token Budget: ~45683 tokens
- Canonical Reference: https://codewiki.google/github.com/remotion-dev/remotion