Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/remotion-dev/template-prompt-to-motion-graphics-saas/llms.txt

Use this file to discover all available pages before exploring further.

Once your Lambda infrastructure is deployed, you can render videos by making API requests to the Lambda endpoints.

Render Endpoint

The render endpoint initiates a new video render job on AWS Lambda.

Endpoint

POST /api/lambda/render

Implementation

The render endpoint is implemented in src/app/api/lambda/render/route.ts:
import {
  renderMediaOnLambda,
  speculateFunctionName,
} from "@remotion/lambda/client";

export const POST = executeApi<RenderMediaOnLambdaOutput, typeof RenderRequest>(
  RenderRequest,
  async (req, body) => {
    const result = await renderMediaOnLambda({
      codec: "h264",
      functionName: speculateFunctionName({
        diskSizeInMb: DISK,
        memorySizeInMb: RAM,
        timeoutInSeconds: TIMEOUT,
      }),
      region: REGION,
      serveUrl: SITE_NAME,
      composition: COMP_NAME,
      inputProps: body.inputProps,
      framesPerLambda: 60,
      downloadBehavior: {
        type: "download",
        fileName: "video.mp4",
      },
    });

    return result;
  },
);

Request Body

The request expects a JSON body with your composition’s input properties:
{
  "inputProps": {
    // Your composition-specific props here
  }
}

Response

The endpoint returns a RenderMediaOnLambdaOutput object containing:
  • renderId: Unique identifier for this render job
  • bucketName: S3 bucket where the video will be stored
  • Additional metadata about the render job

Render Configuration

The render uses these settings:
  • Codec: H.264 (MP4 format)
  • Frames per Lambda: 60 frames per function invocation for parallel rendering
  • Download Behavior: Videos are named video.mp4 when downloaded
  • Function Name: Automatically determined based on your Lambda configuration (RAM, disk, timeout)

Progress Endpoint

Monitor the status of your render job using the progress endpoint.

Endpoint

POST /api/lambda/progress

Implementation

The progress endpoint tracks render job status in src/app/api/lambda/progress/route.ts:
import {
  getRenderProgress,
  speculateFunctionName,
} from "@remotion/lambda/client";

export const POST = executeApi<ProgressResponse, typeof ProgressRequest>(
  ProgressRequest,
  async (req, body) => {
    const renderProgress = await getRenderProgress({
      bucketName: body.bucketName,
      functionName: speculateFunctionName({
        diskSizeInMb: DISK,
        memorySizeInMb: RAM,
        timeoutInSeconds: TIMEOUT,
      }),
      region: REGION,
      renderId: body.id,
    });

    if (renderProgress.fatalErrorEncountered) {
      return {
        type: "error",
        message: renderProgress.errors[0].message,
      };
    }

    if (renderProgress.done) {
      return {
        type: "done",
        url: renderProgress.outputFile,
        size: renderProgress.outputSizeInBytes,
      };
    }

    return {
      type: "progress",
      progress: Math.max(0.03, renderProgress.overallProgress),
    };
  },
);

Request Body

{
  "bucketName": "remotionlambda-useast1-xxxxxx",
  "id": "render-id-from-render-response"
}

Response Types

The progress endpoint returns one of three response types:

In Progress

{
  "type": "progress",
  "progress": 0.45
}
  • progress: A number between 0 and 1 (minimum 0.03 to show initial progress)

Complete

{
  "type": "done",
  "url": "https://s3.amazonaws.com/.../video.mp4",
  "size": 1234567
}
  • url: Direct URL to the rendered video file
  • size: File size in bytes

Error

{
  "type": "error",
  "message": "Error description"
}
  • message: Description of what went wrong during rendering

Complete Workflow

Here’s a complete example of rendering a video and checking its progress:
1

Initiate Render

Send a POST request to start rendering:
const renderResponse = await fetch('/api/lambda/render', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    inputProps: {
      // Your composition props
    }
  })
});

const { renderId, bucketName } = await renderResponse.json();
2

Poll for Progress

Periodically check the render status:
const checkProgress = async () => {
  const progressResponse = await fetch('/api/lambda/progress', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      id: renderId,
      bucketName: bucketName
    })
  });
  
  const result = await progressResponse.json();
  
  if (result.type === 'done') {
    console.log('Video ready:', result.url);
    console.log('Size:', result.size, 'bytes');
  } else if (result.type === 'error') {
    console.error('Render failed:', result.message);
  } else {
    console.log('Progress:', Math.round(result.progress * 100) + '%');
    setTimeout(checkProgress, 1000); // Check again in 1 second
  }
};

checkProgress();
3

Download Video

Once complete, use the returned URL to download or display the video:
// Direct link for download
window.location.href = result.url;

// Or embed in video player
videoElement.src = result.url;

Error Handling

Missing Credentials

If AWS credentials are not configured, you’ll receive:
{
  "error": "Set up Remotion Lambda to render videos. See the README.md for how to do so."
}
Ensure your environment variables are set:
  • REMOTION_AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY_ID
  • REMOTION_AWS_SECRET_ACCESS_KEY or AWS_SECRET_ACCESS_KEY

Render Failures

Common render failures include:
  • Timeout: Render exceeded 240 seconds (increase TIMEOUT in config.mjs)
  • Out of Memory: Increase RAM in config.mjs
  • Invalid Props: Check that your inputProps match the composition’s expected schema

Performance Optimization

Parallel Rendering

The framesPerLambda: 60 setting determines how work is distributed:
  • Lower values (e.g., 30): More parallel Lambda invocations, faster for complex scenes
  • Higher values (e.g., 120): Fewer invocations, lower cost but slower

Region Selection

Choose a region close to your users for faster uploads and downloads. Configure in config.mjs:
export const REGION = "us-east-1"; // Change to your preferred region

Cost Considerations

Lambda rendering costs depend on:
  • Number of frames in your video
  • framesPerLambda setting (determines number of invocations)
  • Lambda function configuration (RAM/disk/timeout)
  • Region selected
See the Configuration guide for optimizing resource allocation.