Remotion Lambda のレンダリングコスト計算式
執筆: RenderComp チーム 編集方針
Remotion でビデオをレンダリングするとき、同じ props を渡せば常に同じフレームが生成されます。この決定論的な挙動は、コスト計算にも同じ再現性をもたらします。フレーム数、フレームあたりの処理時間、Lambda のメモリサイズが決まれば、請求額はほぼ計算で求まります。
renderMediaOnLambda は内部で複数の Lambda 関数を並列起動し、各関数が framesPerLambda 枚ずつフレームを担当します。すべてのチャンクが S3 に出揃ったあと、最終的な結合処理が走ります。このアーキテクチャのどのパラメータがコストを動かすかを把握することで、同じ出力品質をより少ない計算資源で達成できます。
以下では、AWS Lambda の課金モデルと Remotion 固有の並列化戦略を組み合わせ、コスト計算式を分解します。
AWS Lambda の課金単位
AWS Lambda は GB-秒(GB-second) を課金単位とします。1 GB-秒は、1 GB のメモリを割り当てた関数が 1 秒間実行されたときのコストです。メモリを 2 GB にすれば、同じ 1 秒で 2 GB-秒になります。
Remotion Lambda の 1 回のレンダリングでは複数の Lambda 関数が起動します。コストの基本式は次のとおりです。
総コスト ≈ Σ (メモリ GB × 実行秒数) × 単価 ← 全 Lambda 関数の合計
+ S3 ストレージコスト
+ S3 リクエストコスト
S3 側のコストは通常ごく小さく、短尺ビデオであれば Lambda 実行コストの数パーセント未満に収まります。支配的な変数は Lambda の実行時間とメモリサイズです。
estimatePrice で事前見積もりを取る
@remotion/lambda パッケージは estimatePrice 関数を提供します。Lambda 関数の起動回数、実行時間、メモリサイズを渡すと、AWS の料金表に基づいた見積額を返します。
import { estimatePrice } from '@remotion/lambda';
const cost = estimatePrice({
region: 'ap-northeast-1',
memorySizeInMb: 3009,
diskSizeInMb: 2048,
durationInMilliseconds: 12000, // 各 Lambda の平均実行時間
lambdasInvoked: 15, // 並列起動した関数数
});
console.log(cost.estimatedDisplayCost); // 例: '$0.0047'
console.log(cost.currency); // 'USD'
console.log(cost.disclaimer); // AWS の免責事項テキスト
durationInMilliseconds は 1 つの Lambda 関数の実行時間です。lambdasInvoked はそのレンダリングで起動した関数の総数です。この 2 つの積が、実際に課金される GB-秒の量に直結します。
Remotion は現時点の AWS 料金表を参照してこの値を計算します。戻り値の estimatedDisplayCost は文字列で、AWS の免責事項に従った概算値として扱います。
framesPerLambda が並列数とコストを決める
renderMediaOnLambda の framesPerLambda パラメータは、1 つの Lambda 関数が担当するフレーム数を指定します。300 フレームのビデオを framesPerLambda: 20 でレンダリングすると、15 個の Lambda 関数が並列起動します。
import { renderMediaOnLambda } from '@remotion/lambda/client';
const result = await renderMediaOnLambda({
region: 'ap-northeast-1',
functionName: 'remotion-render-4-0-272-mem3009mb-disk2048mb-120sec',
serveUrl: 'https://your-site.s3.ap-northeast-1.amazonaws.com/sites/your-bundle-id',
composition: 'MyVideo',
inputProps: {},
codec: 'h264',
framesPerLambda: 20, // 300 フレーム ÷ 20 = 15 並列
memorySizeInMb: 3009,
});
並列数が増えると全体の完了時間は短縮されますが、Lambda の初期化(コールドスタート)と S3 への書き込みが各関数で発生するため、起動オーバーヘッドも増えます。
framesPerLambda と実行特性の関係
framesPerLambda を小さくすると並列度は上がりますが、起動回数が増えて初期化コストと S3 I/O が積み上がります。大きくすると並列度は下がり、1 関数あたりの実行時間が長くなります。純粋なフレーム処理コストはどちらもほぼ同じですが、起動回数が多いほどオーバーヘッド分の GB-秒が増えます。
| framesPerLambda | 並列 Lambda 数(300 フレーム) | 主なトレードオフ |
|---|---|---|
| 8 | 38 | 最速・高オーバーヘッド |
| 20 | 15 | バランス型 |
| 60 | 5 | 低オーバーヘッド・低速 |
framesPerLambda を省略した場合、Remotion はコンポジションの総フレーム数から値を自動算出します。明示的に指定すると、並列度とコストを意図的に制御できます。
レンダリング進行中のコスト確認
getRenderProgress は、レンダリング中にポーリングしてコスト情報を取得できます。レンダリングが完了するまでに複数回呼び出しても安全です。
import { getRenderProgress } from '@remotion/lambda/client';
const progress = await getRenderProgress({
bucketName: result.bucketName,
functionName: 'remotion-render-4-0-272-mem3009mb-disk2048mb-120sec',
region: 'ap-northeast-1',
renderId: result.renderId,
});
console.log(progress.overallProgress); // 0 〜 1
console.log(progress.costs.estimatedCost); // 現時点の推定コスト(USD)
console.log(progress.costs.estimatedDisplayCost); // 例: '$0.0023'
progress.costs が返す値は、その時点までに起動・完了した Lambda 関数の実行時間に基づく累積値です。レンダリングが 50 % 終了していれば、おおむね最終コストの半分に近い値が返ります。この値を監視ループに組み込むと、想定外のコスト超過を早期に検出できます。
import { renderMediaOnLambda, getRenderProgress } from '@remotion/lambda/client';
import type { AwsRegion } from '@remotion/lambda';
async function renderWithCostGuard(
maxCostUsd: number,
renderParams: Parameters<typeof renderMediaOnLambda>[0]
) {
const result = await renderMediaOnLambda(renderParams);
while (true) {
const progress = await getRenderProgress({
bucketName: result.bucketName,
functionName: renderParams.functionName as string,
region: renderParams.region as AwsRegion,
renderId: result.renderId,
});
if (progress.costs.estimatedCost > maxCostUsd) {
throw new Error(
`コスト上限 $${maxCostUsd} を超過: ${progress.costs.estimatedDisplayCost}`
);
}
if (progress.done) break;
if (progress.fatalErrorEncountered) {
throw new Error(progress.errors[0].message);
}
await new Promise((r) => setTimeout(r, 2000));
}
return result;
}
maxCostUsd を予算の上限に設定しておくと、バグやパラメータのミスによる過剰請求をプログラム側で抑制できます。
メモリサイズとコストの関係
Lambda のメモリサイズは CPU 割り当てに比例します。AWS Lambda は 1769 MB を超えると CPU リソースの割り当てが増加するため、3009 MB の設定では 1769 MB より多くの CPU が利用できます。CPU が増えると 1 フレームあたりの処理時間が短縮され、durationInMilliseconds が減ります。
課金単位は GB-秒なので、メモリを増やして実行時間が比例して短縮されれば、総コストはほぼ変わりません。ただし、Remotion の処理がシングルスレッドに近い部分ではメモリを増やしても速度向上が頭打ちになります。
// メモリと実行時間の GB-秒比較
function calcGbSeconds(memoryMb: number, durationMs: number, lambdas: number): number {
return (memoryMb / 1024) * (durationMs / 1000) * lambdas;
}
// 3009 MB × 8 秒 × 15 並列 = 約 353 GB-秒
console.log(calcGbSeconds(3009, 8000, 15).toFixed(1));
// 1769 MB × 13 秒 × 15 並列 = 約 345 GB-秒(ほぼ同等)
console.log(calcGbSeconds(1769, 13000, 15).toFixed(1));
この例ではメモリサイズを変えても GB-秒がほぼ変わりません。実際の数値は、コンポジションがテキスト描画、動画デコード、Web API をどう使うかによって変わります。Remotion のドキュメントでは 3009 MB を推奨のデフォルトとして示しており、多くのコンポジションでこの値が出発点になります。
実測して比較する手順
設定の効果を測るには、getRenderProgress の costs と overallProgress をログに記録しながら複数設定でレンダリングを走らせます。フレーム数を 30 〜 60 程度に絞ったテスト用コンポジションを用意しておくと、本番よりも短時間・低コストで比較できます。
renderMediaOnLambda が返すコスト情報
レンダリング完了後、renderMediaOnLambda の戻り値にもコスト情報が含まれます。
const result = await renderMediaOnLambda({ /* ... */ });
// レンダリング後の確定コスト
console.log(result.estimatedPrice.estimatedCost); // 例: 0.0051
console.log(result.estimatedPrice.estimatedDisplayCost); // 例: '$0.0051'
console.log(result.timeToFinish); // ミリ秒単位の総処理時間
result.estimatedPrice はレンダリング後に確定した実際の Lambda 実行回数と時間を元に算出されます。事前に estimatePrice を単体で呼び出した値より正確で、CI/CD パイプラインでコストをログに残す際の出典として適しています。
不要な S3 オブジェクトの削除
deleteRender を呼び出すと、レンダリングに使った中間チャンクファイルを S3 から削除できます。
import { deleteRender } from '@remotion/lambda/client';
await deleteRender({
bucketName: result.bucketName,
region: 'ap-northeast-1',
renderId: result.renderId,
});
1 回あたりのストレージコストは小さいですが、大量のレンダリングを継続的に走らせる場合は積み上がります。レンダリング後の後片付けをパイプラインの定型処理に組み込んでおくと、S3 の残留オブジェクトが増えにくくなります。
Wrapping Up
Remotion Lambda のコストは、Lambda の起動回数 × 実行時間 × メモリサイズという 3 変数に集約されます。estimatePrice で事前見積もりを取り、getRenderProgress で進行中のコストを監視し、renderMediaOnLambda の戻り値で事後確認するという流れが基本パターンです。
framesPerLambda は並列度とオーバーヘッドを直接制御します。デフォルト近辺の値から始めて、実際のコンポジションで costs を記録しながら調整するのが確実です。次のユーティリティ関数を手元に置いておくと、本番レンダリング前に予算内に収まるかをすばやく確認できます。
import { estimatePrice, type AwsRegion } from '@remotion/lambda';
function roughCostEstimate({
totalFrames,
framesPerLambda,
memorySizeInMb,
msPerFrame, // テストレンダリングで実測した値を入れる
region,
}: {
totalFrames: number;
framesPerLambda: number;
memorySizeInMb: number;
msPerFrame: number;
region: AwsRegion;
}) {
const lambdasInvoked = Math.ceil(totalFrames / framesPerLambda);
// +3000ms は Lambda 初期化と S3 I/O の見込みオーバーヘッド
const durationPerLambdaMs = framesPerLambda * msPerFrame + 3000;
return estimatePrice({
region,
memorySizeInMb,
diskSizeInMb: 2048,
durationInMilliseconds: durationPerLambdaMs,
lambdasInvoked,
});
}
// 10 秒 × 30 fps のビデオ、1 フレームあたり 400 ms で処理できる場合
const estimate = roughCostEstimate({
totalFrames: 300,
framesPerLambda: 20,
memorySizeInMb: 3009,
msPerFrame: 400,
region: 'ap-northeast-1',
});
console.log(estimate.estimatedDisplayCost);
msPerFrame は 30 〜 60 フレーム程度のテストレンダリングを走らせて timeToFinish / frameCount で求めます。RenderComp カタログのテンプレートも同じ renderMediaOnLambda API を前提に設計されているため、ここで示した計算式をそのまま適用できます。