# How to Render a Video Locally with Remotion CLI: A Complete Guide

> Learn to render video locally with Remotion CLI. This guide shows how to bundle your React app, use headless Chromium, and encode frames into a video file with FFmpeg.

- Repository: [Remotion/remotion](https://github.com/remotion-dev/remotion)
- Tags: how-to-guide
- Published: 2026-02-19

---

**Use `npx remotion render [entry] [composition] [output]` to bundle your React project, launch headless Chromium, and encode frames into a video file using FFmpeg.**

The Remotion CLI provides a deterministic, scriptable interface for transforming React components into video files entirely on your local machine. As implemented in the `remotion-dev/remotion` repository, the CLI orchestrates bundling, browser management, and FFmpeg encoding through a series of specialized internal modules.

## Understanding the Remotion CLI Rendering Pipeline

When you execute `npx remotion render`, the CLI initiates a seven-stage pipeline defined primarily in [`packages/cli/src/render-flows/render.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/render-flows/render.ts). This module coordinates between the bundler, headless browser, and rendering engine.

### Entry Point and Configuration Parsing

The process begins in [`packages/cli/src/index.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/index.ts), where the `cli()` function parses `process.argv` using `minimist` to identify the `render` sub-command. Immediately after, `getCliOptions()` (located in [`packages/cli/src/get-cli-options.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/get-cli-options.ts)) merges your `.remotionrc` or [`remotion.config.js`](https://github.com/remotion-dev/remotion/blob/main/remotion.config.js) with default values, validating parameters like concurrency and codec settings.

### Bundling and Composition Resolution

Before rendering can begin, the project must be bundled. The `bundleOnCliOrTakeServeUrl()` function handles this step, compiling your React code via Webpack. Simultaneously, `getCompositionWithDimensionOverride()` (from [`packages/cli/src/get-composition-with-dimension-override.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/get-composition-with-dimension-override.ts)) loads the bundled project in a headless browser to extract available compositions. If you haven't specified a composition ID via CLI arguments, the system displays an interactive picker using `inquirer`.

### Browser Launch and Frame Rendering

With the bundle ready, `RenderInternals.internalEnsureBrowser()` downloads Chromium if necessary, while `RenderInternals.internalOpenBrowser()` launches the browser instance with your specified flags (such as `--chrome-mode="chrome-for-testing"`). The actual rendering occurs through two possible paths:

- **Image Sequence Mode**: `RenderInternals.internalRenderFrames()` writes individual frames to disk as JPEG or PNG files.
- **Video Mode**: `RenderInternals.internalRenderMedia()` streams rendered frames directly into FFmpeg for encoding and stitching.

Both paths utilize shared progress reporting mechanisms defined in [`packages/cli/src/progress-bar.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/progress-bar.ts).

## Basic CLI Commands for Local Rendering

The simplest invocation relies on automatic discovery of your entry point and composition:

```bash
npx remotion render

```

This command searches for standard entry files ([`src/index.tsx`](https://github.com/remotion-dev/remotion/blob/main/src/index.tsx), [`src/index.js`](https://github.com/remotion-dev/remotion/blob/main/src/index.js), etc.) and prompts you to select a composition if multiple exist. Output defaults to `out/<CompositionId>.mp4`.

To render a specific composition to a custom location:

```bash
npx remotion render src/index.tsx MyComposition ./out/video.mp4

```

Here, [`src/index.tsx`](https://github.com/remotion-dev/remotion/blob/main/src/index.tsx) is the explicit entry point, `MyComposition` matches the `id` prop of your `<Composition>` component, and `./out/video.mp4` specifies the output destination.

## Advanced Rendering Options

The CLI exposes dozens of flags to control encoding, performance, and output characteristics. These are processed in [`packages/cli/src/get-cli-options.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/get-cli-options.ts) and passed through to the renderer.

### Input Properties and Dynamic Data

Pass dynamic data to your composition using the `--props` flag:

```bash

# Inline JSON

npx remotion render HelloWorld --props='{"title":"Hello world"}'

# External file

npx remotion render HelloWorld --props=./props.json

```

Inside your component, access these values using `getInputProps()`.

### Performance and Quality Controls

Manage system resources and output fidelity:

```bash

# Use 4 CPU threads (or 50% of available cores)

npx remotion render HelloWorld --concurrency=4

# Scale frames for higher resolution (1.5×)

npx remotion render HelloWorld --scale=1.5

# Set Constant Rate Factor for quality (requires compatible codec)

npx remotion render HelloWorld --codec=h264 --crf=18

```

### Codec and Format Selection

Control the output encoding:

| Flag | Example | Effect |
|------|---------|--------|
| `--codec` | `--codec=prores` | Select encoding format (h264, h265, vp8, vp9, prores, gif, etc.). |
| `--prores-profile` | `--prores-profile=4444` | Specify ProRes quality level (4444, 422, etc.). |
| `--hardware-acceleration` | `--hardware-acceleration=if-possible` | Enable GPU-accelerated encoding when available. |
| `--pixel-format` | `--pixel-format=yuv420p` | Set chroma subsampling for compatibility. |

### Complete Advanced Example

Combine multiple flags for a high-quality production render:

```bash
npx remotion render src/index.tsx MyComp \
  ./out/final.mov \
  --codec=prores \
  --prores-profile=4444 \
  --scale=2 \
  --concurrency=50% \
  --props=./my-props.json \
  --hardware-acceleration=if-possible \
  --log=verbose

```

This command bundles the project, renders at 2× scale using half the available CPU cores, encodes to ProRes 4444 with hardware acceleration if possible, and injects properties from [`my-props.json`](https://github.com/remotion-dev/remotion/blob/main/my-props.json).

## Rendering Image Sequences vs. Video

By default, the CLI renders a single video file. To output individual frames instead, use the `--sequence` flag:

```bash
npx remotion render HelloWorld --sequence --image-format=png

```

This invokes `RenderInternals.internalRenderFrames()` instead of `RenderInternals.internalRenderMedia()`, saving frames to `out/HelloWorld/0001.png`, `0002.png`, etc. The `--image-format` flag accepts `jpeg` (default) or `png`.

## Troubleshooting Common Local Rendering Issues

| Issue | Root Cause | Solution |
|-------|------------|----------|
| **Chrome cannot decode the video** | Default Chromium lacks proprietary codecs. | Use `--chrome-mode="chrome-for-testing"` which includes full codec support; alternatively install system codecs. |
| **Missing props file** | `--props` points to a non-existent path. | Verify the file path and ensure valid JSON syntax. |
| **Out-of-memory during large renders** | Simultaneous rendering and encoding exhausts RAM. | Add `--disallow-parallel-encoding` to separate the rendering and encoding phases. |
| **Unexpected output dimensions** | Scale or dimension overrides conflict with composition settings. | Ensure `--scale` ≤ 16 and that `--height`/`--width` are multiples of 2 for codec compatibility. |
| **File already exists error** | Default behavior allows overwrite, but some configurations set `--overwrite=false`. | Explicitly add `--overwrite` to allow replacement of existing files. |

## Summary

The Remotion CLI transforms React components into video files through a well-defined local pipeline:

- **Entry resolution** – automatically discovers [`src/index.tsx`](https://github.com/remotion-dev/remotion/blob/main/src/index.tsx) or uses specified paths via [`packages/cli/src/get-cli-options.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/get-cli-options.ts).
- **Bundling** – compiles the project with Webpack using `bundleOnCliOrTakeServeUrl()` in [`packages/cli/src/render-flows/render.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/render-flows/render.ts).
- **Browser orchestration** – downloads and launches Chromium via `RenderInternals.internalEnsureBrowser()` and `RenderInternals.internalOpenBrowser()`.
- **Frame generation** – renders individual frames with `RenderInternals.internalRenderFrames()` or streams to FFmpeg via `RenderInternals.internalRenderMedia()`.
- **Output control** – supports multiple codecs, scaling, concurrency limits, and hardware acceleration through flags processed in [`packages/cli/src/get-cli-options.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/get-cli-options.ts).

## Frequently Asked Questions

### What is the minimum command to render a video with Remotion CLI?

The absolute minimum is `npx remotion render`. This command automatically searches for entry points like [`src/index.tsx`](https://github.com/remotion-dev/remotion/blob/main/src/index.tsx) or [`src/index.js`](https://github.com/remotion-dev/remotion/blob/main/src/index.js), prompts you to select a composition if multiple exist, and outputs to `out/<CompositionId>.mp4`. For automated workflows, specify the entry point, composition ID, and output path explicitly: `npx remotion render src/index.tsx MyComp out/video.mp4`.

### How do I pass dynamic data to my Remotion composition when rendering locally?

Use the `--props` flag to inject JSON data into your composition. You can pass inline JSON: `npx remotion render MyComp --props='{"title":"Hello"}'`, or reference a file: `npx remotion render MyComp --props=./data.json`. Inside your React component, import `getInputProps` from `remotion` to access these values: `const {title} = getInputProps()`.

### Why does my rendered video have no audio or fail to play in certain players?

The default Chromium binary used by Remotion lacks proprietary codecs like H.264. According to the source code in [`packages/cli/src/browser.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/browser.ts), you should use `--chrome-mode="chrome-for-testing"` when rendering. This flag ensures the CLI downloads and uses a Chrome-for-Testing binary that includes full codec support, resolving playback issues in standard video players.

### How can I render an image sequence instead of a video file?

Add the `--sequence` flag to output individual frames rather than a stitched video. For example: `npx remotion render HelloWorld --sequence --image-format=png`. This invokes `RenderInternals.internalRenderFrames()` instead of the media renderer, saving frames to `out/<CompositionId>/0001.png`, `0002.png`, etc. You can then import these frames into external compositing software like After Effects or DaVinci Resolve.