Supabase Edge Functionsのffmpeg処理を、HTTPS呼び出し1回にオフロード。
Edge FunctionsはDeno上で動くため、ffmpegバイナリをspawnするchild_processがありません。関数はそのまま残し、エンコードだけをHTTPS呼び出しにオフロードすれば、完成したファイルのURLが返ってきます。
// supabase/functions/watermark/index.ts
Deno.serve(async (req) => {
const { videoUrl, logoUrl } = await req.json();
const res = await fetch("https://api.fotovid.co/v1/video/watermark", {
method: "POST",
headers: {
Authorization: `Bearer ${Deno.env.get("FOTOVID_API_KEY")}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
source_url: videoUrl, // a Supabase Storage signed URL works here
params: { type: "image", watermark_image_url: logoUrl, position: "bottom-right" },
}),
});
const { url } = await res.json();
return Response.json({ url });
});Edge Functionでffmpegが動かない理由
Supabase Edge FunctionsはDenoランタイム上で実行され、child_processやsubprocessのAPIが存在しません。つまりffmpegバイナリをバンドルしたとしても、それを起動する手段自体がないのです。さらにCPUと実行時間の上限は、軽量なリクエスト処理を想定したサイズであり、メディアエンコードに必要な数秒〜数分単位の継続処理には対応していません。Storageトリガーはファイルが届いた瞬間にジョブを*開始*するには最適な場所ですが、実際のトランスコードは本物のエンコーダーを実行できる場所で行う必要があります。
- Denoにはchild_process/subprocessがなく、ffmpegバイナリをexecできません
- CPUと実行時間の上限は軽量なロジック向けで、メディアエンコード向けではありません
- Storageトリガーはジョブの起点としては理想的だが、実処理は別の場所で行う必要があります
- 静的ビルドのffmpeg、WASM、レイヤーはいずれもサイズではなくランタイム自体の壁に突き当たります
Supabaseでffmpegを動かす方法とその代償
Fotovid以前は、これらの選択肢しかありませんでした。どれも自分たちで抱え込みたくない作業です。
| Option | What it costs you | Verdict |
|---|---|---|
| Supabase Functionにffmpegをバンドルする | Denoにはchild_processがなく、バイナリをspawnできません | |
| コンテナやVMをセルフホストする | 常時稼働のコストに加え、パッチ適用・スケーリング・監視も必要 | |
| ジョブキュー + ワーカーを構築する | キュー、ワーカー、リトライ、デッドレター処理という新規インフラが必要 | |
| ブラウザ内でトランスコードする(WASM) | 動作が遅く、メモリを大量消費し、モバイルではクラッシュします | |
| Fotovid APIを呼び出す | HTTPSリクエスト1回のみ。実行も、パッケージ化も、スケーリングも不要 |
最初の呼び出しまでの3ステップ
- 1無料のAPIキーを取得する
サインアップしてキーを作成します。Fotovidはcreditの従量課金制で、$1 = 100 credits、ほとんどの操作は1 creditで実行できます。まずは主力機能である透かし呼び出しを組み込み、費用をかける前にエンドツーエンドでテストできます。
- 2関数から透かしエンドポイントを呼び出す
同じEdge Function内(あるいはアップロード時に発火したStorageトリガー内)から、Authorization: Bearer p6_<key_id>:<secret>ヘッダーを付けてhttps://api.fotovid.co/v1/video/watermarkにPOSTします。送信するのは標準的なエンベロープです。動画のHTTPS URLを指すsource_url(Supabase Storageの署名付きURLがそのまま使えます)に加え、オーバーレイを記述するparamsオブジェクト、例えばtype imageやwatermark_image_url、bottom-rightのようなposition、opacityやscaleを指定します。関数側はHTTPSリクエストを1回発行するだけで、ffmpegの処理はFotovidがプラットフォーム外で実行するため、DenoのCPUや時間の上限に触れることは一切ありません。
- 3ホストされた結果のURLを使う
レスポンスはフラットなJSONで、id、type、そしてFotovidがホストする完成済みの動画を指すurlが返ります。そのurlを呼び出し元にそのまま返すか、ダウンロードしてSupabase Storageに自分で保存してください。ホストされたURLはexpires_atを持つ一時的なものとして扱い、長期保存が必要な場合はコピーを永続化してください。
