# Technical Documentation: remotion-dev/remotion

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/remotion-dev/remotion)

### Overview (README.md)

<p align="center">
  <a href="https://github.com/remotion-dev/logo">
    <picture>
      <source media="(prefers-color-scheme: dark)" srcset="https://github.com/remotion-dev/logo/raw/main/animated-logo-banner-dark.apng">
      <img alt="Animated Remotion Logo" src="https://github.com/remotion-dev/logo/raw/main/animated-logo-banner-light.gif">
    </picture>
  </a>
</p>

[](https://remotion.dev/discord)
[](https://www.npmjs.org/package/remotion)
[](https://npmcharts.com/compare/remotion?minimal=true)
<a href="https://twitter.com/remotion"><img src="https://img.shields.io/twitter/follow/remotion?label=Twitter&color=black" alt="Twitter"></a>

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

```console
npx create-video@latest
```

to get started. Otherwise, read the [installation page](https://www.remotion.dev/docs/) in the documentation.

## Discover Remotion

Remotion is extensively documented over more than 1000 pages.

- Get Started
  - [Installation](https://remotion.dev/docs)
  - [Agent Skills](https://www.remotion.dev/docs/ai/skills)
  - [Prompts](https://www.remotion.dev/prompts)
  - [Templates](https://remotion.dev/templates)
- Components
  - [Elements](https://remotion.dev/elements)
  - [Effects](https://remotion.dev/effects)
  - [Shapes](https://remotion.dev/docs/shapes)
  - [Transitions](https://remotion.dev/transitions)
  - [Sound Effects](https://remotion.dev/docs/sfx)
  - [Captions](https://remotion.dev/docs/captions)
  - [Fonts](https://remotion.dev/docs/fonts)
- Rendering
  - [Node.js APIs](https://www.remotion.dev/docs/ssr)
  - [Lambda](https://www.remotion.dev/docs/lambda)
  - [Vercel](https://www.remotion.dev/docs/vercel-sandbox)
  - [Client-side rendering](https://www.remotion.dev/docs/client-side-rendering/)
  - [Comparison of options](https://remotion.dev/docs/compare-ssr)
- Making apps
  - [Player](https://remotion.dev/docs/player)
  - [Editor Starter](https://remotion.dev/editor-starter)
  - [Mediabunny](https://remotion.dev/docs/mediabunny)
- Community
  - [Discord](https://remotion.dev/discord)
  - [Experts](https://remotion.dev/experts)
  - [Resources](https://remotion.dev/resources)
  - [Contributing](https://remotion.dev/contributing)
  - Follow us on [X](https://x.com/remotion), [YouTube](https://youtube.com/@remotion_dev), [Instagram](https://instagram.com/remotion), [LinkedIn](https://linkedin.com/company/remotion)
- Commercial
  - [License](https://remotion.dev/license)
  - [Store](https://remotion.pro/store)
  - [About Remotion](https://remotion.dev/about)
  - [Showcase](https://remotion.dev/showcase)
- Help
  - [Support](https://remotion.dev/support)
  - [Discord](https://remotion.dev/discord)
  - [Search](https://remotion.dev/search)
  - [Ask AI](https://remotion.dev/ai)
  - [GitHub Issues](https://github.com/remotion-dev/remotion/issues)

## Documentation

Documentation: [**remotion.dev/docs**](https://www.remotion.dev/docs)  
API Reference: [**remotion.dev/api**](https://www.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](LICENSE.md) page for more information.

## Contributing

Please read [CONTRIBUTING.md](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](https://chatgpt.com/download/), it can create a complete Remotion project that you can edit, run, and render locally using the [Remotion plugin](/docs/ai/codex-plugin).

<CreateWithChatGPTButton />

## 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

```sh
npx create-video@latest --yes --blank my-video
cd my-video
npx remotion skills add
npm run dev
```

Creates a video in the `my-video` directory using the blank template and [Agent Skills](/docs/ai/skills), without TailwindCSS.

Planning to prompt a video using a coding agent?  
Click [here](/docs/ai/coding-agents) for more detailed beginner instructions.

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## Templates

Choose the [template](/templates) that is most suitable for you.
For your first project, we recommend the [Hello World](/templates/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', },
]
}>
<TabItem value="npm">

```bash title="Use npm as the package manager"
npx create-video@latest
```

  </TabItem>
  <TabItem value="pnpm">

```bash title="Use pnpm as the package manager"
pnpm create video
```

  </TabItem>

  <TabItem value="yarn">

```bash title="Use Yarn as the package manager"
yarn create video
```

  </TabItem>

  <TabItem value="nub">

```bash title="Use Nub as the package manager"
nubx create-video@latest
```

  </TabItem>

  <TabItem value="bun">

```bash title="Use Bun as the package manager and runtime"
bun create video
```

:::note
Bun as a runtime is mostly supported. [Read more here](/docs/bun).
:::

  </TabItem>
</Tabs>

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', },
]
}>
<TabItem value="npm">

After the project has been scaffolded, we recommend to open the project in your text editor and starting the [Remotion Studio](/docs/studio):

```bash
npm run dev
```

  </TabItem>
  <TabItem value="pnpm">

After the project has been scaffolded, we recommend to open the project in your text editor and starting the app:

```bash
npm run dev
```

To start the [Remotion Studio](/docs/studio):

```bash
npm run remotion
```

  </TabItem>
</Tabs>

## ESLint

Remotion templates include a recommended ESLint configuration. See [`@remotion/eslint-config`](/docs/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](https://nodejs.org/en/download/) <MinNodeVersion /> or [Bun](https://bun.sh) <MinBunVersion />.  
🍎 macOS 15 (Sequoia) or later is required. [Older versions are not supported.](https://github.com/remotion-dev/remotion/issues/7027)  
🐧 [Linux distros need at least version 2.35 of Libc.](https://github.com/remotion-dev/remotion/issues/2439)  
They also need to [install some additional packages](/docs/miscellaneous/linux-dependencies).  
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](/docs/brownfield)

---

### Packages Docs Elements Template Index (`packages/docs/elements-template/index.mdx`)

---
title: Element title
description: One sentence describing what this element shows.
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: [],
  description: 'One short sentence explaining what this Element demonstrates and when to use it.',
  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

<ElementPage definition={elementDefinition} sourceFile="./element.tsx" />

---

### Packages Docs Elements Index (`packages/docs/elements/index.mdx`)

---
title: Remotion Elements
sidebar_label: Overview
hide_table_of_contents: true
hide_title: true
pagination_next: null
pagination_prev: null
description: Drop-in, remixable video building blocks for Remotion.
---

import {CatalogHero} from '@site/src/components/Catalog/CatalogHero';
import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

<CatalogHero title="Remotion Elements">
<span className="catalog-lead">Drop-in video building blocks.</span> Make it yours,<br /> [interactively](/docs/studio/interactivity) or [with an agent](/docs/ai).
</CatalogHero>

<ElementLibrary category={null} />

## More Elements

Browse the catalog [directly inside Remotion Studio](/docs/studio/browse-elements).

Add [third-party Element Libraries](/elements/libraries) to browse and install Elements from other creators in Studio.

Have an Element idea? [Contribute](/docs/contributing/elements).

---

### 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:

<TableOfContents />

## AI-Ready Documentation

Remotion docs are optimized for AI agents:

- **Copy as Markdown**: Click the copy button on any doc page to copy raw markdown
- **Markdown URLs**: Add `.md` to any doc URL (e.g., `remotion.dev/docs/player.md`) to view/fetch raw markdown
- **Content negotiation**: Remotion docs respect the `Accept` header - request `text/markdown` to get markdown instead of HTML. Paste any Remotion doc link into Claude Code, opencode, or other AI coding agents and they'll automatically fetch the markdown version

---

### Packages Docs Docs Animated Emoji Index (`packages/docs/docs/animated-emoji/index.mdx`)

---
image: /generated/articles-docs-animated-emoji-index.png
sidebar_label: Overview
title: "@remotion/animated-emoji"
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import {TableOfContents} from "./TableOfContents";

# @remotion/animated-emoji<AvailableFrom v="4.0.187" />

This package wraps the [Google Fonts Animated Emoji](https://googlefonts.github.io/noto-emoji-animation/) into Remotion components.

## Installation

<Installation pkg="@remotion/animated-emoji" />

## APIs

The following APIs are available:

<TableOfContents />

## License

[Remotion License](https://remotion.dev/license)  
The animated Emoji are licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).

---

### Packages Docs Docs Animation Utils Index (`packages/docs/docs/animation-utils/index.mdx`)

---
image: /generated/articles-docs-animation-utils-index.png
title: '@remotion/animation-utils'
---

# @remotion/animation-utils<AvailableFrom v="4.0.92" />

Functions that support you in animating CSS styles.

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', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/animation-utils
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/animation-utils
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/animation-utils
```

  </TabItem>
</Tabs>

## Functions

<TableOfContents />

## License

MIT

---

### Packages Docs Docs Browser Bundler Index (`packages/docs/docs/browser-bundler/index.mdx`)

---
image: /generated/articles-docs-browser-bundler-index.png
sidebar_label: Overview
title: '@remotion/browser-bundler'
crumb: '@remotion/browser-bundler'
---

# @remotion/browser-bundler<AvailableFrom v="4.0.527" />

Compile a virtual Remotion project in the browser and use a registered [composition](/docs/composition) in your own UI, such as a [`<Player>`](/docs/player/player).

:::warning

*Draft API*: This API is not yet stable. We are in the experimental phase of this package and reserve to change it at any time.

:::

The initial implementation has only been tested in Chrome.

The main entry point compiles source snapshots, manages its worker and WebAssembly compiler, applies source edits incrementally, and resolves npm imports over HTTP. The separate `@remotion/browser-bundler/runtime` entry point executes a bundle and resolves a registered composition.

Neither entry point provides an editor or playback UI.

## Installation

<Installation pkg="@remotion/browser-bundler" />

For the example below, also install [`@remotion/player`](/docs/player/installation). Keep all Remotion packages on the same version, and use the same React and React DOM versions in the host app and virtual project.

## Browser setup

Serve your app in a secure context, such as HTTPS or `localhost`, with these response headers:

```text title="HTTP response headers"
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

`window.crossOriginIsolated` must be `true`. The browser must support module workers, `SharedArrayBuffer`, and WebAssembly with shared memory. Cross-origin scripts, media, and other resources must satisfy the page's cross-origin policy.

The compiler downloads a sizable WebAssembly binary and can use significant memory. The first compilation is slower than subsequent edits. Use [`onProgress`](/docs/browser-bundler/create-browser-bundler#onprogress) to display download progress, and reuse a bundler instance while editing.

### Host bundler support

The package ships a prebuilt compiler worker together with its WebAssembly binary and supporting worker asset. Your app's bundler must handle `new Worker(new URL(..., import.meta.url))` and emit the assets referenced with `new URL(..., import.meta.url)`. Serve those emitted assets alongside your app.

Alternatively, use [`workerUrl`](/docs/browser-bundler/create-browser-bundler#workerurl) to host the packaged worker and its adjacent assets at a custom same-origin location. Preserve the packaged filenames and relative paths. This overrides the main worker URL, not the requirement to deploy its supporting assets. See [serving the compiler as static files](#serving-the-compiler-as-static-files) for a setup that does not depend on the host bundler.

Other bundlers and deployment configurations are not guaranteed to work without additional setup. Call these APIs on the client, not during server rendering.

### Next.js

For TypeScript projects, use `"moduleResolution": "bundler"` in `tsconfig.json` so imports from `@remotion/browser-bundler/runtime` resolve through the package's exports.

Add the cross-origin isolation headers to the routes that use the compiler, including the compiler assets. This example uses `/browser-bundler` as the page route; replace it with your route.

```js title="next.config.mjs"
/** @type {import('next').NextConfig} */
const nextConfig = {
  async headers() {
    return ['/browser-bundler', '/_next/:path*', '/compiler/:path*'].map(
      (source) => ({
        source,
        headers: [
          {key: 'Cross-Origin-Opener-Policy', value: 'same-origin'},
          {key: 'Cross-Origin-Embedder-Policy', value: 'require-corp'},
        ],
      }),
    );
  },
};

export default nextConfig;
```

If other pages are served without these headers, use full-page navigation when entering or leaving this route. Next.js client-side navigation does not change the current document's cross-origin isolation. A normal `<a>` link performs a full-page navigation.

#### Serving the compiler as static files<AvailableFrom v="4.0.529" />

The recommended setup works with Turbopack and webpack, in the App Router and the Pages Router: copy the compiler assets into `public/` and point [`workerUrl`](/docs/browser-bundler/create-browser-bundler#workerurl) at them. The worker resolves its WebAssembly binary and supporting worker relative to its own URL, so the Next.js bundler does not process them.

```js title="scripts/copy-compiler.mjs"
import {copyFile, mkdir} from 'node:fs/promises';
import {createRequire} from 'node:module';
import path from 'node:path';

const require = createRequire(import.meta.url);
const dist = path.join(
  path.dirname(require.resolve('@remotion/browser-bundler/package.json')),
  'dist',
);
const target = path.join(process.cwd(), 'public', 'compiler');

await mkdir(target, {recursive: true});
for (const asset of [
  'browser-bundler-worker.js',
  'rspack.wasm32-wasi.wasm',
  'wasi-worker-browser.mjs',
]) {
  await copyFile(path.join(dist, asset), path.join(target, asset));
}
```

Run the script before `next dev` and `next build`, and ignore `public/compiler` in version control. Then create the bundler with the served worker:

```ts twoslash title="compiler.ts"
// @moduleResolution: bundler
import {createBrowserBundler} from '@remotion/browser-bundler';

const bundler = createBrowserBundler({
  workerUrl: new URL('/compiler/browser-bundler-worker.js', window.location.origin),
});
```

Without `workerUrl`, the package falls back to `new Worker(new URL('./browser-bundler-worker.js', import.meta.url))`, which makes the Next.js bundler process the worker and its assets. In the App Router, the supporting worker is then transpiled and fails to start with `Cannot use 'import.meta' outside a module`, and Turbopack warns about a module format mismatch.

#### Bundling the compiler with webpack

In the Pages Router with webpack, the compiler assets can be bundled by Next.js instead. Use webpack for development and production builds, not Turbopack:

```json title="package.json (scripts)"
{
  "scripts": {
    "dev": "next dev --webpack",
    "build": "next build --webpack"
  }
}
```

Merge these rules into your configuration:

```js title="next.config.mjs"
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack(config) {
    config.module.rules.push(
      {test: /browser-bundler-worker\.js$/, parser: {url: true}},
      {test: /\.wasm$/, type: 'asset/resource'},
      {test: /wasi-worker-browser\.mjs$/, type: 'asset/resource'},
    );
    return config;
  },
};

export default nextConfig;
```

Next.js normally makes asset URLs relative. The supporting worker starts from a `blob:` URL, so its `importScripts()` call needs an absolute script URL. The scoped `parser: {url: true}` rule preserves that behavior for the packaged compiler worker without changing URL handling throughout your app.

This configuration does not work in the App Router, where the supporting worker is passed through the React Refresh loader before the `asset/resource` rule applies. Use the static files setup above instead.

## Trusted code only

[`loadBrowserBundle()`](/docs/browser-bundler/load-browser-bundle) evaluates JavaScript using `Function`. The bundle and its dependencies run with your host page's privileges, including access to its DOM, storage, and network. This is not a sandbox; do not use it to execute untrusted source.

Your Content Security Policy must permit JavaScript code evaluation (`'unsafe-eval'`), workers, and WebAssembly compilation, as well as the asset and dependency requests. Allowing only `'wasm-unsafe-eval'` is insufficient for the runtime's JavaScript evaluation.

## Minimal example

This is a normal Remotion project: its entry point calls [`registerRoot()`](/docs/register-root), and its root registers a [`<Composition>`](/docs/composition). The host selects the hardcoded `HelloWorld` ID after compiling.

```
/* Detailed source-code truncated for AI context efficiency. */
```

Pass the returned `component` to [`<Player>`](/docs/player/player), not the registered root or `<Composition>` itself. Pass `props` and the resolved dimensions, frame rate, and duration alongside it. [`getBrowserComposition()`](/docs/browser-bundler/get-browser-composition) merges default and input props and runs [`calculateMetadata()`](/docs/calculate-metadata) when provided.

This example compiles once and disposes its worker. For editing, keep the bundler alive and submit a new complete snapshot when the source changes. Keep the last successful preview visible while compiling.

## Scope and limitations

### Source snapshots

A [`VirtualProject`](/docs/browser-bundler/create-browser-bundler#virtualproject) contains project-relative source file paths, such as `src/index.ts` and `src/Root.tsx`, and their text. You own editing, history, saving, and restoring snapshots. The package does not provide filesystem persistence or an installation UI for npm packages.

### Dependencies

Browser-compatible npm imports resolve through [esm.sh](https://esm.sh). Default dependency versions come from the versions used to build the package. Use [`dependencyVersions`](/docs/browser-bundler/create-browser-bundler#dependencyversions) to pin additional dependencies.

React, React DOM, and Remotion imports are shared with the host app when executing the bundle; they are not isolated copies. An override cannot make a different React or Remotion version run alongside the host version.

### Public assets

The virtual project has no `public/` asset mapping or public-file persistence. [`staticFile()`](/docs/staticfile) does not map a virtual source file to a served asset. Use hosted asset URLs that satisfy the page's cross-origin policy.

### Updating the preview

Compiling does not automatically replace an existing Player component. You own recompilation triggers, loading and resolving the new bundle, handling stale results and errors, and updating playback.

For state-preserving edits, enable [`enableFastRefresh`](/docs/browser-bundler/create-browser-bundler#enablefastrefresh) and apply bundles with [`createBrowserBundleRuntime()`](/docs/browser-bundler/create-browser-bundle-runtime). Use an isolated preview with development React and [`createBrowserCompositionObserver()`](/docs/browser-bundler/create-browser-composition-observer) to keep the composition registration tree mounted alongside the Player. This uses Rspack hot updates and React Fast Refresh rather than evaluating and remounting a fresh Player on each edit.

Coalesce pending source edits before compilation, but apply every successfully compiled Fast Refresh bundle in order. Discarding compiled updates breaks the hot-update chain.

This package does not export a video file. See [client-side rendering](/docs/client-side-rendering) for video export APIs and their separate requirements.

## APIs

import {TableOfContents} from './table-of-contents';

<TableOfContents />

## License

[Remotion License](/docs/license)

---

### Packages Docs Docs Canvas Capture Index (`packages/docs/docs/canvas-capture/index.mdx`)

---
image: /generated/articles-docs-canvas-capture-index.png
title: Canvas Capture
---

import {TableOfContents} from './TableOfContents';

# Canvas Capture

Remotion Canvas Capture is a high-fidelity webpage recorder which leverages HTML-in-canvas.

It can record content at a higher resolution than the native display resolution.

Perfect for product demos showing closeups of UI.

## Table of contents

<TableOfContents />

---

### Packages Docs Docs Captions Index (`packages/docs/docs/captions/index.mdx`)

---
image: /generated/articles-docs-captions-index.png
title: Captions
sidebar_label: Overview
---

import {GuideTableOfContents} from './GuideTableOfContents';

# Captions

Learn how to add captions and subtitles to your Remotion videos.

<GuideTableOfContents />

## See also

- [`@remotion/captions`](/docs/captions/api) - API reference for caption utilities

---

### Packages Docs Docs Client Side Rendering Index (`packages/docs/docs/client-side-rendering/index.mdx`)

---
image: /generated/articles-docs-client-side-rendering-index.png
crumb: 'Overview'
sidebar_label: Overview
title: Client-side rendering
---

Client-side rendering is a Remotion capability that allows you to render videos, images, and audio directly in the browser, without requiring server-side infrastructure.

It is available through the [`@remotion/web-renderer`](/docs/web-renderer) package and is stable from <AvailableFrom v="4.0.491" inline />.

## Key differences from server-side rendering

Unlike server-side rendering with [`@remotion/renderer`](/docs/renderer), client-side rendering:

- Runs in the browser - No need to setup Node servers or Remotion Lambda
- Encodes with WebCodecs using [Mediabunny](/docs/mediabunny) instead of FFmpeg
- Limited to a subset of HTML elements - see [limitations](/docs/client-side-rendering/limitations)
- No bundling step - takes components and video config directly

## Browser support

Client-side rendering requires the [WebCodecs API](https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API), which limits browser support to:

| Browser | Minimum version |
| ------- | --------------- |
| Chrome  | 94+             |
| Firefox | 130+            |
| Safari  | 26+             |

## APIs

The package provides APIs called [`renderStillOnWeb()`](/docs/web-renderer/render-still-on-web) and [`renderMediaOnWeb()`](/docs/web-renderer/render-media-on-web).

Here is an example of how to use it:

```tsx twoslash title="Example"
import {renderMediaOnWeb} from '@remotion/web-renderer';

const Component: React.FC = () => {
  return (
    <svg viewBox="0 0 100 100" width="100" height="100" style={{transform: 'rotate(45deg)'}}>
      <polygon points="50,10 90,90 10,90" fill="orange" />
    </svg>
  );
};

const {getBlob} = await renderMediaOnWeb({
  composition: {
    component: Component,
    durationInFrames: 100,
    fps: 30,
    width: 100,
    height: 100,
    calculateMetadata: null,
    id: 'my-composition',
  },
  inputProps: {},
});
```

## Remotion Studio

Client-side rendering is always enabled in the Remotion Studio from <AvailableFrom v="4.0.491" inline />. Use the "Render in browser" button to start a render.

## Telemetry

Client-side rendering always sends a telemetry event for every render, even if no license key is set.  
See [Telemetry](/docs/telemetry) for which information is sent and how to set a license key.

## See also

- [How it works](/docs/client-side-rendering/how-it-works)
- [Limitations](/docs/client-side-rendering/limitations)
- [Telemetry](/docs/telemetry)
- [Server-side rendering](/docs/ssr)

---

### Packages Docs Docs Codemods Index (`packages/docs/docs/codemods/index.mdx`)

---
image: /generated/articles-docs-codemods-index.png
sidebar_label: Overview
title: '@remotion/codemods'
crumb: '@remotion/codemods'
---

# @remotion/codemods<AvailableFrom v="4.0.527" />

Edit Remotion source in memory. Discover nodes, insert elements, edit props and animations, and manage composition registrations.

:::warning

_Draft API_: This API is not yet stable. We are in the experimental phase of this package and reserve to change it at any time.

:::

The package accepts file paths and source code and returns the files that changed. It does not read or write the filesystem, execute the project, download media, or install packages. You control how changes are previewed, saved, and compiled.

## Installation

<Installation pkg="@remotion/codemods" />

Keep the version aligned with the other Remotion packages in the project.

## Project model

A `CodemodProject` contains the following properties.

### rootDir

The project's root directory, used to resolve imports and file paths.

### files

A `Record<string, string>` mapping file paths to source code. Paths may be project-relative or absolute, but must consistently identify files within the project. Include the project files needed to resolve imported components.

```ts twoslash title="project.ts"
import type {CodemodProject} from '@remotion/codemods';

export const project: CodemodProject = {
  rootDir: '/',
  files: {
    'src/Root.tsx': `import {Composition} from 'remotion';
import {Video} from './Video';
export const Root = () => <Composition id="Demo" component={Video} width={1920} height={1080} fps={30} durationInFrames={90} />;`,
    'src/Video.tsx': `export const Video = () => <div style={{opacity: 1}}>Hello</div>;`,
  },
};
```

Include the files needed for the edit. A prop edit needs its target file; resolving an imported composition component also needs the files along the import path. Mutations leave the input project unchanged.

## Creating elements<AvailableFrom v="4.0.530" />

Describe elements with [`createElement()`](/docs/codemods/create-element) and insert it with [`addElement()`](/docs/codemods/add-element). Elements are immutable descriptions: methods such as `withProp()` and `withChild()` return new elements. Imports and local names are resolved when the element is inserted.

```ts twoslash title="insert.ts"
import {addElement, applyCodemodChanges, createElement, type CodemodProject} from '@remotion/codemods';

declare const project: CodemodProject;

const solid = createElement({
  component: 'Solid',
  importPath: 'remotion',
  props: {width: 1920, height: 1080, color: 'gray'},
});
const sequence = createElement({
  component: 'Sequence',
  importPath: 'remotion',
  props: {from: 30},
}).withChild(solid);

const result = addElement({
  project,
  element: sequence,
  target: {type: 'composition', compositionFile: 'src/Root.tsx', compositionId: 'Demo'},
});
const nextProject = applyCodemodChanges(project, result.changes);
console.log(nextProject.files, result.insertedNode);
```

Elements can also be inserted `inside`, `before`, or `after` an existing node, and [`wrapNode()`](/docs/codemods/wrap-node) wraps an existing node in an element.

## Editing a node<AvailableFrom v="4.0.528" />

Find a node, inspect the properties you want to edit, and pass its reference to a mutation.

```ts twoslash title="edit.ts"
import {applyCodemodChanges, getNodes, getNodeProps, updateNodeProps, type CodemodProject} from '@remotion/codemods';

declare const project: CodemodProject;

const node = getNodes({project, filePath: 'src/Video.tsx'}).find((candidate) => candidate.tagName === 'div');

if (node) {
  const {props} = getNodeProps({project, node, keys: ['style.opacity']});
  if (props['style.opacity'].status === 'static') {
    const result = updateNodeProps({
      project,
      node,
      props: {'style.opacity': 0.5},
    });
    const nextProject = applyCodemodChanges(project, result.changes);
    console.log(nextProject.files, result.updatedNode);
  }
}
```

## Node references<AvailableFrom v="4.0.528" />

A `NodeReference` contains the following properties.

### filePath

The file containing the node.

### nodePath

The `SequenceNodePath` identifying the element in the current source snapshot. Obtain it from [`getNodes()`](/docs/codemods/get-nodes), an insertion result, or a mounted layer's `nodePathInfo.sequenceSubscriptionKey.nodePath`. Treat its contents as opaque. To traverse the tree, compare it with the `parentNodePath` that [`getNodes()`](/docs/codemods/get-nodes) returns for each node.

A reference identifies source, not a particular rendered instance. Editing a component used by several compositions changes that shared component. Editing a node inside a loop changes the source used by every iteration.

### Keeping references after edits

Node and registration mutations return `nodePathRemappings`. Each entry contains `filePath`, `oldNodePath`, and `newNodePath`. Apply a mapping once to references from the input project, matching both the file and old path. A `null` old path means insertion; a `null` new path means removal. An omitted reference keeps its path.

Use `insertedNode`, `insertedNodes`, or `updatedNode` when returned instead of trying to reconstruct a path. Adding hooks, duplicating elements, changing wrappers, or moving registrations can move other nodes as well. After manual source changes, discover nodes again.

Editors that keep mounted sequences attached to their source nodes, such as [`<Canvas>`](/docs/sdk/canvas), accept these mappings through [`queueSequenceNodePathRemappings()`](/docs/sdk/create-canvas-controller#queuesequencenodepathremappings).

## Effect references<AvailableFrom v="4.0.528" />

An `EffectReference` extends a node reference with `effectIndex`, the zero-based position in its inline `effects` array. [`getNodeProps()`](/docs/codemods/get-node-props) inspects effects, and effect mutations return `insertedEffect`, `insertedEffects`, or `updatedEffect` where applicable.

Adding, deleting, duplicating, or reordering effects can shift effect indices. Node-path remappings do not remap effect indices. Inspect the updated effects before reusing other effect references.

## Mutation results

Every mutation returns a `CodemodResult`, synchronously or through a promise as documented on its page.

### changes

An array of `CodemodFileChange` objects.

#### filePath

The changed file's key in the input project's `files` map, or the path of a newly created file.

#### previousContents

The previous source, or `null` if the file was created.

#### nextContents

The next source, or `null` if the file was deleted.

### nodePathRemappings<AvailableFrom v="4.0.528" />

Node, effect, keyframe, and registration mutations return these mappings in addition to the shared result. Registration mutations return them since <AvailableFrom v="4.0.530" inline />. See [node references](#node-references).

## Applying changes

Use [`applyCodemodChanges()`](/docs/codemods/apply-codemod-changes) to produce a new project. The function checks every `previousContents` value before applying any changes, throws if a file has changed since the codemod ran, and preserves other project fields. An empty `changes` array returns the input project.

For undo and redo, store the file changes as one transaction. Swap `previousContents` and `nextContents` to undo it, and apply the original changes to redo it. Apply changes in the reverse order when undoing multiple transactions.

## Supported edits

Code must be valid JavaScript or TypeScript with supported JSX structures. Prop inspection distinguishes static values, recognized keyframes, and computed expressions. The package does not evaluate arbitrary JavaScript. The `props` form of prop updates rejects computed values; [structured `updates`](/docs/codemods/update-node-props#updates) permit explicit replacement. Setting a recognized keyframed prop to a static value replaces its animation.

Registration edits use explicit composition files and static IDs. They support `Composition`, `Still`, and `Folder` from `remotion`, including aliased and namespace imports. Component insertion and resolution support additional import patterns, as documented on their pages.

`CodemodValue` represents serializable strings, numbers, booleans, `null`, arrays, and objects. Strings are values, not executable expressions; use [`staticFileValue()`](/docs/codemods/static-file-value) to reference a file in the public folder. [`updateNodeProps()`](/docs/codemods/update-node-props) also accepts `undefined` to remove a property.

Unsupported edits throw or reject without mutating the input project. Batch operations resolve their references against the same input snapshot. Unrelated source formatting and comments are preserved; edited regions use the surrounding source style.

## APIs

import {TableOfContents} from './table-of-contents';

<TableOfContents />

## Compatibility

<CompatibilityTable chrome firefox safari nodejs bun serverlessFunctions clientSideRendering serverSideRendering player studio />

---

### Packages Docs Docs Contributing Index (`packages/docs/docs/contributing/index.mdx`)

---
image: /generated/articles-docs-contributing-index.png
title: Contributing to Remotion
sidebar_label: General information
crumb: How to be awesome
---

Issues and pull requests of all sorts are welcome!

For bigger projects, please coordinate with Jonny Burger (<a href="mailto:jonny@remotion.dev">jonny@remotion.dev</a>, <a href="https://remotion.dev/discord">Discord</a>: <code>@jonnyburger</code>) to make sure your changes get merged.

Please note that since we charge for Remotion when companies are using it, this is a **commercial project**.  
By sending pull requests, you agree that we can use your code changes in a commercial context.

Furthermore, also note that you **cannot redistribute** this project. Please see [LICENSE.md](https://remotion.dev/license) for what's allowed and what's not.

This project is released with a [Contributor Code of Conduct](https://remotion.dev/coc). By participating in this project you agree to abide by its terms.

## Setup

<Step>1</Step> Remotion uses [`Bun`](https://bun.com) v1.4.3 as the package manager for development in this repository. The version must be at least `1.4.3`.

```sh
curl -fsSL https://bun.com/install | bash -s "bun-v1.4.3"
```

<Step>2</Step> Clone the Remotion repository:

```sh
git clone --depth=1 https://github.com/remotion-dev/remotion.git && cd remotion
```

:::note
The full Git history of Remotion is large. To save time and disk space, we recommend adding `--depth=1` to only clone the most recent `main` branch.
:::

<Step>3</Step> Install all dependencies:

```sh
bun i
```

<Step>4</Step> Build the project initially:

```sh
bun run build
```

<Step>5</Step> Rebuild whenever a file changes:

```sh
bun run watch
```

<Step>6</Step> You can start making changes!

## Coming from pnpm

Before using Bun, we used pnpm as the package manager. If you are coming from pnpm, you need to wipe all node_modules folders first before you run `bun i`.

```sh
bun run cleanall
```

## Testing your changes

You can start the Testbed using

```sh
cd packages/example
bun run dev
```

You can render a test video using

```sh
cd packages/example
bunx remotion render
```

You can run tests using

```sh
bun run test
```

in either a subpackage to run tests for that package or in the root to run all tests.

## Running the `@remotion/player` testbed

You can test changes to [@remotion/player](https://remotion.dev/docs/player) by starting the Player testbed:

```sh
cd packages/player-example
bun run dev
```

For information about testing Remotion components, please consult the [Testing Remotion components](/docs/testing) page. Issues and pull requests of all sorts are welcome!

## Running documentation

You can run the Docusaurus server that powers our docs using:

```sh
cd packages/docs
bun run start
```

## Running the CLI

You can test changes to the CLI by moving to `packages/example` directory and using `bunx` to execute the CLI:

```sh
cd packages/example
# Example - Get available compositions
bunx remotion compositions
# Example - Render command
bunx remotion render ten-frame-tester --output ../../out/video.mp4
```

## Testing Remotion Lambda

In `packages/example`, there is a `runlambda.sh` script that will rebuild the code for the Lambda function, remove any deployed Lambda functions, deploy a new one and render a video.  
You need to put you [AWS credentials](/docs/lambda/authentication) in a `.env` file of the `packages/example` directory.

```sh
cd packages/example
sh ./runlambda.sh
```

:::note
This will delete any Lambda functions in your account!
:::

## Testing Remotion Cloud Run

In `packages/example`, there is a `runcloudrun.sh` script that will rebuild the code for the Cloud Run function, remove any deployed Cloud Run services, deploy a new one and render a video.  
You need to put you [GCP credentials](/docs/cloudrun/generate-env) in a `.env` file of the `packages/example` directory.

```sh
cd packages/example
sh ./runcloudrun.sh
```

:::note
This will delete any Cloud Run services in your account!
:::

## Troubleshooting

If your `bun run build` throws errors, oftentimes it is because of caching issues. You can resolve many of these errors by running

```ts
bun run clean
```

in the root directory. Make sure to beforehand kill any `bun run watch` commands, as those might regenerate files as you clean them!

## Developing new transition presentations

To develop new transition presentations, see [here](/docs/contributing/presentation).

## Developing Rust parts

To develop the Rust parts of Remotion, see [here](/docs/contributing/rust).

## See also

- [Implementing a new feature](/docs/contributing/feature)
- [Implementing a new option](/docs/contributing/option)
- [Writing documentation](/docs/contributing/docs)
- [Formatting guidelines](/docs/contributing/formatting)
- [Authoring Remotion libraries](/docs/authoring-packages)

---

### Packages Docs Docs Editor Starter Index (`packages/docs/docs/editor-starter/index.mdx`)

---
image: https://pub-646d808d9cb240cea53bedc76dd3cd0c.r2.dev/editor-starter-og-image.jpg
title: Editor Starter
sidebar_label: Editor Starter
crumb: Editor Starter
hide_title: true
---

<img src="https://pub-646d808d9cb240cea53bedc76dd3cd0c.r2.dev/editor-starter-og-image.jpg" />
<br />
<br />

A template containing the most essential elements of a video editor.

- **Save countless hours** by leveraging our pre-made components for timeline, interactive canvas, font picker, asset uploads, etc.
- **Get the best of Remotion** put together into one template, culminating years of development and battle-testing.
- **Customize anything** by adopting a clean, well-structured codebase with 80+ feature flags.

import {TableOfContents} from './TableOfContents';

## Introduction video

<iframe
  style={{
    width: '100%',
    aspectRatio: '16 / 9',
  }}
  src="https://www.youtube.com/embed/KwMMm1n3giU"
  title="YouTube video player"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
/>
<br />

## Table of contents

<TableOfContents />

## Contributors

The Editor Starter has been worked on by the following people:

- [Jonny Burger](https://github.com/JonnyBurger)
- [Igor Samokhovets](https://github.com/samohovets)
- [Shankhadeep Dey](https://github.com/Iamshankhadeep)
- [Mehmet Ademi](https://github.com/mehmetademi)
- [Pramod Kumar](https://github.com/pskd73)
- [Matthew McGillivray](https://github.com/UmungoBungo)

## License

The source code of the Remotion Editor Starter is governed by the [Remotion License](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md) and [its own specific license](https://www.remotion.pro/editor-starter?tab=license).

- Remotion, as an underlying technology of the Remotion Editor Starter, is free to use for individuals and small companies. If you fall into this category, you can buy the Remotion Editor Starter as a one-time purchase. If you are a larger company, you must subscribe to the [Company License](/docs/license/pricing). Read the [Terms & Conditions](/docs/terms).

- The Remotion Editor Starter License [can be seen in the Remotion Store Page](https://www.remotion.pro/editor-starter) as well as accessible through the dedicated GitHub repository after purchase.

---

### Packages Docs Docs Effects Index (`packages/docs/docs/effects/index.mdx`)

---
image: /generated/articles-docs-effects-index.png
id: effects-api
slug: /effects/api
title: '@remotion/effects'
---

# @remotion/effects<AvailableFrom v="4.0.464" />

[Effects](/docs/effects) that can be applied to Remotion-based canvas components.

import {TableOfContents} from './table-of-contents';

<Installation pkg="@remotion/effects" />

## Supported components

Pass effects through the `effects` prop of these components:

- [`<Solid>`](/docs/solid)
- [`<HtmlInCanvas>`](/docs/remotion/html-in-canvas)
- [`<Video>`](/docs/media/video)
- [`<Img>`](/docs/img)
- [`<CanvasImage>`](/docs/canvasimage)
- [`<AnimatedImage>`](/docs/animatedimage)
- [`<Gif>`](/docs/gif/gif)
- [`<RemotionRiveCanvas>`](/docs/rive/remotionrivecanvas)
- [`<Rect>`](/docs/shapes/rect)
- [`<Circle>`](/docs/shapes/circle)
- [`<Triangle>`](/docs/shapes/triangle)
- [`<Star>`](/docs/shapes/star)
- [`<Ellipse>`](/docs/shapes/ellipse)
- [`<Pie>`](/docs/shapes/pie)
- [`<Polygon>`](/docs/shapes/polygon)
- [`<Heart>`](/docs/shapes/heart)
- [`<Arrow>`](/docs/shapes/arrow)

## Effect resolution<AvailableFrom v="4.0.536" />

Use `effectsOutputSize` on any supported component to choose the pixel dimensions used by its effect chain:

```tsx twoslash
import {Video} from '@remotion/media';
import {pixelate} from '@remotion/effects/pixelate';
// ---cut---
<Video
  src="https://example.com/video.mp4"
  effects={[pixelate({blockSize: 12})]}
  effectsOutputSize={{width: 1920, height: 1080}}
/>;
```

Both dimensions must be positive integers. The source is resized to this resolution before the effects run, and the result is composited back into the component's existing output canvas. CSS layout, cropping, and the output video's dimensions stay the same.

This is useful when switching between an original video and a smaller proxy: keeping the effect resolution fixed keeps pixel-based parameters, such as pixelation block sizes, in the same coordinate space. It also applies to images, animated images, GIFs, Rive canvases, solids, HTML-in-canvas, and shapes.

Omitting `effectsOutputSize` preserves the existing effect resolution. Empty or entirely disabled effect chains do not resize the source. To change the resolution, update the numeric width and height; passing a new object with the same values does not recreate the effect chain. Video previews redraw the current frame when these values change without restarting their decoder.

A larger effect resolution increases processing and canvas memory. Resizing a low-resolution source cannot restore missing detail. This prop controls effect processing; [`maxCanvasSinkFrameSize`](/docs/media/video#maxcanvassinkframesize) separately controls decoded preview frame size.

Shader-based [transition presentations](/docs/transitions/presentations), including custom presentations created with [`makeHtmlInCanvasPresentation()`](/docs/transitions/make-html-in-canvas-presentation), accept `effectsOutputSize` alongside `effects`:

```tsx twoslash title="MyComposition.tsx"
import {dissolve} from '@remotion/transitions/dissolve';
import {pixelate} from '@remotion/effects/pixelate';
// ---cut---
dissolve({
  effects: [pixelate({blockSize: 12})],
  effectsOutputSize: {width: 1920, height: 1080},
});
```

This sets the resolution of the effects applied after the transition shader. The shader and transition output keep their existing dimensions.

## Effects

<TableOfContents />

## Creating custom effects

To build your own effect, use [`createEffect()`](/docs/create-effect) from `remotion`. It creates a custom effect factory and uses [`InteractivitySchema`](/docs/interactivity-schema) for Studio controls.

## License

[Remotion License](/docs/license)

---

### Packages Docs Docs Elevenlabs Index (`packages/docs/docs/elevenlabs/index.mdx`)

---
image: /generated/articles-docs-elevenlabs-index.png
title: '@remotion/elevenlabs'
crumb: 'Subtitle videos'
---

# @remotion/elevenlabs<AvailableFrom v="4.0.443" />

The `@remotion/elevenlabs` package converts the output of the [ElevenLabs Speech to Text API](https://elevenlabs.io/docs/api-reference/speech-to-text/convert) into an array of [`Caption`](/docs/captions/caption) objects, making them compatible with other caption-related Remotion APIs.

import {TableOfContents} from './TableOfContents';

<Installation pkg="@remotion/elevenlabs" />

## APIs

<TableOfContents />

## License

MIT

## See also

- [`@remotion/captions`](/docs/captions/api)
- [`@remotion/openai-whisper`](/docs/openai-whisper)

---

### Packages Docs Docs Enable Scss Overview (`packages/docs/docs/enable-scss/overview.mdx`)

---
image: /generated/articles-docs-enable-scss-overview.png
sidebar_label: Overview
title: '@remotion/enable-scss'
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {ExperimentalBadge} from '../../components/Experimental';
import {TableOfContents} from './TableOfContents';

This package provides a bundler override for enabling [SCSS/SASS](https://sass-lang.com/) with Remotion.

## Installation

Install `@remotion/enable-scss` as well as TailwindCSS dependencies.

<Installation pkg="@remotion/enable-scss sass@1.77.2 sass-loader@14.2.1 css-loader@5.2.7" />

<br />

:::warning
Pay attention to install exactly these versions.  
Newer versions may not work.
:::

## Usage

[Override the bundler config](/docs/bundlers) by using [`enableScss()`](/docs/enable-scss/enable-scss).

```ts twoslash title="remotion.config.ts"
import {Config} from '@remotion/cli/config';
import {enableScss} from '@remotion/enable-scss';

Config.overrideBundlerConfig((currentConfiguration) => {
  return enableScss(currentConfiguration);
});
```

## APIs

<TableOfContents />

---

### Packages Docs Docs Fonts Api Index (`packages/docs/docs/fonts-api/index.mdx`)

---
image: /generated/articles-docs-fonts-api-index.png
id: fonts-api
sidebar_label: Overview
title: "@remotion/fonts"
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import { TableOfContents } from "./TableOfContents";

The `@remotion/fonts` package provides an API for [loading local fonts](/docs/fonts) or remote fonts from a URL into a Remotion component.

## Installation

<Installation pkg="@remotion/fonts" />

## APIs

The following APIs are available:

<TableOfContents />

---

### Packages Docs Docs Gif Index (`packages/docs/docs/gif/index.mdx`)

---
image: /generated/articles-docs-gif-index.png
sidebar_label: "@remotion/gif"
title: "@remotion/gif"
---

import {TableOfContents} from './table-of-contents';

You can install this package from NPM to get a component for displaying GIFs that synchronize with Remotions [`useCurrentFrame()`](/docs/use-current-frame).

<Installation pkg="@remotion/gif"/>

## APIs

The following APIs are available:

<TableOfContents />

---

### Packages Docs Docs Google Fonts Index (`packages/docs/docs/google-fonts/index.mdx`)

---
image: /generated/articles-docs-google-fonts-index.png
id: google-fonts
sidebar_label: Overview
title: '@remotion/google-fonts'
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {TableOfContents} from './TableOfContents';

One way of [embedding fonts](/docs/fonts) in Remotion is `@remotion/google-fonts`, sourcing fonts from [Google Fonts](https://fonts.google.com/).

## Installation

<Tabs
defaultValue="npm"
values={[
{ label: 'npm', value: 'npm', },
{ label: 'yarn', value: 'yarn', },
{ label: 'pnpm', value: 'pnpm', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/google-fonts
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/google-fonts
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/google-fonts
```

  </TabItem>
</Tabs>

## Usage

To load a font, import the package `@remotion/google-fonts/<FontName>` and call [`loadFont()`](/docs/google-fonts/load-font).

For production, start with these defaults:

- Pass a style and usually `weights` + `subsets` to avoid loading unnecessary variants.
- Load your fonts in one module and reuse the exports.
- If you use text measurement APIs, gate rendering until fonts are ready using a higher-order component.

```tsx twoslash title="Load one style, weight and subset"
import {loadFont} from '@remotion/google-fonts/TitanOne';

const {fontFamily} = loadFont('normal', {
  weights: ['400'],
  subsets: ['latin'],
}); // "Titan One"
```

If you want to import multiple fonts and want to avoid a variable name collision, you can import the fonts using an `import * as` statement.

```tsx twoslash title="Scope loadFont() variable"
import * as Montserrat from '@remotion/google-fonts/Montserrat';
Montserrat.loadFont('normal', {
  weights: ['400'],
  subsets: ['latin'],
});
```

Call [`loadFont()`](/docs/google-fonts/load-font) to start the loading process. In Remotion 4.0, calling it without arguments loads every style, weight and subset, which can cause unnecessary requests. From [v5.0](/docs/5-0-migration), `weights` and `subsets` are required.

Use TypeScript autocomplete to see the available styles. To further narrow down what's being loaded, specify `weights` and `subsets`. If you need multiple styles, call `loadFont()` multiple times.

```tsx twoslash title="Load multiple styles explicitly"
import * as Montserrat from '@remotion/google-fonts/Montserrat';

Montserrat.loadFont('normal', {
  weights: ['400', '700'],
  subsets: ['latin'],
});
Montserrat.loadFont('italic', {
  weights: ['400'],
  subsets: ['latin'],
});
```

[`loadFont()`](/docs/google-fonts/load-font) returns an object with a `fontFamily` property. You can use the `style` attribute to render text in the font you loaded.

```tsx twoslash title="Use the fontFamily property"
import {loadFont} from '@remotion/google-fonts/TitanOne';
import {AbsoluteFill} from 'remotion';

const {fontFamily} = loadFont('normal', {
  weights: ['400'],
  subsets: ['latin'],
});

export const GoogleFontsDemoComposition = () => {
  return (
    <AbsoluteFill
      style={{
        fontFamily,
      }}
    >
      <div>Hallo Google Fonts</div>
    </AbsoluteFill>
  );
};
```

If your project uses multiple fonts, define them in one file and export a `waitForFonts()` helper:

```tsx twoslash title="fonts.ts"
import {loadFont as loadInter} from '@remotion/google-fonts/Inter';
import {loadFont as loadRobotoMono} from '@remotion/google-fonts/RobotoMono';

const inter = loadInter('normal', {
  weights: ['400', '700'],
  subsets: ['latin'],
});
const mono = loadRobotoMono('normal', {
  weights: ['400'],
  subsets: ['latin'],
});

export const waitForFonts = async () => {
  await Promise.all([inter.waitUntilDone(), mono.waitUntilDone()]);
};
```

If you use text measurement APIs, wrap your content in a component that waits for your fonts before rendering. See the [higher-order component example](/docs/layout-utils/best-practices#example-with-high-order-component) and [font loading troubleshooting](/docs/troubleshooting/font-loading-errors).

To get information about a font, you can import the `getInfo()` function:

```tsx twoslash title="Get info about the font"
import {getInfo} from '@remotion/google-fonts/Montserrat';
console.log(getInfo());
```

```json title="Example value of info object"
{
  "fontFamily": "Titan One",
  "importName": "TitanOne",
  "version": "v13",
  "url": "https://fonts.googleapis.com/css2?family=Titan+One:ital,wght@0,400",
  "unicodeRanges": {
    "latin-ext": "U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF",
    "latin": "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
  },
  "fonts": {
    "normal": {
      "400": {
        "latin-ext": "https://fonts.gstatic.com/s/titanone/v13/mFTzWbsGxbbS_J5cQcjCmjgm6Es.woff2",
        "latin": "https://fonts.gstatic.com/s/titanone/v13/mFTzWbsGxbbS_J5cQcjClDgm.woff2"
      }
    }
  },
  "subsets": ["latin", "latin-ext"]
}
```

To get a list of all available fonts, you can call [`getAvailableFonts()`](/docs/google-fonts/get-available-fonts) imported from `@remotion/google-fonts`:

```ts twoslash
import {getAvailableFonts} from '@remotion/google-fonts';

console.log(getAvailableFonts());
```

## APIs

<TableOfContents />

## Troubleshooting

Known issues:

- [delayRender timeout when fetching fonts](/docs/troubleshooting/font-loading-errors#render-timeout-when-loading-google-fonts)

## Credits

Implemented by [Hidayatullah](https://github.com/ayatkyo).

## License

MIT

## See also

- [Fonts](/docs/fonts)
- [`loadFont()`](/docs/google-fonts/load-font)

---

### Packages Docs Docs Gsap Index (`packages/docs/docs/gsap/index.mdx`)

---
image: /generated/articles-docs-gsap-index.png
id: gsap-index
sidebar_label: Overview
title: '@remotion/gsap'
slug: /gsap
---

# @remotion/gsap<AvailableFrom v="4.0.517" />

import {TableOfContents} from './table-of-contents';

Use [GSAP](https://gsap.com/) timelines in Remotion.

GSAP normally advances animations on its own ticker, which runs on the wall clock. Remotion requires every frame to be a pure function of [`useCurrentFrame()`](/docs/use-current-frame). This package builds a paused GSAP timeline and seeks it to the current frame, so previews, scrubbing and renders are deterministic.

<Installation pkg="@remotion/gsap" />

Also install `gsap` itself, which is a peer dependency:

<Installation pkg="gsap" />

## APIs

<TableOfContents />

## License

MIT

---

### Packages Docs Docs Install Whisper Cpp Index (`packages/docs/docs/install-whisper-cpp/index.mdx`)

---
image: /generated/articles-docs-install-whisper-cpp-index.png
title: '@remotion/install-whisper-cpp'
crumb: 'Transcribe audio locally'
---

# @remotion/install-whisper-cpp<AvailableFrom v="4.0.115" />

With [Whisper.cpp](https://github.com/ggerganov/whisper.cpp), you can transcribe audio locally on your machine.  
This package provides easy to use cross-platform functions to install Whisper.cpp and a model.

import {TableOfContents} from './install-whisper-cpp';

<Installation pkg="@remotion/install-whisper-cpp" />

## Example usage

Install Whisper `1.5.5` (the latest version at the time of writing that we find works well and supports token-level timestamps) and the `medium.en` model to the `whisper.cpp` folder.

```tsx twoslash title="install-whisper.cpp"
import path from 'path';
import {downloadWhisperModel, installWhisperCpp, transcribe, toCaptions} from '@remotion/install-whisper-cpp';
import fs from 'fs';

const to = path.join(process.cwd(), 'whisper.cpp');

await installWhisperCpp({
  to,
  version: '1.5.5',
});

await downloadWhisperModel({
  model: 'medium.en',
  folder: to,
});

// Convert the audio to a 16KHz wav file first if needed:
// import {execSync} from 'child_process';
// execSync('ffmpeg -i /path/to/audio.mp4 -ar 16000 /path/to/audio.wav -y');

const whisperCppOutput = await transcribe({
  model: 'medium.en',
  whisperPath: to,
  whisperCppVersion: '1.5.5',
  inputPath: '/path/to/audio.wav',
  tokenLevelTimestamps: true,
});

// Optional: Apply our recommended postprocessing
const {captions} = toCaptions({
  whisperCppOutput,
});

fs.writeFileSync('captions.json', JSON.stringify(captions, null, 2));
```

## Functions

<TableOfContents />

## License

MIT

## See also

- [`@remotion/openai-whisper`](/docs/openai-whisper)

---

### Packages Docs Docs Layout Utils Index (`packages/docs/docs/layout-utils/index.mdx`)

---
image: /generated/articles-docs-layout-utils-index.png
title: '@remotion/layout-utils'
---

# @remotion/layout-utils<AvailableFrom v="4.0.50" />

Utility functions for creating dynamic layouts.

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', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/layout-utils
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/layout-utils
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/layout-utils
```

  </TabItem>
</Tabs>

## Functions

<TableOfContents />

## License

MIT

---

### Packages Docs Docs Licensing Index (`packages/docs/docs/licensing/index.mdx`)

---
image: /generated/articles-docs-licensing-index.png
sidebar_label: Overview
title: '@remotion/licensing'
crumb: API
---

# @remotion/licensing<AvailableFrom v="4.0.237" />

This package allows holders of the [Company License](/docs/license/pricing) to send events to Remotion to track the usage of renders.  
Also, it offers an API to programmatically check the usage in order to implement spend controls.

### How do I use this package?

Not directly - pass the `licenseKey` option in the renderer package you use.

**Supported packages**

- [`@remotion/lambda`](/docs/lambda): Pass `licenseKey` to [`renderMediaOnLambda()`](/docs/lambda/rendermediaonlambda#licensekey) and [`renderStillOnLambda()`](/docs/lambda/renderstillonlambda#licensekey) to trigger an event.
- [`@remotion/vercel`](/docs/vercel/api): Pass `licenseKey` to [`renderMediaOnVercel()`](/docs/vercel/render-media-on-vercel#licensekey) and [`renderStillOnVercel()`](/docs/vercel/render-still-on-vercel#licensekey) to trigger an event.
- [`@remotion/renderer`](/docs/renderer): Pass `licenseKey` to [`renderMedia()`](/docs/renderer/render-media#licensekey) and [`renderStill()`](/docs/renderer/render-still#licensekey) to trigger an event.
- [`@remotion/web-renderer`](/docs/web-renderer): An event is always sent. Pass a real `licenseKey`, or declare eligibility for the free license with `licenseKey: "free-license"`. See [Telemetry](/docs/telemetry#setting-a-license-key).

<details>
  <summary>Deprecated packages</summary>

- [`@remotion/cloudrun`](/docs/cloudrun): No telemetry is implemented. Use [`@remotion/licensing`](/docs/licensing) directly to track usage.
- [`@remotion/webcodecs`](/docs/webcodecs): Telemetry was removed in v4.0.399 because this package is no longer monetized.

</details>

On your Company License dashboard on [remotion.pro](https://remotion.pro), you can find your license keys on the License keys page.

### Do I need to use this package?

For all versions below Remotion 5.0, it is **voluntary** to use this package.  
An exception is [`@remotion/web-renderer`](/docs/web-renderer), which will always send telemetry events.

If you are not eligible for the Free License, you need to get a Company License and are required to keep your allowance up to date.

From Remotion 5.0, telemetry reporting using the `licenseKey` option is **mandatory** for Remotion for Automators (render-based licensing).

For Remotion for Creators (seat-based licensing), telemetry reporting is optional. Remotion for Creators is meant for low-volume rendering within and for your own company, not to serve (personalized) videos to your end users.

### Can I use this package to count renders if I am eligible for the Free License?

Yes, you may still create a project on [remotion.pro](https://remotion.pro) and use this package to count renders.  
You do not have to pay anything for the renders.  
This package is only used to count the number of renders, not for billing.

### Will I get charged based on the usage?

This package currently only counts renders, it does not bill you based on them.  
If you are a Company License holder, you need to manually adjust your seat count on [remotion.pro](https://remotion.pro) to cover all your renders.

However, the plan is to introduce a system that automatically bills you based on the usage, eliminating the need for you to manually adjust the seat count.

### What data is sent?

When a telemetry event is triggered, the following information is sent to Remotion's servers:

- License key
- Host domain (`window.location.origin`) — only for [`@remotion/web-renderer`](/docs/web-renderer)
- Event type (e.g. `cloud-render`, `web-render`)
- Whether the render succeeded or failed
- Whether it is a production or development render

No information about the rendered media content, metadata, or any user data is collected.

For client-side rendering using [`@remotion/web-renderer`](/docs/web-renderer), the IP address is also recorded.

See [Telemetry](/docs/telemetry) for the source of truth on telemetry.

### Data retention and sharing

Telemetry data is currently retained indefinitely and is not regularly deleted.  
This data is not shared with any third parties. It is only used internally by Remotion for license accountability.

We plan to introduce a retention policy that automatically deletes telemetry data after a defined period. This has not been implemented yet, but is on our roadmap for the future.

### Note for GDPR Compliance

If you utilize client-side rendering, our licensing package transmits the end-user's IP address to Remotion strictly for license verification and billing metrics. You should ensure your app's privacy policy reflects that limited operational telemetry is shared with technical service providers under Legitimate Interest.

### Does telemetry affect renders?

No. Telemetry never blocks or fails a render. Even if the telemetry request fails or licensing is violated, the render will still complete successfully.

### Can I opt out?

For versions below Remotion 5.0, you can opt out by simply not passing a `licenseKey`. The render will still work.

From Remotion 5.0, opt-out is possible under an [Enterprise License](/docs/license/pricing) agreement if monthly usage reports are provided instead.  
The Enterprise License has the same per-render pricing, but requires a minimum spend of $500 per month.

## Installation

<Installation pkg="@remotion/licensing" />

## API

import {TableOfContents} from './TableOfContents';

<TableOfContents />

## License

[Remotion License](https://remotion.dev/license)

---

### Packages Docs Docs Light Leaks Index (`packages/docs/docs/light-leaks/index.mdx`)

---
image: /generated/articles-docs-light-leaks-index.png
id: light-leaks-api
slug: /light-leaks/api
title: '@remotion/light-leaks'
---

# ~~@remotion/light-leaks~~<AvailableFrom v="4.0.415" />

:::info Deprecated
`@remotion/light-leaks` is deprecated and will no longer be published starting with Remotion 5.0. Migrate to [`lightLeak()`](/docs/effects/light-leak) from `@remotion/effects/light-leak`. The `<LightLeak>` component will not be moved to `@remotion/effects`.
:::

Light leak effects for Remotion videos.

import {TableOfContents} from './table-of-contents';

<Installation pkg="@remotion/light-leaks" />

## APIs

<TableOfContents />

## License

[Remotion License](/docs/license)

---

### Packages Docs Docs Lottie Index (`packages/docs/docs/lottie/index.mdx`)

---
image: /generated/articles-docs-lottie-index.png
id: lottie-index
sidebar_label: Overview
title: "@remotion/lottie"
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {TableOfContents} from "./table-of-contents"

This package provides a component for displaying [Lottie](http://airbnb.io/lottie/) animations in Remotion.

## Installation

Install, `@remotion/lottie` as well as `lottie-web`.

<Tabs
defaultValue="npm"
values={[
{ label: 'npm', value: 'npm', },
{ label: 'yarn', value: 'yarn', },
{ label: 'pnpm', value: 'pnpm', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/lottie lottie-web
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/lottie lottie-web
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/lottie lottie-web
```

  </TabItem>
</Tabs>

You can now start using the [`<Lottie>`](/docs/lottie/lottie) component in your Remotion project.

## Supported features

- Playing Lottie animations using `lottie-web`
- Change the speed of the animation
- Playing animation forwards and backwards
- Playing remote files
- Determining dimensions and duration of a Lottie animation

## Unsupported features

- Rendering on other renderers as `svg`
- `setSubFrame()`, `setLocationHref()`
- Limited expression support: Remotion uses the `.goToAndStop()` method from `lottie-web` to seek through the Lottie file. Depending on the expression, the frame might not render deterministally, leading to [flickering](/docs/flickering) in the Remotion output. Remotion cannot fix this without a change in `lottie-web` upstream. You need to evaluate on a case-by-case basis whether the expression you are using is supported by Remotion.

:::note
[Open an issue](https://remotion.dev/issue) if you want to request a currently unsupported feature.
:::

## Table of contents

<TableOfContents />

## License

[Remotion License](https://remotion.dev/license)

---

### Packages Docs Docs Mac Cursors Index (`packages/docs/docs/mac-cursors/index.mdx`)

---
image: /generated/articles-docs-mac-cursors-index.png
id: mac-cursors-api
slug: /mac-cursors
title: '@remotion/mac-cursors'
crumb: API
---

# @remotion/mac-cursors<AvailableFrom v="4.0.513" />

Render bundled macOS cursors and CSS custom cursors in Remotion.

import {TableOfContents} from './table-of-contents';

<Installation pkg="@remotion/mac-cursors" />

## APIs

<TableOfContents />

## License

[Remotion License](/docs/license)

---

### Packages Docs Docs Media Parser Index (`packages/docs/docs/media-parser/index.mdx`)

---
image: /generated/articles-docs-media-parser-index.png
sidebar_label: Overview
title: '@remotion/media-parser'
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {TableOfContents, MediaParserGuideTableOfContents, ReadersTableOfContents, WritersTableOfContents, TypesTableOfContents} from './TableOfContents';

# @remotion/media-parser

:::warning
[We are phasing out Media Parser and are moving to Mediabunny](/blog/mediabunny)!
:::

<img src="/img/media-parser.png" alt="Media Parser" />
<br />
<br />

This is a package that parses video and audio files to extract metadata and samples.

Design goals:

- [Support all major containers](/docs/media-parser/format-support): `.mp4`, `.mov`, `.webm`, `.mkv`, `.avi`, `.m3u8`, `.ts`, `.mp3`, `.wav`, `.aac`, `.m4a` and `.flac`.
- [Easily get various information](/docs/media-parser/fields) from multimedia files
- [Work in the browser, Node.js and Bun](/docs/media-parser/runtime-support)
- [Satisfy your query with minimal fetching](/docs/media-parser/fast-and-slow)
- [Functional TypeScript API](/docs/media-parser/parse-media)
- [Be useful when passing unsupported media](/docs/media-parser/foreign-file-types)
- [Allow decoding video frames and audio samples using WebCodecs](/docs/media-parser/webcodecs)
- [Pausable, resumable and cancellable](/docs/media-parser/pause-resume-abort)
- [Be able to seek to a different position in a media file](/docs/media-parser/seeking)
- No dependencies

## Introduction video

<iframe
  style={{
    width: '100%',
    aspectRatio: '16 / 9',
  }}
  src="https://www.youtube.com/embed/r3dUGdfVnkM"
  title="YouTube video player"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
/>
<br />

## Installation

<Installation pkg="@remotion/media-parser" />

## Hello World

Get metadata from a video file - [over 20 different fields are supported.](/docs/media-parser/fields)

```tsx twoslash title="Get the duration and codec of a video"
import {parseMedia} from '@remotion/media-parser';

const {durationInSeconds, videoCodec} = await parseMedia({
  src: 'https://remotion.media/video.mp4',
  fields: {
    durationInSeconds: true,
    videoCodec: true,
  },
});

console.log(durationInSeconds); // 5.056;
console.log(videoCodec); // 'h264';
```

Extract samples from a video file - [supports WebCodecs](/docs/media-parser/webcodecs).

```tsx twoslash title="Extract samples from a video"
import {parseMedia} from '@remotion/media-parser';

await parseMedia({
  src: 'https://remotion.media/video.mp4',
  onVideoTrack: ({track}) => {
    // Get information about the
    console.log(track.width);
    console.log(track.height);
    return (sample) => {
      // Retrieve samples as they are extracted
      console.log(sample.timestamp); // 0
      console.log(sample.data); // Uint8Array(12345)
    };
  },
});
```

<details>
<summary>What are samples?</summary>

Samples contain audio or video data - but they are compressed using codecs like AAC for audio or H.264 for video.  
You can turn audio samples into a waveform and video samples into images by decoding them.

</details>

## Guide

<MediaParserGuideTableOfContents />

## APIs

The following APIs are available:

<TableOfContents />

## Readers

Choose the appropriate reader for your file source:

<ReadersTableOfContents />

## Writers

Choose how to store files downloaded using [`downloadAndParseMedia()`](/docs/media-parser/download-and-parse-media):

<WritersTableOfContents />

## Types

<TypesTableOfContents />

## How does this compare to FFmpeg?

- Media Parser specializes for JavaScript and on the web.  
  It is designed to embrace the language and make use of the APIs that JavaScript has to offer.
- Unlike FFmpeg, Remotion Media Parser does not have functionality for decoding and encoding – it only parses media files.  
  Instead, we hope you combine it with WebCodecs, the native API built into browsers.
- Media Parser has no command line interface and cannot be integrated into native applications.

## How does this compare to MP4Box.js?

MP4Box.js does a better job at parsing the ISO Base Media Format (`.mp4`, `.m4a`, `.mov`) and supports reading more information from it.  
Remotion Media Parser supports more [container formats](/docs/media-parser/format-support), with the goal that it can handle arbitrary user-provided media files.

## Thank you

<table>
  <tr>
    <td>
      <img style={{width: 100}} src="https://pub-646d808d9cb240cea53bedc76dd3cd0c.r2.dev/tellahq_logo.jpeg" />
    </td>
    <td>
      <a href="https://tella.com">Tella</a> for boosting the development of @remotion/media-parser with $10.000!
    </td>
  </tr>
</table>

## License

[Remotion License](https://remotion.dev/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()`](/docs/use-audio-data), all functions can also be used outside of Remotion.

<Installation pkg="@remotion/media-utils"/>

## Functions

<TableOfContents />

## License

MIT

---

### Packages Docs Docs Media Index (`packages/docs/docs/media/index.mdx`)

---
image: /generated/articles-docs-media-index.png
title: '@remotion/media'
crumb: 'API - @remotion/media'
---

import {TableOfContents} from './table-of-contents';

# @remotion/media

This package provides the recommended [`<Video>`](/docs/media/video) and [`<Audio>`](/docs/media/audio) tags for embedding video and audio in Remotion.

Use these tags for new projects. The media tags from the [`remotion`](/docs/remotion) package remain available for direct use and fallback-specific behavior.

## ProRes

Apple ProRes decoding is not enabled by default.
See [Embedding ProRes](/docs/videos/prores) to enable the decoder.

## Components

<TableOfContents />

## License

[Remotion License](/docs/license)

---

### Packages Docs Docs Mediabunny Index (`packages/docs/docs/mediabunny/index.mdx`)

---
image: /generated/articles-docs-mediabunny-index.png
title: Mediabunny
crumb: 'Mediabunny'
sidebar_label: Overview
---

[Mediabunny](https://mediabunny.dev) is an awesome multimedia library by [Vanilagy](https://github.com/Vanilagy).  
It allows for general purpose media tasks like extracting metadata and format conversions such as trimming and cropping in the browser.

## Remotion and Mediabunny

Mediabunny is internally used in packages such as [`@remotion/media`](/docs/media) and [`@remotion/media-utils`](/docs/media-utils) as well as in [Remotion Studio](/docs/studio) and [remotion.dev/convert](https://www.remotion.dev/convert).

Mediabunny is a completely independent project.  
Remotion is a Gold Sponsor of Mediabunny ($1000/month).

## Installation

Install Mediabunny with the version that matches your Remotion installation:

<Installation pkg="mediabunny" />

To upgrade Remotion and Mediabunny together, run [`npx remotion upgrade`](/docs/cli/upgrade):

```bash
npx remotion upgrade
```

See [Mediabunny version used by Remotion](/docs/mediabunny/version) for more details.

## `@remotion/media-parser`

Before Mediabunny, Remotion had its own multimedia libraries [`@remotion/media-parser`](/docs/media-parser) and [`@remotion/webcodecs`](/docs/webcodecs).

Those packages are now deprecated. Use [Mediabunny](https://mediabunny.dev) instead.

## Reporting bugs

If you can pin down an issue to the Mediabunny library directly, then report an issue under [Mediabunny's repo](https://github.com/Vanilagy/mediabunny/issues).  
If an issue also concerns Remotion usage described in our docs, you can file it within the [Remotion repo](https://github.com/remotion-dev/remotion/issues).

## License

Remotion continues to use the [Remotion License](/docs/license).  
If you are using Remotion and are not eligible for the Free License, you continue to require a Company License.

[Mediabunny](https://mediabunny.dev) has a more permissive MPL 2.0 license.  
If you are only using Mediabunny and not Remotion, you don't need a Company License.

## See also

- [`<Video>` and `<Audio>` tags](/docs/mediabunny/new-video)
- [Getting metadata](/docs/mediabunny/metadata)
- [Extracting frames](/docs/mediabunny/extract-frames)
- [Supported formats](/docs/mediabunny/formats)
- [Mediabunny version](/docs/mediabunny/version)
- [Mediabunny documentation](https://mediabunny.dev)

---

### Packages Docs Docs Motion Blur Index (`packages/docs/docs/motion-blur/index.mdx`)

---
image: /generated/articles-docs-motion-blur-index.png
title: Motion blur
crumb: 'Designing visuals'
---

# Motion blur

To realize a realistic motion blur, a frame needs to be duplicated multiple times and blended together.

Remotion provides a [`@remotion/motion-blur`](/docs/motion-blur/api) package to achieve this.

Ask an agent with [Remotion Skills](/docs/ai/skills) installed to add motion blur to a component:

<SuggestedPrompt prompt="/remotion-markup Add motion blur to my text animation" />

## Recommended: HTML-in-canvas motion blur

[`<HtmlInCanvasMotionBlur>`](/docs/motion-blur/html-in-canvas-motion-blur) is the state-of-the-art implementation of motion blur.

It requires [HTML-in-canvas](/docs/html-in-canvas#enabling-the-flag-in-chrome) to be enabled during preview. Rendering needs no configuration.

<Demo type="motion-blur-html-in-canvas" />

## Camera motion blur

[`<CameraMotionBlur>`](/docs/motion-blur/camera-motion-blur) works in browsers that don't have HTML-in-canvas enabled, but layered blending can change colors and opacity.

<Demo type="motion-blur-camera" />

Set `shutterAngle` to control the exposure length and `samples` to control smoothness.

## Trail

[`<Trail>`](/docs/motion-blur/trail) repeats earlier positions behind the current one.

It does not aim to reproduce a realistic camera exposure.

<Demo type="motion-blur-trail" />

## See also

- [`@remotion/motion-blur`](/docs/motion-blur/api)
- [HTML-in-canvas](/docs/html-in-canvas)

---

### Packages Docs Docs Noise Index (`packages/docs/docs/noise/index.mdx`)

---
image: /generated/articles-docs-noise-index.png
title: '@remotion/noise'
---

# @remotion/noise<AvailableFrom v="3.2.32" />

Utility functions that create a noise effect.

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', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/noise
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/noise
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/noise
```

  </TabItem>
</Tabs>

## Functions

<TableOfContents />

## License

MIT

---

### Packages Docs Docs Openai Whisper Index (`packages/docs/docs/openai-whisper/index.mdx`)

---
image: /generated/articles-docs-openai-whisper-index.png
title: '@remotion/openai-whisper'
crumb: 'Subtitle videos'
---

# @remotion/openai-whisper<AvailableFrom v="4.0.217" />

The `@remotion/openai-whisper` package provides utilities for working with the OpenAI Whisper API.

It provides a transformation function for converting the output of the OpenAI Whisper API into an array of [`Caption`](/docs/captions/caption) objects in order to make the captions compatible with other caption-related Remotion APIs.

import {TableOfContents} from './TableOfContents';

<Installation pkg="@remotion/openai-whisper" />

## APIs

<TableOfContents />

## License

MIT

## See also

- [`@remotion/captions`](/docs/captions/api)
- [`@remotion/elevenlabs`](/docs/elevenlabs)
- [`@remotion/install-whisper-cpp`](/docs/install-whisper-cpp)

---

### Packages Docs Docs Options Index (`packages/docs/docs/options/index.mdx`)

---
image: /generated/articles-docs-options-index.png
# Generated by packages/docs/generate-option-docs.ts. Do not edit directly.
# Regenerate: cd packages/docs && bun run generate-option-docs
title: Options
slug: /options
crumb: API
custom_edit_url: https://github.com/remotion-dev/remotion/edit/main/packages/docs/generate-option-docs.ts
---

A list of options that Remotion supports.

CLI flags override [configuration file defaults](/docs/config).

Only the CLI reads the config file. In programmatic APIs, you need to pass all options explicitly.

- [@remotion/media cache size](/docs/options/media-cache-size-in-bytes) (`--media-cache-size-in-bytes`)
- [Allow HTML-in-canvas for client-side rendering](/docs/options/allow-html-in-canvas) (`--allow-html-in-canvas`)
- [API key](/docs/options/api-key)
- [Audio Bitrate](/docs/options/audio-bitrate) (`--audio-bitrate`)
- [Audio Codec](/docs/options/audio-codec) (`--audio-codec`)
- [Audio Latency Hint](/docs/options/audio-latency-hint) (`--audio-latency-hint`)
- [Beep on finish](/docs/options/beep-on-finish) (`--beep-on-finish`)
- [Benchmark concurrencies](/docs/options/concurrencies) (`--concurrencies`)
- [Benchmark runs](/docs/options/runs) (`--runs`)
- [Binaries Directory](/docs/options/binaries-directory) (`--binaries-directory`)
- [Browser](/docs/options/browser) (`--browser`)
- [Browser download callback function](/docs/options/on-browser-download)
- [Browser executable](/docs/options/browser-executable) (`--browser-executable`)
- [Chrome Mode](/docs/options/chrome-mode) (`--chrome-mode`)
- [Codec](/docs/options/codec) (`--codec`)
- [Color space](/docs/options/color-space) (`--color-space`)
- [Concurrency](/docs/options/concurrency) (`--concurrency`)
- [Config file](/docs/options/config) (`--config`)
- [Create reproduction](/docs/options/repro) (`--repro`)
- [CRF](/docs/options/crf) (`--crf`)
- [Dark Mode](/docs/options/dark-mode) (`--dark-mode`)
- [Default coding agent](/docs/options/coding-agent) (`--coding-agent`)
- [Default editor](/docs/options/editor) (`--editor`)
- [Default premount duration in seconds](/docs/options/default-premount-in-seconds) (`--default-premount-in-seconds`)
- [delayRender() timeout](/docs/options/timeout) (`--timeout`)
- [Disable browser auto-open](/docs/options/no-open) (`--no-open`)
- [Disable Git source](/docs/options/disable-git-source) (`--disable-git-source`)
- [Disable Headless Mode](/docs/options/disable-headless) (`--disable-headless`)
- [Disable or Enable keyboard shortcuts](/docs/options/disable-keyboard-shortcuts) (`--disable-keyboard-shortcuts`)
- [Disable or enable Studio canvas tabs](/docs/options/disable-canvas-tabs) (`--disable-canvas-tabs`)
- [Disable or enable Studio interactivity](/docs/options/disable-interactivity) (`--disable-interactivity`)
- [Disable or Enable the Ask AI option](/docs/options/disable-ask-ai) (`--disable-ask-ai`)
- [Disable shared-memory capture](/docs/options/disable-shared-memory-capture) (`--disable-shared-memory-capture`)
- [Disable web security](/docs/options/disable-web-security) (`--disable-web-security`)
- [Disallow parallel encoding](/docs/options/disallow-parallel-encoding) (`--disallow-parallel-encoding`)
- [Enable cancellation](/docs/options/enable-cancellation) (`--enable-cancellation`)
- [Enable Cross-Site Isolation](/docs/options/cross-site-isolation) (`--cross-site-isolation`)
- [Enable Lambda Insights](/docs/options/enable-lambda-insights) (`--enable-lambda-insights`)
- [Enable Multiprocess on Linux](/docs/options/enable-multiprocess-on-linux) (`--enable-multiprocess-on-linux`)
- [Enforce Audio Track](/docs/options/enforce-audio-track) (`--enforce-audio-track`)
- [Env File](/docs/options/env-file) (`--env-file`)
- [Every nth frame](/docs/options/every-nth-frame) (`--every-nth-frame`)
- [FFmpeg -bufsize flag](/docs/options/buffer-size) (`--buffer-size`)
- [FFmpeg -maxrate flag](/docs/options/max-rate) (`--max-rate`)
- [For seamless AAC concatenation](/docs/options/for-seamless-aac-concatenation) (`--for-seamless-aac-concatenation`)
- [Force New Studio](/docs/options/force-new) (`--force-new`)
- [Frame](/docs/options/frame) (`--frame`)
- [Frame Range](/docs/options/frames) (`--frames`)
- [GOP size](/docs/options/gop) (`--gop`)
- [Hardware Acceleration](/docs/options/hardware-acceleration) (`--hardware-acceleration`)
- [Ignore certificate errors](/docs/options/ignore-certificate-errors) (`--ignore-certificate-errors`)
- [Image Sequence](/docs/options/sequence) (`--sequence`)
- [Image Sequence Pattern](/docs/options/image-sequence-pattern) (`--image-sequence-pattern`)
- [Input Props](/docs/options/props) (`--props`)
- [IPv4](/docs/options/ipv4) (`--ipv4`)
- [Is Production](/docs/options/is-production) (`--is-production`)
- [JPEG Quality](/docs/options/jpeg-quality) (`--jpeg-quality`)
- [Keep AudioContext alive (experimental)](/docs/options/experimental-keep-audio-context-alive) (`--experimental-keep-audio-context-alive`)
- [Lambda render expiration](/docs/options/delete-after) (`--delete-after`)
- [Lambda render expiration](/docs/options/enable-folder-expiry) (`--enable-folder-expiry`)
- [License key](/docs/options/license-key) (`--license-key`)
- [Log Level](/docs/options/log) (`--log`)
- [Metadata](/docs/options/metadata) (`--metadata`)
- [Muted](/docs/options/muted) (`--muted`)
- [Number of GIF loops](/docs/options/number-of-gif-loops) (`--number-of-gif-loops`)
- [Number of shared audio tags](/docs/options/number-of-shared-audio-tags) (`--number-of-shared-audio-tags`)
- [OffthreadVideo cache size](/docs/options/offthreadvideo-cache-size-in-bytes) (`--offthreadvideo-cache-size-in-bytes`)
- [OffthreadVideo threads](/docs/options/offthreadvideo-video-threads) (`--offthreadvideo-video-threads`)
- [OpenGL renderer](/docs/options/gl) (`--gl`)
- [Output Directory](/docs/options/out-dir) (`--out-dir`)
- [Override Duration](/docs/options/duration) (`--duration`)
- [Override FPS](/docs/options/fps) (`--fps`)
- [Override Height](/docs/options/height) (`--height`)
- [Override Width](/docs/options/width) (`--width`)
- [Overwrite output](/docs/options/overwrite) (`--overwrite`)
- [Package Manager](/docs/options/package-manager) (`--package-manager`)
- [Pixel format](/docs/options/pixel-format) (`--pixel-format`)
- [Port](/docs/options/port) (`--port`)
- [Prefer lossless](/docs/options/prefer-lossless) (`--prefer-lossless`)
- [Preserve pitch on playback](/docs/options/preserve-pitch-on-playback) (`--preserve-pitch-on-playback`)
- [Preview Sample Rate](/docs/options/preview-sample-rate) (`--preview-sample-rate`)
- [ProRes profile](/docs/options/prores-profile) (`--prores-profile`)
- [Public Directory](/docs/options/public-dir) (`--public-dir`)
- [Public License Key](/docs/options/public-license-key) (`--public-license-key`)
- [Public Path](/docs/options/public-path) (`--public-path`)
- [Rspack](/docs/options/rspack) (`--rspack`)
- [Sample Rate](/docs/options/sample-rate) (`--sample-rate`)
- [Scale](/docs/options/scale) (`--scale`)
- [Separate audio to](/docs/options/separate-audio-to) (`--separate-audio-to`)
- [Sequence Activity limit](/docs/options/sequence-activity-limit) (`--sequence-activity-limit`)
- [Show frame numbers of layer](/docs/options/show-layer-frame-numbers) (`--show-layer-frame-numbers`)
- [Show premounting in the Studio timeline](/docs/options/show-premounting) (`--show-premounting`)
- [Skip Skills](/docs/options/skip-skills) (`--skip-skills`)
- [Still Image Format](/docs/options/still-image-format) (`--image-format`)
- [Throw if site exists](/docs/options/throw-if-site-exists) (`--throw-if-site-exists`)
- [User agent](/docs/options/user-agent) (`--user-agent`)
- [Version](/docs/options/version) (`--version`)
- [Video Bitrate](/docs/options/video-bitrate) (`--video-bitrate`)
- [Video Image Format](/docs/options/video-image-format) (`--image-format`)
- [Webhook custom data](/docs/options/webhook-custom-data) (`--webhook-custom-data`)
- [Webpack Bundle Caching](/docs/options/bundle-cache) (`--bundle-cache`)
- [Webpack Polling](/docs/options/webpack-poll) (`--webpack-poll`)
- [x264 Preset](/docs/options/x264-preset) (`--x264-preset`)

---

### Packages Docs Docs Paths Index (`packages/docs/docs/paths/index.mdx`)

---
image: /generated/articles-docs-paths-index.png
title: '@remotion/paths'
crumb: 'SVG'
---

import {TableOfContents} from './table-of-contents';

A package providing utility functions for dealing with SVG paths. This package includes code from [`svg-path-properties`](https://www.npmjs.com/package/svg-path-properties), [`svg-path-reverse`](https://github.com/Pomax/svg-path-reverse#readme), [`svgpath`](https://github.com/fontello/svgpath), [`svg-path-bbox`](https://github.com/mondeja/svg-path-bbox), [`translate-svg-path`](https://github.com/michaelrhodes/translate-svg-path) and [`d3-interpolate-path`](https://github.com/pbeshai/d3-interpolate-path) with the following improvements:

- Functional style APIs
- First class Typescript types
- Documentation with examples
- ESM import style

These utilities can be used outside a Remotion composition.

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', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/paths
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/paths
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/paths
```

  </TabItem>
</Tabs>

## Functions

<TableOfContents />

## License

MIT

---

### Packages Docs Docs Player Index (`packages/docs/docs/player/index.mdx`)

---
image: /generated/articles-docs-player-index.png
title: '@remotion/player'
---

import {PlayerExampleWithControls} from '../../components/PlayerExampleWithControls';
import {PlayerTableOfContents, PlayerGuide} from './TableOfContents';

Using the Remotion Player you can embed Remotion videos in any React app and customize the video content at runtime.

## Demo

Play the video, then tweak the parameters below the video.

<PlayerExampleWithControls />

See the [source code](https://github.com/remotion-dev/remotion/blob/main/packages/docs/components/PlayerExampleWithControls.tsx) for this example.

## Templates

The following templates include the Player and cloud rendering and are a good starting point for building a video app:

- [Next.js](/templates/next)
- [Next.js (Vercel Sandbox)](/templates/vercel)
- [React Router 7 (Remix)](/templates/react-router)

## API

<PlayerTableOfContents />

## Guide

<PlayerGuide />

## See also

- [Installation](/docs/player/installation)
- [API](/docs/player/player)

---

### Packages Docs Docs Recorder Index (`packages/docs/docs/recorder/index.mdx`)

---
image: /generated/articles-docs-recorder-index.png
title: Remotion Recorder
sidebar_label: Introduction
crumb: Templates
hide_title: true
---

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="/recorder/recorder-logo-dark.gif" />
    <img alt="Animated Remotion Recorder Logo" src="/recorder/recorder-logo-light.gif" />
  </picture>
</p>

The Remotion Recorder is a video production tool <strong>built entirely in JavaScript</strong>.

## Recording

Record your facecam and screen in sync but independently. This allows you to create a dynamic layout later.

<div style={{overflowX: 'auto', WebkitOverflowScrolling: 'touch', }}>
<table style={{  tableLayout: "fixed", width: 950, marginBottom: 0 }}>

<tr>
    <td valign="top" style={{width: 950/ 2}}>
      <img src="/recorder/individual.png"></img>
      </td>
    <td valign="top" style={{width: 950/ 2}}>
      <video src="/recorder/volume.mp4" autoPlay muted playsInline loop></video>
    </td>

  </tr>
  <tr>
    <td valign="top" style={{width: 950/ 2}}>
      Record webcam and display as separate streams. Up to 4 sources can be recorded at the same time!   
         </td>
    <td valign="top" style={{width: 950/ 2}}>
   Ensure you are in the center of the video and you are not too close to the microphone.
    </td>
</tr>
</table>
</div>

## Different platforms require different formats

Each platform has its own conventions for how videos should look.

<div style={{overflowX: 'auto', WebkitOverflowScrolling: 'touch', }}>
<table style={{  tableLayout: "fixed", width: 950 }}>
  <tr>
    <td valign="top">
      <img
        style={{ height: 230,  border: "3px solid black", borderRadius: 5, aspectRatio: '1 / 1' }}
        src="/recorder/vps-square.png"
      />
    </td>
    <td valign="top">
      <img
        style={{
          height: 230,
          border: "3px solid black",
          borderRadius: 5,
          overflow: "hidden",
        }}
        src="/recorder/vps-landscape.png"
      />
  
    </td>
    <td valign="top">
     <div
        style={{
          display: "flex",
          flexDirection: "row",
          justifyContent: "center",
        }}
      >
        <div
          style={{
            height: 230,
            border: "3px solid black",
            borderRadius: 5,
            overflow: "hidden",
            aspectRatio: "9 / 16",
            backgroundColor: "#FAFAFA",
            justifyContent: "center",
            alignItems: "center",
            color: "#ccc",
            display: "flex",
            fontWeight: "bold",
          }}
        >
          WIP
        </div>
      </div>
    </td>

  </tr>
  <tr>
  <td valign="top">      
     <strong>Twitter, LinkedIn</strong>
      <div>1:1</div>
      <div>Muted by default</div>
      <div>Captions burned in</div>
  </td>
  <td valign="top">   
   <strong>YouTube</strong>
      <div>16:9</div>
      <div>Audio by default</div>
      <div>
        Captions as .srt file{" "}
      </div>
      <div>Endcard with related videos</div>
      </td>
  <td valign="top">
   
      <strong>
        TikTok, Reels, Shorts{" "}
        <sup>
          <a href="#tiktok-format">planned</a>
        </sup>
      </strong>
      <div>9:16</div>
      <div>Safe space at bottom required</div>
      <div>Word-by-word captions</div>
  </td>
  </tr>
</table>
</div>

The goal of the Recorder: Edit once <strong>and feel native on each platform</strong>.

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](https://buffer.com/resources/square-video-vs-landscape-video/).

## Captions are essential

Generate captions locally using [Whisper.cpp](https://github.com/ggerganov/whisper.cpp). The Recorder will automatically install it for you.  
AI will make mistakes - so we make it easy to correct them.

<div style={{overflowX: 'auto', WebkitOverflowScrolling: 'touch', }}>
<table style={{  tableLayout: "fixed", width: 950, marginBottom: 0 }}>  <tr>
    <td valign="top" style={{width: 950/ 3}}>
      <video src="/recorder/wordlevel.webm" autoPlay muted playsInline loop></video>
      Captions have word-level timings
      </td>
    <td valign="top" style={{width: 950/ 3}}>
      <video src="/recorder/noorphans.webm" autoPlay muted playsInline loop></video>
     Orphan words are avoided by balancing the text layout
    </td>
    <td valign="top" style={{width: 950/ 3}}>
      <video src="/recorder/monospace.webm" autoPlay muted playsInline loop></video>
      Use `backticks` to highlight technical terms
    </td>

  </tr>
</table>
<table style={{ tableLayout: "fixed", width: 950}}>
  <tr style={{borderTop: 0}}>
    <td valign="top" style={{width: 950/ 3}}>
      <video  style={{height: 300}} src="/recorder/subseditor.webm" autoPlay muted playsInline loop></video>
      Fix captions quickly by clicking on a word
    </td>
    <td valign="top" style={{width: 950/ 3}}>
      <img style={{ borderRadius: 5}} src="/recorder/autocorrect.png" autoPlay muted playsInline loop></img><br/>
      Write a JavaScript function to fix common misspellings
    </td>
    <td valign="top" style={{width: 950/ 3}}>
      <img style={{width: '100%', borderRadius: 5}} src="/recorder/asjson.png" autoPlay muted playsInline loop></img><br/>
      Captions are stored as editable JSON
    </td>
  </tr>
</table>
</div>

## Agnostic endcards

Your viewer watched the entire video! Now don't make them forget about you.

<div style={{overflowX: 'auto', WebkitOverflowScrolling: 'touch', }}>

<table style={{ width: 950, tableLayout: "fixed" }}>
  <tr>
    <td valign="top" style={{ width: 950 / 2 }}>
      <p align="center" style={{ marginTop: 0, marginBottom: 0 }}>
        <img
          style={{ borderRadius: 5, height: 250 }}
          src="/recorder/endcard-square.png"
          autoPlay
          muted
          playsInline
          loop
        ></img>
      </p>
      If you post on Twitter, the call-to-action is "Follow" and your other platforms
      are linked.
    </td>
    <td valign="top" style={{ width: 950 / 2 }}>
      <img
        style={{ width: 950 / 2, borderRadius: 5 }}
        src="/recorder/endcard-youtube.png"
        autoPlay
        muted
        playsInline
        loop
      ></img>
      <br />
      If you post on YouTube, the call to action is "Subscribe" and cutouts for related
      videos are made.
    </td>
  </tr>
</table>
</div>

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.

<div style={{overflowX: 'auto', WebkitOverflowScrolling: 'touch'}}>
  <table style={{tableLayout: 'fixed', width: 950}}>
    <tr style={{borderTop: 0}}>
      <td valign="top" style={{width: 950 / 3}}>
        <img style={{borderRadius: 5}} src="/recorder/theme-light.png"></img>
        Look of the built-in light theme
      </td>
      <td valign="top" style={{width: 950 / 3}}>
        <img style={{borderRadius: 5}} src="/recorder/theme-dark.png"></img>
        <br />
        Look of the built-in dark theme
      </td>
      <td valign="top" style={{width: 950 / 3}}>
        <img style={{borderRadius: 5}} src="/recorder/theme-fancy.png"></img>
        <br />
        Use CSS to make it your own!
      </td>
    </tr>
  </table>
</div>

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

- [Editor Starter](/docs/editor-starter)

---

<sup id="tiktok-format">1)</sup> 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](https://rive.app) animations in Remotion.

## Installation

Install `@remotion/rive`

<Tabs defaultValue="npm" values={[
{ label: 'npm', value: 'npm', },
{ label: 'yarn', value: 'yarn', },
{ label: 'pnpm', value: 'pnpm', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/rive
```

</TabItem>
<TabItem value="yarn">

```bash
yarn add @remotion/rive
```

</TabItem>
<TabItem value="pnpm">

```bash
pnpm i @remotion/rive
```

</TabItem>
</Tabs>

## API

<TableOfContents />

## License

[Remotion License](https://remotion.dev/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<AvailableFrom v="4.0.490" />

Animated marker highlights, circles, boxes, underlines and other hand-drawn text annotations for Remotion videos.

import {TableOfContents} from './table-of-contents';

<Installation pkg="@remotion/rough-notation" />

## APIs

<TableOfContents />

## 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`](/docs/sequence#from), [`durationInFrames`](/docs/sequence#durationinframes), [`trimBefore`](/docs/sequence#trimbefore), [`playbackRate`](/docs/sequence#playbackrate), [`freeze`](/docs/sequence#freeze), [`hidden`](/docs/sequence#hidden), [`name`](/docs/sequence#name) and [`showInTimeline`](/docs/sequence#showintimeline) from [`<Sequence>`](/docs/sequence).

From <AvailableFrom v="4.0.528" inline />, it also inherits [`premountFor`](/docs/sequence#premountfor), [`postmountFor`](/docs/sequence#postmountfor), [`styleWhilePremounted`](/docs/sequence#stylewhilepremounted) and [`styleWhilePostmounted`](/docs/sequence#stylewhilepostmounted) from [`<Sequence>`](/docs/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<AvailableFrom v="4.0.360" />

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', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/rounded-text-box
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/rounded-text-box
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/rounded-text-box
```

  </TabItem>
</Tabs>

## Functions

<TableOfContents />

## 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()<AvailableFrom v="4.0.533" />

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.

```ts twoslash title="get-insertion-index.ts"
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()`](/docs/codemods/reorder-nodes) 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

<CompatibilityTable chrome firefox safari nodejs="" bun="" serverlessFunctions="" clientSideRendering={false} serverSideRendering player studio="" hideServers />

## See also

- [`getCanvasSequenceReorderSelection()`](/docs/sdk/get-canvas-sequence-reorder-selection)
- [`reorderNodes()`](/docs/codemods/reorder-nodes)

---

### 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<AvailableFrom v="4.0.527" />

Build a composition preview and layer list for a Remotion authoring interface. The package combines [`<Player>`](/docs/player/player) 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

<Installation pkg="@remotion/sdk" />

Install [`@remotion/player`](/docs/player/installation) as well. Keep the Remotion packages on the same version.

## Basic example

Pass the same controller to [`<Canvas>`](/docs/sdk/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>`](/docs/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()`](/docs/sdk/get-canvas-sequence-reorder-selection) chooses the dragged sequence group. [`getCanvasSequenceReorderInsertionIndex()`](/docs/sdk/get-canvas-sequence-reorder-insertion-index) identifies valid drop positions. Persist the result with [`reorderNodes()`](/docs/codemods/reorder-nodes).

## Selection identity

The built-in [`getCanvasSequenceNodePathInfo()`](/docs/sdk/get-canvas-sequence-node-path-info) 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()`](/docs/sdk/create-canvas-controller#setsequencenodepaths). For projects compiled with [`@remotion/browser-bundler`](/docs/browser-bundler), [`getCanvasSequenceSourceLocation()`](/docs/sdk/get-canvas-sequence-source-location) returns the file and position of each sequence's JSX element, which [`getNodes()`](/docs/codemods/get-nodes) 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`](/docs/sdk/create-canvas-controller#sequencecontrols) 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`](/docs/codemods).

While a value is being dragged, [`controller.overrides`](/docs/sdk/create-canvas-controller#overrides) previews it on the canvas immediately. Persist the final value when the gesture ends, then clear the override.

Pass [`onSequencePropsChange`](/docs/sdk/canvas#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`](/docs/sdk/canvas#getsequencepropstatuses), it respects how the source is written: computed values cannot be moved and keyframed values receive a keyframe.

## Keyframes<AvailableFrom v="4.0.530" />

Props animated with `interpolate()` are reported as `keyframed` by [`getNodeProps()`](/docs/codemods/get-node-props). 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()`](/docs/sdk/get-canvas-keyframes) places the keyframes of a prop on the timeline. [`getCanvasKeyframeToggle()`](/docs/sdk/get-canvas-keyframe-toggle) describes a keyframe button at the playhead and returns the change that adds or removes a keyframe there, while [`getCanvasPropValueAtFrame()`](/docs/sdk/get-canvas-prop-value-at-frame) reads the animated value for an inspector. [`startCanvasKeyframeDrag()`](/docs/sdk/start-canvas-keyframe-drag) moves keyframes with the pointer, previewing the result through `controller.overrides`. Every edit is a `CanvasKeyframeChange` whose `operation` you pass to [`updateNodeKeyframes()`](/docs/codemods/update-node-keyframes).

Between two keyframes, [`getCanvasKeyframeEasingSegments()`](/docs/sdk/get-canvas-keyframe-easing-segments) describes the segments a timeline can draw and select, and [`getCanvasKeyframeEasingChange()`](/docs/sdk/get-canvas-keyframe-easing-change) sets the easing of one, with `canvasKeyframeEasingPresets` for a picker. [`getCanvasKeyframeSettings()`](/docs/sdk/get-canvas-keyframe-settings) and [`getCanvasKeyframeSettingsChange()`](/docs/sdk/get-canvas-keyframe-settings-change) read and write the extrapolation, `output` mode and `posterize` of the interpolation. [`getCanvasKeyframeChangeOverride()`](/docs/sdk/get-canvas-keyframe-change-override) turns any change into an override, so the canvas shows it before the source is updated.

## APIs

import {TableOfContents} from './table-of-contents';

<TableOfContents />

## License

[Remotion License](/docs/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<AvailableFrom v="4.0.429" />

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';

<Installation pkg="@remotion/sfx" />

## Exports

<TableOfContents />

## 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', },
]
}>
<TabItem value="npm">

```bash
npm i @remotion/shapes
```

  </TabItem>

  <TabItem value="pnpm">

```bash
pnpm i @remotion/shapes
```

  </TabItem>

  <TabItem value="yarn">

```bash
yarn add @remotion/shapes
```

  </TabItem>
</Tabs>

## Functions

<TableOfContents />

## 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~~<AvailableFrom v="4.0.435" />

:::info Deprecated
`@remotion/starburst` is deprecated and will no longer be published starting with Remotion 5.0. Migrate to [`starburst()`](/docs/effects/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';

<Installation pkg="@remotion/starburst" />

## APIs

<TableOfContents />

## License

[Remotion License](/docs/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<AvailableFrom v="4.0.502" />

With this package, you can create payloads for passing content to Remotion Studio.

<Installation pkg="@remotion/studio-protocol" />

## Capabilities

### Installing Remotion Elements

Websites can provide [Elements](/elements) to a Studio either using drag-and-drop or using an installation dialog.

<Step>1</Step> Create an Element payload with [`createElementPayload()`](/docs/studio-protocol/create-element-payload).<br />
<Step>2</Step> Put it on a drag event with [`setStudioDragData()`](/docs/studio-protocol/set-studio-drag-data), or send a signal to a Studio using [`installInStudio()`](/docs/studio-protocol/install-in-studio).

| Method                                                         | Benefits                                                                                  | Tradeoffs                                                                                       |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| [Drag-and-drop](/docs/studio-protocol/set-studio-drag-data)    | The user chooses the exact Studio tab, timeline position, and canvas position.            | Studio labels the source as [unverified](/docs/studio-protocol/security#confirmation-boundary). |
| [Installation dialog](/docs/studio-protocol/install-in-studio) | 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()`](/docs/studio-protocol/add-element-library-to-studio) you can request to add an Element Library to the Studio.

### Previewing Elements

Using [`buildOpenInRemotionNewUrl()`](/docs/studio-protocol/build-open-in-remotion-new-url), you can open your [Element](/elements) in [remotion.dev/new](https://remotion.dev/new).

## APIs

import {TableOfContents} from './table-of-contents';

<TableOfContents />

## Security

Learn about the [confirmation and origin policy](/docs/studio-protocol/security).

## License

[Remotion License](/docs/license)

## See also

- [Building Element Libraries](/docs/elements/libraries)

---

### 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](https://tailwindcss.com/) with Remotion, as documented on our [TailwindCSS](/docs/tailwind) page.

## Installation

Install `@remotion/tailwind-v4` as well as TailwindCSS dependencies.

<Installation pkg="@remotion/tailwind-v4" />

<br />

[Override the bundler config](/docs/bundlers) by using [`enableTailwind()`](/docs/tailwind/enable-tailwind).

```ts twoslash title="remotion.config.ts"
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](/docs/tailwind) page.

## APIs

<TableOfContents />

---

### 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](/docs/tailwind-v4/overview).
:::

This package provides utilities useful for integrating [TailwindCSS](https://tailwindcss.com/) with Remotion, as documented on our [TailwindCSS](/docs/tailwind) page.

## Installation

Install `@remotion/tailwind` as well as TailwindCSS dependencies.

<Installation pkg="@remotion/tailwind" />

<br />

[Override the bundler config](/docs/bundlers) by using [`enableTailwind()`](/docs/tailwind/enable-tailwind).

```ts twoslash title="remotion.config.ts"
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](/docs/tailwind) page.

## APIs

<TableOfContents />

---

### 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';

# &lt;Timeline&gt;

<img alt="Remotion Timeline Banner" src="/img/remotion-timeline-banner.jpg" />
<br />
<br />

A paid customizable timeline component that integrates seamlessly with [Remotion Player](/docs/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](https://www.remotion.pro/timeline).

<TableOfContents />

## 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
- `CanvasComposition` for 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](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md) and [its own specific license](https://www.remotion.pro/timeline?tab=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](/docs/license/pricing). Read the [Terms & Conditions](/docs/terms).

- The Remotion Timeline License [can be seen in the Remotion Store Page](https://www.remotion.pro/timeline) 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<AvailableFrom v="4.0.53" />

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {TableOfContents} from './table-of-contents';

This package provides the [`<TransitionSeries>`](/docs/transitions/transitionseries) component for transitioning between two scenes as well as timing presets.

## Installation

<Installation pkg="@remotion/transitions" />

## API

<TableOfContents />

## License

[Remotion License](https://remotion.dev/license)

## See also

- [Transitions](/docs/transitioning)

---

### 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<AvailableFrom v="4.0.426" />

:::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](https://vercel.com/docs/vercel-sandbox).
This package requires `@vercel/sandbox` as a peer dependency.

## APIs

<TableOfContents />

## License

[Remotion License](/docs/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<AvailableFrom v="4.0.523" />

Separate a video into opaque base and transparent foreground layers, locally in the browser or [Node.js](/docs/video-matting/node) using WebGPU.

import {TableOfContents} from './table-of-contents';

## Installation

<Installation pkg="@remotion/video-matting @huggingface/transformers" />

## 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()`](/docs/video-matting/separate-video-layers).

## 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

<TableOfContents />

## Requirements

A GPU is needed for this.
Use [`canUseVideoMatting()`](/docs/video-matting/can-use-video-matting) 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()`](/docs/video-matting/separate-video-layers) checks these media capabilities for the selected input.

## License

The package is MIT licensed.  
Models retain the licenses listed under [`getAvailableModels()`](/docs/video-matting/get-available-models).

---

### 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`](/docs/media/video) component.

```tsx twoslash
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](/docs/terminology/public-dir) and reference it using [`staticFile()`](/docs/staticfile).

```tsx twoslash
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`](/docs/media/video#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).

```tsx twoslash
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`](/docs/media/video#durationinframes) to select how many source frames should play.

```tsx twoslash
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`](/docs/media/video#from) prop to delay the appearance of a video.
In the example below, the video will start playing at frame 60.

```tsx twoslash
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.

```tsx twoslash
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`](/docs/media/video#volume) prop.

```tsx twoslash
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`](/docs/media/video#muted) prop.

```tsx twoslash
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](/docs/audio/volume) for more ways you can control volume.

## Speed

You can use the [`playbackRate`](/docs/media/video#playbackrate) prop to change the speed of the video.

```tsx twoslash
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](/docs/videos/accelerated-video).

## Looping

Use the [`loop`](/docs/media/video#loop) prop to restart the video when it reaches the end.

```tsx twoslash title="Looping a 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')} loop />;
};
```

To learn how looping interacts with `trimBefore` and `durationInFrames`, see [Timing and trimming](/docs/timing).

## GIFs

See: [Using GIFs](/docs/gif)

## See also

- [`<Video>` from `@remotion/media`](/docs/media/video)
- [Comparison of video tags](/docs/video-tags)
- [Using Audio](/docs/using-audio)

---

### 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 <AvailableFrom v="4.0.491" inline />.

### Key differences from server-side rendering

Unlike server-side rendering with [`@remotion/renderer`](/docs/renderer), client-side rendering:

- Runs in the browser instead of Node.js
- Encodes with WebCodecs using [Mediabunny](/docs/mediabunny) instead of FFmpeg
- Limited to a subset of tags and CSS properties - see [limitations](/docs/client-side-rendering/limitations)
- No bundling step - takes components and video config directly

## Installation

<Installation pkg="@remotion/web-renderer" />

## API

import {TableOfContents} from './TableOfContents';

<TableOfContents />

## See also

- [Client-side rendering overview](/docs/client-side-rendering)
- [How client-side rendering works](/docs/client-side-rendering/how-it-works)
- [Limitations](/docs/client-side-rendering/limitations)
- [Telemetry](/docs/telemetry)
- [Server-side rendering](/docs/ssr)

---

### 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<AvailableFrom v="4.0.229" />

:::warning
[We are phasing out Remotion WebCodecs and are moving to Mediabunny](/blog/mediabunny)!
:::

This package provides APIs for converting videos in the browser.  
It leverages [`@remotion/media-parser`](/docs/media-parser) to parse the video and audio data, and then uses the [WebCodecs API](https://developer.mozilla.org/en-US/docs/Web/API/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](/docs/webcodecs/convert-a-video) (From .mp4, .webm, .mov, .mkv, .m3u8, .ts, .avi, .mp3, .flac, .wav, .m4a, .aac to .mp4, .webm, .wav)
- [Rotate videos](/docs/webcodecs/rotate-a-video)
- [Efficiently extract frames from a video](/docs/webcodecs/extract-frames)
- Extract audio from a video
- Manipulate the pixels of a video
- [Fix videos that were recorded with `MediaRecorder`](/docs/webcodecs/fix-mediarecorder-video)
- 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](https://github.com/remotion-dev/webcodecs-benchmark) here.

## 💼 License Disclaimer

<LicenseDisclaimer />

## 🚧 Unstable API Warning

<UnstableDisclaimer />

## Installation

<Installation pkg="@remotion/webcodecs" />

## Guide

<WebCodecsGuide />

## APIs

The following APIs are available:

<TableOfContents />

---

### 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`](/docs/whisper-webgpu), which uses WebGPU and does not require cross-origin isolation. Existing 4.x versions remain available.
:::

Similar to [@remotion/install-whisper-cpp](/docs/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

<Installation pkg="@remotion/whisper-web" />

## 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements) for using `SharedArrayBuffer` in modern browsers.

See: [Important Considerations](/docs/whisper-web/can-use-whisper-web#important-considerations)

### Vite

To use `@remotion/whisper-web` with Vite, you need to make two important changes:

1. Exclude the package from Vite's dependency optimization to prevent [known issues](https://github.com/vitejs/vite/issues/11672#issuecomment-1397855641)
2. Configure the required security headers for `SharedArrayBuffer` support

```tsx title="vite.config.ts"
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

```tsx twoslash title="Transcribing with @remotion/whisper-web"
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

<TableOfContents />

## 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<AvailableFrom v="4.0.518" />

Transcribe audio locally in the browser or Node.js using timestamped Whisper models and WebGPU through [Transformers.js](https://huggingface.co/docs/transformers.js), and convert the result to [`@remotion/captions`](/docs/captions).

import {TableOfContents} from './table-of-contents';

## Installation

<Installation pkg="@remotion/whisper-webgpu @huggingface/transformers" />

## Example

```ts twoslash title="transcribe.ts"
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](/docs/whisper-webgpu/node) for a complete Node.js example.

## APIs

<TableOfContents />

## Requirements

You obviously need a GPU.  
Use [`canUseWhisperWebGpu()`](/docs/whisper-webgpu/can-use-whisper-webgpu) 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](https://github.com/colinhacks/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`](/docs/zod-types/v3) instead of [`@remotion/zod-types`](/docs/zod-types).
:::

## Installation

<Installation pkg="@remotion/zod-types" />

## API

<ZodTypesTableOfContents />

## License

[Remotion License](https://remotion.dev/license)

---

### Packages Docs Elements Audio Index (`packages/docs/elements/audio/index.mdx`)

---
title: Audio
description: Audio-reactive Elements for visualizing voices, podcasts, music, and other sounds.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Audio

<ElementLibrary category="audio" />

---

### Packages Docs Elements Backgrounds Index (`packages/docs/elements/backgrounds/index.mdx`)

---
title: Backgrounds
description: Drop-in background Elements for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Backgrounds

<ElementLibrary category="backgrounds" />

---

### Packages Docs Elements Captions Index (`packages/docs/elements/captions/index.mdx`)

---
title: Captions
description: Drop-in synchronized caption Elements for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Captions

<ElementLibrary category="captions" />

<div className="caption-library-instructions">

## How to use

### Transcribing in the Studio

<Step>1</Step> Select a video or audio.<br/>
<Step>2</Step> Click <kbd>Generate captions</kbd> in the inspector.<br/>
<Step>3</Step> Keep the default Basic Captions style, or select a caption Element in the <kbd>Styles</kbd> tab.<br/>
<Step>4</Step> Click <kbd>Generate captions</kbd> to transcribe and insert captions using the chosen style.<br/>

Style selection is available from <AvailableFrom v="4.0.535" inline />. Basic Captions works without loading the Element library.

### Importing captions into Studio<AvailableFrom v="4.0.521" />

<Step>1</Step> Install an Element from below.<br/>
<Step>2</Step> Select its caption layer in Studio.<br/>
<Step>3</Step> In the Captions inspector, click <kbd>Import</kbd> and choose a file. <br/>

Supported formats:

- Remotion [`Caption[]`](/docs/captions/caption) JSON
- SRT
- ElevenLabs Speech-to-Text or segmented JSON
- OpenAI Whisper JSON transcript (verbose mode must be on)

</div>

---

### Packages Docs Elements Commerce Index (`packages/docs/elements/commerce/index.mdx`)

---
title: Effects
description: Animated visual effects for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Effects

<ElementLibrary category="commerce" />

---

### Packages Docs Elements Data Index (`packages/docs/elements/data/index.mdx`)

---
title: Charts & Data
description: Animated charts and data visualization Elements for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Charts & Data

<ElementLibrary category="data" />

---

### Packages Docs Elements Layouts Index (`packages/docs/elements/layouts/index.mdx`)

---
title: Layouts
description: Animated layouts for arranging content in Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Layouts

<ElementLibrary category="layouts" />

---

### Packages Docs Elements Maps Index (`packages/docs/elements/maps/index.mdx`)

---
title: Maps
description: Animated map and geographic visualization Elements for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Maps

<ElementLibrary category="maps" />

---

### Packages Docs Elements Overlays Index (`packages/docs/elements/overlays/index.mdx`)

---
title: Overlays
description: Drop-in overlay Elements for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Overlays

<ElementLibrary category="overlays" />

---

### Packages Docs Elements Storytelling Index (`packages/docs/elements/storytelling/index.mdx`)

---
title: Storytelling
description: Drop-in storytelling scenes for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Storytelling

<ElementLibrary category="storytelling" />

---

### Packages Docs Elements Text Index (`packages/docs/elements/text/index.mdx`)

---
title: Text Effects
description: Drop-in text effect Elements for Remotion videos.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# Text Effects

<ElementLibrary category="text" />

---

### Packages Docs Elements Youtube Index (`packages/docs/elements/youtube/index.mdx`)

---
title: YouTube
description: Elements for YouTube videos, including end cards and audience engagement graphics.
---

import {ElementLibrary} from '@site/src/components/Elements/ElementLibrary';

# YouTube

<ElementLibrary category="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<AvailableFrom v="4.0.137"/>

Commands for managing the browser used by Remotion.

## Commands

<TableOfContents />

## See also

- [Chrome Headless Shell](/docs/miscellaneous/chrome-headless-shell)
- [`ensureBrowser()`](/docs/renderer/ensure-browser)

---

### 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`](/docs/lambda/permissions), 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()`](/docs/lambda/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()`](/docs/lambda/rendermediaonlambda) on services such as [`Lambda`](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html), [`EC2`](https://aws.amazon.com/ec2/), and other [`computing services`](https://aws.amazon.com/products/compute/) where the use of long-term credentials is not an option.

AWS offers the concept of [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_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

1. A deployed Lambda function running on AWS. An example using [`CDK`](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html) is available [`here`](https://github.com/alexfernandez803/example-lambda). It gives you an idea how to call [`renderMediaOnLambda()`](/docs/lambda/rendermediaonlambda) inside another Lambda function. The function is triggered by [API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html). The example assumes that you have knowledge of using [`CDK`](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html), a [write up](/docs/lambda/without-iam/example) is also available.
2. An execution role that is assigned to the Lambda function.
3. A user policy with the necessary [user permissions](/docs/lambda/permissions#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:

<details>
  <summary>Show full role permissions JSON file for latest Remotion Lambda version</summary>
  <UserPolicy />
</details>

- 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](https://console.aws.amazon.com/console/home)
  - Navigate to [Lambda (change to your function region)](https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/discover)
  - Select [Functions](https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/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 policies` button.

With the assignment of the `policy` to the Lambda execution role, it is now empowered to execute the [`renderMediaOnLambda()`](/docs/lambda/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](/docs/lambda/custom-destination)

```ts twoslash title="my-function.ts"
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](https://console.aws.amazon.com/console/home) and:
  - Navigate to [Lambda (change to your function region)](https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/discover)
  - [Functions](https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/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](/docs/lambda/custom-destination#write-only-aws-s3-buckets).

```json title="Destination bucket policy"
{
  "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

- [Example setup without IAM user](/docs/lambda/without-iam/example)
- [Authenticating with EC2](/docs/lambda/ec2)

---

### 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.

<br />
<DragAndDropDemo />
<br />

## General considerations

Pointer events work mostly just like in regular React.

Disable the [`controls`](/docs/player/player#controls) prop to disable any obstructing elements. You can render Playback controls [outside of the Player](/docs/player/custom-controls).

The Player might have CSS `scale()` applied to it.  
[If you measure elements](/docs/measuring), you need to divide by the scale obtained by [`useCurrentScale()`](/docs/use-current-scale).

You can pass state update functions via [`inputProps`](/docs/player/player#inputprops) to the Player.  
Alternatively, wrapping the Player in React Context also works.

## Example

```twoslash include item
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. */
```

```twoslash include Layer
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. */
```

```twoslash include SortedOutlines
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}
      />
    );
  });
};
```

```twoslash include Main
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.

### <TitleStep>1</TitleStep> 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` and
`durationInFrames`, the position `left`, `top`, `width` and `height`, a
background `color` as well as a boolean `isDragging` to fine-tune the behavior while dragging.

```tsx twoslash title="item.ts"
// @filename: item.ts
// ---cut---
// @include: item
```

If you like to support different types of items (solid, video, image),
see [here](/docs/building-a-timeline).

### <TitleStep>2</TitleStep> Item rendering

Declare a React component that renders the item.

```tsx twoslash title="Layer.tsx"
// @filename: item.ts
// @include: item
// @filename: Layer.tsx
// ---cut---
// @include: Layer
```

By passing `from` and `durationInFrames` to `Interactive.Div`, the item is only displayed from `from` until `from + durationInFrames`.

`Interactive.Div` renders the draggable `<div>` directly, without an additional layout wrapper.

### <TitleStep>3</TitleStep> Outline rendering

Create a React component that renders an outline when an item isselected or hovered.

```tsx twoslash title="SelectionOutline.tsx"
// @filename: ResizeHandle.tsx
// @include: ResizeHandle
// @filename: item.ts
// @include: item
// @filename: SelectionOutline.tsx
// ---cut---
// @include: SelectionOutline
```

```tsx twoslash title="ResizeHandle.tsx"
// @filename: item.ts
// @include: item
// @filename: ResizeHandle.tsx
// ---cut---
// @include: ResizeHandle
```

**Z-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 [`<Player />`](/docs/player/player) has a CSS `scale` transform applied to it.  
Since we consume the coordinates of the pointer events, we need to divide them by [`useCurrentScale()`](/docs/use-current-scale) 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.

### <TitleStep>4</TitleStep> 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](/docs/layers).

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.

```tsx twoslash title="SortedOutlines.tsx"
// @filename: item.ts
// @include: item
// @filename: ResizeHandle.tsx
// @include: ResizeHandle
// @filename: SelectionOutline.tsx
// @include: SelectionOutline
// @filename: SortedOutlines.tsx
// ---cut---
// @include: SortedOutlines
```

### <TitleStep>5</TitleStep> Putting it together

Next, we create a main component that renders the items and the outlines.

```tsx twoslash title="Main.tsx"
// @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: Main
```

**Z-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.

### <TitleStep>6</TitleStep> Rendering the Player

We can now render the Main component that we created in the Remotion Player.

```tsx twoslash title="Demo.tsx"
// @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: Demo
```

We omit the [`controls`](/docs/player/player#controls) prop to disable the built-in controls.  
You can add [custom controls outside the Player](/docs/player/custom-controls).

We add the [`overflowVisible`](/docs/player/player#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

- [Source code for this demo](https://github.com/remotion-dev/remotion/blob/main/packages/docs/docs/player/drag-and-drop/Demo.tsx)
- [Custom controls](/docs/player/custom-controls)
- [`useCurrentScale()`](/docs/use-current-scale)
- [`<Player />`](/docs/player/player)

---

### 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:

```tsx
bun run dev
```

A Vite app will listen on [`http://localhost:4000`](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

<div
  style={{
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    flexWrap: 'wrap',
  }}
>
  <div>
    To start recording, press <kbd>R</kbd> or click{' '}
  </div>
  <RecordingButton type="start" />
  <div>in the top left corner.</div>
</div>
<br />
<div
  style={{
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    flexWrap: 'wrap',
  }}
>
  <div>Once you are done with the scene, click</div>
  <RecordingButton type="stop" />
  <div>.</div>
</div>

## 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](https://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.

```ts title="copy.ts"
const prefix = '<id-of-your-composition>';
```

Then run the `copy.ts` script whenever you want to save a take and immediately generate captions:

```bash
bun copy.ts
bun sub.ts
```

If 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](/docs/transitions/presentations/custom).

## Table of contents

import { Presentations } from "../../../components/TableOfContents/transitions/presentations";

<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](/docs/transitions/timings/custom).

## Available timings

import { Timings } from "../../../components/TableOfContents/transitions/timings";

<Timings />

## Getting the duration of a timing

You can get the duration of a transition by calling `getDurationInFrames()` on the timing:

```tsx twoslash title="Assuming a framerate of 30fps"
import { springTiming } from "@remotion/transitions";

springTiming({ config: { damping: 200 } }).getDurationInFrames({ fps: 30 }); // 23
```

---

### Packages Docs Elements Audio Mirrored Spectrum Index (`packages/docs/elements/audio/mirrored-spectrum/index.mdx`)

---
title: Mirrored Spectrum
description: Suitable for both music and speech visualization.
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
description: Suitable for visualizing speech.
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
description: A static audio waveform with playback progress.
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
description: A flowing two-color background made from animated liquid contour bands.
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
description: A seamless wave background that flows upward.
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
description: A seamless zigzag background that flows upward.
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
description: A white paper background with subtle blue gridlines.
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
description: A white animated paper texture background.
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
description: A Solid background with a slowly rotating starburst effect.
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
description: Simple synchronized captions with white text on a translucent gray background.
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
description: Synchronized captions with a pill that moves between spoken words.
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
description: Synchronized captions that pop each spoken word into focus.
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
description: Multi-line captions in a SVG text box with roundings in all corners
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](/docs/rounded-text-box/create-rounded-text-box).

<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
description: Synchronized captions that highlight each spoken word.
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
description: Peels any content away with a curled paper edge.
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
description: Three cards which each take center once.
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
description: An attention-grabbing speech bubble.
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
description: Adds a diagonal shine sweep to any content.
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
description: A tear effect that can be applied to any content.
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
description: A bold bar chart card with three directly labeled data points.
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
description: A bold animated line chart with a directly labeled trend.
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
description: A simple animated counter that counts up from a start value to an end value.
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
description: A bold animated pie chart with four directly labeled data points.
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
description: A bold vertical bar chart with three directly labeled data points.
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: ~45730 tokens
- Canonical Reference: https://codewiki.google/github.com/remotion-dev/remotion
