RVE LogoReact Video EditorDOCS
RVE SDK/Rendering/Rendering/Custom Rendering (SSR)/Getting Setup

Getting Setup

Setup guide for optional Server-Side Rendering in React Video Editor

This guide shows how to add server-side rendering (SSR) as an optional, self-managed backend for the RVE SDK. Use SSR when your team needs full server control. Use RVE Cloud Rendering when you want a managed production service.

The example app apps/with-nextjs-basic contains these routes:

RouteFilePurpose
POST /api/latest/ssr/renderapp/api/latest/ssr/render/route.tsStarts a render
POST /api/latest/ssr/progressapp/api/latest/ssr/progress/route.tsReturns the render progress
GET /api/latest/ssr/download/[id]app/api/latest/ssr/download/[id]/route.tsSends the finished MP4 file

1. Connect the editor

The HttpRenderer adds /render and /progress to the endpoint that you give it.

app/page.tsx
"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' },
        { name: 'Server' },
      ),
    [],
  );

  return (
    <ReactVideoEditor
      projectId="example-project"
      fps={30}
      customRenderer={ssrRenderer}
    />
  );
}
ArgumentDescription
endpointThe base path of your routes
renderType{ type: 'ssr' | 'lambda', entryPoint: string }. The type goes to the export callbacks as renderType
options.enabledDefault true. If true, the editor uses cloud mode. Use false with enableWebRender={true} for browser mode
options.nameDefault 'Cloud'. The renderer name in the export dialog

2. Add the render route

Request (POST {endpoint}/render):

{
  id: string; // the editor projectId, used as the composition id
  inputProps: {
    tracks: Track[];
    durationInFrames: number;
    width: number;
    height: number;
    fps: number;
    src: '';
    scale?: number;               // only present when the scale is not 1
    background?: CanvasBackground;
    backgroundColor?: string;     // deprecated
  };
}

Response:

{ renderId: string; bucketName?: string }

Validate tracks, not overlays

The SDK sends inputProps.tracks. If your route validates an overlays field, every render request fails validation. Validate tracks as the request above shows.

The route must return quickly. Start the render in the background and keep its state in a store that the progress route can read. The example app writes the state to JSON files in tmp/render-state. It saves each MP4 file in public/rendered-videos.

Add fontInfos to the inputProps before the render starts. If you do not, text uses the fallback font. See Fonts.


3. Add the progress route

Request (POST {endpoint}/progress):

{ id: string; bucketName?: string } // id is the renderId

Response: one of these shapes.

| { type: 'progress'; progress: number }     // from 0 to 1
| { type: 'done'; url: string; size: number } // size in bytes
| { type: 'error'; message: string }

The SDK sends this request again after each poll interval (default 1000 ms) until it gets done or error. If the route returns an HTTP error status, the render fails.

The HttpRenderer also accepts the shape { type: 'success', data } for both routes. It reads data from that shape.


4. Write the composition

Your server renders a composition that you bundle. It must:

  • Use the request id as its composition id, or your route must pass a fixed id.
  • Read the size, the duration, the frame rate, and the scale from inputProps.
  • Draw each item inside LayerBox.

Write a custom composition

If your route sets the size of the render, use width × scale and height × scale. Round each value to an even number.


Use another framework

If you use Vite or another framework, create the same routes in your server, for example with Express or Fastify. The client only needs these things:

  1. A POST {endpoint}/render route that returns { renderId }.
  2. A POST {endpoint}/progress route that returns the progress shapes above.
  3. A URL for the finished file that the browser can download.

Need help? Open an issue or send an email to hello@reactvideoeditor.com.