5.7 KiB
5.7 KiB
name, description, metadata
| name | description | metadata | ||
|---|---|---|---|---|
| rendering | Rendering videos with Remotion - CLI, Node.js API, Lambda, and Cloud Run |
|
Rendering Videos
CLI Rendering
Render a composition to a video file:
npx remotion render src/index.ts MyComposition out/video.mp4
Common flags
# Set output format
npx remotion render src/index.ts MyComp out.mp4 --codec h264
npx remotion render src/index.ts MyComp out.webm --codec vp8
npx remotion render src/index.ts MyComp out.gif --codec gif
# Set resolution and frame range
npx remotion render src/index.ts MyComp out.mp4 --width 1080 --height 1920
npx remotion render src/index.ts MyComp out.mp4 --frames 0-100
# Increase quality / CRF (lower = better, default 18)
npx remotion render src/index.ts MyComp out.mp4 --crf 15
# Concurrency (parallel frames)
npx remotion render src/index.ts MyComp out.mp4 --concurrency 4
# Pass input props as JSON
npx remotion render src/index.ts MyComp out.mp4 --props '{"title": "Hello"}'
# Or from a file
npx remotion render src/index.ts MyComp out.mp4 --props ./props.json
Render a still image
npx remotion still src/index.ts MyStill out.png
npx remotion still src/index.ts MyStill out.png --frame 30
Available codecs
| Codec | Extension | Use case |
|---|---|---|
h264 |
.mp4 | Default, best compatibility |
h265 |
.mp4 | Smaller files, less compatibility |
vp8 |
.webm | Web, transparent video |
vp9 |
.webm | Better quality WebM |
prores |
.mov | Professional editing (Apple ProRes) |
gif |
.gif | Short loops, social media |
Node.js API Rendering
For server-side rendering, use the @remotion/renderer package:
import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";
import path from "path";
const render = async () => {
// Bundle the project
const bundled = await bundle({
entryPoint: path.resolve("./src/index.ts"),
});
// Select the composition
const composition = await selectComposition({
serveUrl: bundled,
id: "MyComposition",
inputProps: {
title: "Hello World",
},
});
// Render
await renderMedia({
composition,
serveUrl: bundled,
codec: "h264",
outputLocation: "out/video.mp4",
inputProps: {
title: "Hello World",
},
onProgress: ({ progress }) => {
console.log(`Rendering: ${(progress * 100).toFixed(1)}%`);
},
});
};
render();
Render a still frame
import { renderStill } from "@remotion/renderer";
await renderStill({
composition,
serveUrl: bundled,
output: "out/thumbnail.png",
frame: 0,
inputProps: { title: "Thumbnail" },
});
Render to a buffer (no file)
import { renderMedia } from "@remotion/renderer";
const result = await renderMedia({
composition,
serveUrl: bundled,
codec: "h264",
outputLocation: null, // No file output
});
// result.buffer contains the video as a Buffer
AWS Lambda Rendering
For serverless rendering at scale. Install the Lambda package:
npx remotion lambda policies role
npx remotion lambda sites create src/index.ts --site-name=my-site
npx remotion lambda functions deploy
Render from code:
import { renderMediaOnLambda } from "@remotion/lambda/client";
const result = await renderMediaOnLambda({
region: "us-east-1",
functionName: "remotion-render-...",
serveUrl: "https://...", // from sites create
composition: "MyComposition",
codec: "h264",
inputProps: {
title: "Dynamic Video",
},
});
// result.outputFile - S3 URL of rendered video
Lambda considerations
- Max 15 min per render (AWS limit)
- Splits video into chunks, renders in parallel, stitches
- Cost-effective for burst workloads
- Use
@remotion/lambdafor the full API
Google Cloud Run Rendering
Alternative to Lambda using Cloud Run:
npx remotion cloudrun services deploy
npx remotion cloudrun sites create src/index.ts
import { renderMediaOnCloudrun } from "@remotion/cloudrun/client";
const result = await renderMediaOnCloudrun({
serviceName: "remotion-render",
region: "us-east-1",
serveUrl: "https://storage.googleapis.com/...",
composition: "MyComposition",
codec: "h264",
inputProps: { title: "Hello" },
});
Express/HTTP Server Pattern
Expose rendering as an API endpoint:
import express from "express";
import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";
import path from "path";
const app = express();
app.use(express.json());
// Bundle once at startup
let bundled: string;
bundle({ entryPoint: path.resolve("./src/index.ts") }).then((b) => {
bundled = b;
console.log("Bundled and ready");
});
app.post("/render", async (req, res) => {
const { compositionId, props } = req.body;
const composition = await selectComposition({
serveUrl: bundled,
id: compositionId,
inputProps: props,
});
const result = await renderMedia({
composition,
serveUrl: bundled,
codec: "h264",
outputLocation: null,
inputProps: props,
});
res.set("Content-Type", "video/mp4");
res.send(result.buffer);
});
app.listen(3000);
Performance Tips
- Concurrency: Use
--concurrencyto render frames in parallel (default: 50% of CPU cores) - Bundle once: In server scenarios, call
bundle()once and reuse the URL - Use
calculateMetadata: Pre-compute heavy data before rendering starts - Avoid network calls in components: Fetch data via
inputPropsorcalculateMetadatainstead - Image optimization: Pre-resize images to the exact dimensions needed
- Memory: For long videos, consider splitting into segments and concatenating