Setup
How to enable client-side video rendering with the RVE SDK
Client-Side Rendering Setup
Client-side rendering is enabled by default in the RVE SDK. This guide covers the setup details and configuration options.
Install Dependencies
Client-side rendering requires two additional packages as peer dependencies:
npm install @remotion/web-renderer @remotion/mediaThese are peer dependencies of @reactvideoeditor/react-video-editor - they're not bundled with the SDK, so you need to install them in your project.
Default Behavior
Client-side rendering is enabled automatically when no customRenderer is provided. The simplest setup is:
Browser-Only Export (Default)
"use client";
import React from 'react';
import { ReactVideoEditor } from '@reactvideoeditor/react-video-editor/react-video-editor';
import '@reactvideoeditor/react-video-editor/styles.css';
export default function Page() {
return (
<ReactVideoEditor
projectId="example-project"
fps={30}
enableWebRender={true}
/>
);
}That's it - no HttpRenderer, no API routes, no server setup. Users click "Export Video" and the MP4 downloads directly to their device.
This is the default
You don't even need enableWebRender={true} — it's enabled automatically when no customRenderer is provided.
Browser and Server Renderer Together
You can give the editor a customRenderer and also allow browser export. The props set the render mode. The editor has no control that changes the mode, and it does not change to browser mode when a server render fails.
- If the renderer is enabled (the
HttpRendererdefault), the editor uses cloud mode. - If you set
enableWebRender={true}and create the renderer with{ enabled: false }, the editor uses browser mode.
"use client";
import React from 'react';
import { ReactVideoEditor } from '@reactvideoeditor/react-video-editor/react-video-editor';
import { HttpRenderer } from '@reactvideoeditor/react-video-editor/utils/http-renderer';
import '@reactvideoeditor/react-video-editor/styles.css';
export default function Page() {
const ssrRenderer = React.useMemo(
() =>
new HttpRenderer(
'/api/latest/ssr',
{ type: 'ssr', entryPoint: '/api/latest/ssr' },
{ enabled: false }, // start in browser mode
),
[],
);
return (
<ReactVideoEditor
projectId="example-project"
fps={30}
customRenderer={ssrRenderer}
enableWebRender={true}
/>
);
}Configuration Props
This table shows the props that control export. For all props, see ReactVideoEditor.
| Prop | Type | Default | Description |
|---|---|---|---|
enableWebRender | boolean | true if there is no customRenderer, else false | Allows browser export |
customRenderer | VideoRenderer | - | A server renderer (SSR, Lambda, or custom) |
exportOptions | ExportOptions | { availableResolutions: ['720p', '1080p', '4k'], defaultResolution: '1080p', quality: 'high' } | Resolution presets, the default resolution, and the browser export quality |
disableExportModal | boolean | false | Skips the export dialog. The export starts at the composition size |
defaultExportScale | number | - | A size multiplier for the export when disableExportModal is set. Example: 2 for twice the canvas size |
watermark | WatermarkConfig | false | true shows the RVE badge. An object { src, position?, opacity?, scale?, padding? } shows your image. See Watermark |
exportProgressIntervalMs | number | 1000 | Time between progress heartbeats (ms). 0 or less stops heartbeats |
webRenderStallTimeoutMs | number | 300000 | Maximum visible-tab time without browser render progress (ms) |
webRenderFinalizationTimeoutMs | number | 1800000 | Maximum visible-tab time for each browser finalization phase (ms) |
onExportStart, onExportProgress, onExportComplete, onExportFail, onExportCancel | function | - | Export lifecycle callbacks. See Export Lifecycle |
Export Resolution Presets
When the user clicks "Export", a dialog lets the user select a resolution. Use exportOptions to set the available presets:
<ReactVideoEditor
projectId="example-project"
fps={30}
exportOptions={{
availableResolutions: ['720p', '1080p'],
defaultResolution: '720p',
}}
/>The dialog calculates the pixel size from the current aspect ratio. 1080p always sets the short edge, for example 1920×1080 for 16:9 and 608×1080 for 9:16.
| Resolution | Short Edge |
|---|---|
720p | 720px |
1080p | 1080px |
4k | 2160px |
If the canvas has a custom size that no preset gives, the dialog also shows Original.
Performance tip
Higher resolutions take more time to render in the browser. For browser export, use 720p or 1080p as the default.
Export Quality and File Size
exportOptions also sets the bitrate of browser exports. Server and cloud renders ignore these options, because the server renderer selects its own bitrate.
| Option | Type | Description |
|---|---|---|
quality | 'very-low' | 'low' | 'medium' | 'high' | 'very-high' | A quality preset. The default is 'high' |
videoBitrate | number | The video bitrate in bits per second. It overrides quality for video |
audioBitrate | number | The audio bitrate in bits per second. It overrides quality for audio |
| Quality | 720p | 1080p | 4K | Audio |
|---|---|---|---|---|
very-low | ~0.4 Mbps | 0.9 Mbps | ~3.4 Mbps | 96 kbps |
low | ~0.8 Mbps | 1.8 Mbps | ~6.7 Mbps | 96 kbps |
medium | ~1.4 Mbps | 3 Mbps | ~11 Mbps | 128 kbps |
high (default) | ~2.8 Mbps | 6 Mbps | ~22 Mbps | 192 kbps |
very-high | ~5.6 Mbps | 12 Mbps | ~45 Mbps | 192 kbps |
<ReactVideoEditor
projectId="example-project"
fps={30}
exportOptions={{ quality: 'medium' }}
/>- Before this option, browser exports always used
'very-high'(12 Mbps at 1080p). To keep the old file size, setquality: 'very-high'. - The export dialog shows the estimated file size for the selected resolution.
onExportStartreceivesestimatedSizeInBytesfor browser exports.onExportCompletereceives the realsizeInBytes.- The encoder uses a variable bitrate. Simple content, such as slides, usually gives a smaller file than the estimate.
- If
qualityhas an unknown value, or a bitrate is not a positive number, the export fails beforeonExportStart.
To calculate a size in your own interface, import the helpers from /types:
import {
estimateExportSize,
getEncodedExportDimensions,
} from '@reactvideoeditor/react-video-editor/types';
const { width, height } = getEncodedExportDimensions({ width: 1280, height: 720 }, '1080p');
const bytes = estimateExportSize({ width, height, durationInSeconds: 60, quality: 'high' });The /types entry also exports resolveExportBitrates(width, height, options), DEFAULT_EXPORT_QUALITY, and the types ExportOptions, ExportResolution, ExportQuality, ExportBitrateOptions, ExportBitrates, and EstimateExportSizeParams.
Behavior Matrix
customRenderer | enableWebRender | Result |
|---|---|---|
| Not provided | Not set | Browser export (default) |
| Not provided | true | Browser export |
| Not provided | false | Export button disabled |
| Enabled | Not set or false | Cloud rendering only |
| Enabled | true | Cloud rendering. The editor does not use browser export |
{ enabled: false } | true | Browser export |
{ enabled: false } | Not set or false | Export button disabled |
No HttpRenderer needed
Unlike SSR and Lambda rendering, client-side rendering doesn't use the HttpRenderer or require you to implement any API endpoints. The entire export pipeline runs in the browser using @remotion/web-renderer.
UI Differences in Web Render Mode
When exporting via the browser, the UI adapts automatically:
- The export button label changes from "Render Video" to "Export Video"
- Completed exports trigger an automatic download (instead of a notification bell)
Troubleshooting
"Your browser doesn't support video export"
This means the browser lacks WebCodecs support (VideoEncoder / AudioEncoder APIs). The user needs Chrome 94+ or Edge 94+.
Export is slow
Browser rendering speed depends on the user's hardware. Tips:
- Shorter videos render faster
- Lower resolutions (720p vs 1080p) are significantly faster
- Hardware acceleration is enabled by default (
prefer-hardware) but falls back to software encoding if unavailable
Memory issues on long videos
The browser creates a blob in memory for the entire video. For very long videos (10+ minutes), users may run into memory limits. For heavy workloads, consider directing users to server rendering instead.