Remotionワーカープールのサイジング設計
執筆: RenderComp チーム 編集方針
Remotionがフレームを計算する単位は、映像ファイルではなくJSXコンポーネントの返り値です。同じinputPropsと同じフレーム番号を渡せば、どの実行環境でも同一のビットマップが生成されます。この決定論的な性質が、フレームを分割して複数のLambdaワーカーに並行して投げる根拠になっています。
問題が複雑になるのは、複数のジョブが同時にキューに積まれる運用フェーズです。ワーカーの同時起動数がAWS Lambdaの同時実行上限を超えると、後続ジョブが503エラーで失敗します。framesPerLambdaの値とアカウントの同時実行数設定の関係を把握することが、安定したキュー運用の前提になります。
framesPerLambda が決めるもの
renderMediaOnLambdaに渡すframesPerLambdaは、1台のLambdaワーカーが担当するフレーム数を指定します。合計フレーム数をこの値で割った数が、そのジョブで起動するワーカーの台数です。
Remotion 4.0.331以降、framesPerLambdaの下限は5です。それ以前のバージョンでは下限は4でした。指定値が下限を下回ってもサイレントにクランプされるため、フレーム数が少ない短尺動画でも最低5フレームが1台のワーカーに割り当てられます。
import { renderMediaOnLambda } from "@remotion/lambda/client";
const { renderId, bucketName } = await renderMediaOnLambda({
region: "ap-northeast-1",
functionName: "remotion-render-4-0-mem2048mb-disk2048mb-120sec",
serveUrl: SERVE_URL,
composition: "MyVideo",
inputProps: { title: "Hello World" },
codec: "h264",
// 300フレームの場合、起動するワーカーは300÷20=15台
framesPerLambda: 20,
});
framesPerLambdaを小さくするとワーカー数が増えて並列度が上がります。各ワーカーの起動にはコールドスタートのオーバーヘッドがあるため、値を下げれば全体の書き出し時間が短くなるわけではありません。ワーカー数を増やすほどLambdaの同時実行枠を消費するという点も同様に重要です。
ワーカー数の計算と同時ジョブ数の見積もり
AWS Lambdaの実行環境1インスタンスは、秒間最大10リクエストを処理できます。アカウント全体の呼び出し上限は「同時実行数の設定値×10」です。同時実行数を1,000に設定した環境では、秒間10,000リクエストまで呼び出せます。
複数のジョブが同時にLambdaを呼び出す場合、各ジョブのワーカー数の合計がこの上限に収まるかどうかを事前に計算します。
// Remotion 4.0.331以降の下限
const FRAMES_PER_LAMBDA_MIN = 5;
function estimateWorkerCount(
totalFrames: number,
framesPerLambda: number
): number {
const clamped = Math.max(framesPerLambda, FRAMES_PER_LAMBDA_MIN);
return Math.ceil(totalFrames / clamped);
}
// オーケストレーターLambdaの1台分を加算して上限を計算
function maxConcurrentJobs(
concurrencyLimit: number,
totalFrames: number,
framesPerLambda: number
): number {
const workersPerJob = estimateWorkerCount(totalFrames, framesPerLambda);
return Math.floor(concurrencyLimit / (workersPerJob + 1));
}
たとえば30fps・150秒の動画(4,500フレーム)をframesPerLambda: 30で書き出すと、1ジョブあたりのワーカーは150台です。同時実行数1,000の環境ではmaxConcurrentJobs(1000, 4500, 30)は6を返します。7本目以降のジョブは、いずれかが完了して枠が空くまで待機させる必要があります。
キューとスロットル
並列ジョブ数をプログラムで制御するには、Amazon SQSとLambdaを組み合わせる構成が実用的です。EventSourceのmaxConcurrencyを設定すると、アカウント全体の同時実行数とは別にキュー消費側の並行数を絞れます。
import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
// レンダーワーカーがキューを消費する際の同時実行数上限
renderFunction.addEventSource(
new SqsEventSource(renderQueue, {
batchSize: 1, // 1呼び出し=1ジョブ
maxConcurrency: 50, // このキューの消費は最大50並列まで
})
);
batchSize: 1にすると、1回のLambda呼び出しで1ジョブだけ処理します。レンダーは長時間実行になりやすく、バッチサイズを大きくするとタイムアウトのリスクが高まります。
ジョブをキューに投入する側は、レンダー完了を待たずにすぐ返ります。renderIdをデータベースに記録しておき、後のポーリングで完了を確認します。
import { SendMessageCommand, SQSClient } from "@aws-sdk/client-sqs";
const sqs = new SQSClient({ region: "ap-northeast-1" });
async function enqueueRenderJob(
renderId: string,
renderParams: Record<string, unknown>
): Promise<void> {
await sqs.send(
new SendMessageCommand({
QueueUrl: RENDER_QUEUE_URL,
MessageBody: JSON.stringify({ renderId, ...renderParams }),
})
);
}
進捗ポーリング
renderMediaOnLambdaはレンダーの完了を待たずに返ります。getRenderProgressを定期的に呼び出して完了を検知します。
import { getRenderProgress } from "@remotion/lambda/client";
async function pollUntilDone(
renderId: string,
bucketName: string,
region: string,
functionName: string
): Promise<string> {
while (true) {
const progress = await getRenderProgress({
renderId,
bucketName,
functionName,
region,
});
if (progress.done) {
return progress.outputFile!;
}
if (progress.fatalErrorEncountered) {
throw new Error("Render failed");
}
// overallProgress は 0〜1 の小数
console.log(`進捗: ${Math.round(progress.overallProgress * 100)}%`);
await new Promise<void>((resolve) => setTimeout(resolve, 3_000));
}
}
ポーリング間隔3秒は実用的な基準です。並列ジョブが多い場合、getRenderProgressの呼び出し自体もLambda実行数に加算されます。ジョブ数が数十を超える環境では、間隔を長めに設定するか、SNSトピックへのWebhookに切り替えることを検討します。
framesPerLambda の選択指針
framesPerLambdaの値は、1本あたりの書き出し速度と同時処理可能なジョブ数のトレードオフを決めます。短尺・大量同時投入の用途ではワーカー数を絞って同時実行枠を複数ジョブで共有し、長尺・少量の用途では1本あたりの並列度を上げます。
// 用途別の framesPerLambda 設定例
const presets = {
// 30fps × 15秒 = 450フレーム → ワーカー9台
shortClip: { framesPerLambda: 50 },
// 30fps × 120秒 = 3600フレーム → ワーカー240台
longForm: { framesPerLambda: 15 },
} as const;
下限の5を下回る値を渡してもクランプされるため、設定ミスで想定外のワーカー数が起動することはありません。実際の起動台数はgetRenderProgressの返り値で確認できるため、本番前に1ジョブだけ走らせてconcurrencyLimitの見積もりと照合しておくと、後の調整コストを減らせます。
無料50本
テンプレート50本を ZIP で受け取る
メールアドレスを入れると、50本の ZIP のリンクをすぐにお送りします。
50本の ZIP をメールで受け取ります。あわせて RenderComp テンプレートの更新と、有料ライブラリを含む製品のご案内を受け取ることに同意します(メールは数通・ワンクリック解除)。 プライバシーポリシー(英語)
メールを使わずに受け取ることもできます。GitHub のリポジトリは公開のままで、登録も不要です。 リポジトリを開く
送信しました
ZIP のリンクを記載したメールをお送りしました。届かない場合は迷惑メールをご確認ください。いますぐ受け取る場合はこちらから直接ダウンロードできます。