Vercel上のffmpegはデプロイで壊れます — 壊れないAPIを、今すぐ呼びましょう。
localhostでは動いていましたが、デプロイした瞬間に壊れました。それはあなたのコードの問題ではなく、ランタイムの問題です。Vercel関数からFotovidを呼び出しましょう:ソースURLを送信すると、Fotovidがレンダリング済みのメディアを返します。
// app/api/watermark/route.ts
import { NextResponse } from "next/server";
export async function POST(req: Request) {
const { videoUrl, logoUrl } = await req.json();
const res = await fetch("https://api.fotovid.co/v1/video/watermark", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FOTOVID_API_KEY!}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
source_url: videoUrl,
params: { type: "image", watermark_image_url: logoUrl, position: "bottom-right" },
}),
});
const { url } = await res.json();
return NextResponse.json({ url });
}なぜffmpegはVercelで壊れるのか
Vercelはアプリを動かすには最適な場所ですが、ffmpegを動かすには不向きです。Nodeのserverless関数は解凍後のバンドルを250MBまでに制限しており、自分のコードがカウントされる前の時点で、ffmpegとそのコーデックだけでこの上限を超えてしまいます。サイズ制限を避けようとEdgeランタイムに切り替えると、今度はchild_processが完全に使えなくなり、バイナリを起動する手段がなくなります。たとえビルドがすり抜けたとしても、関数のタイムアウト(Hobbyで10秒、Proでも上限あり)が実際のエンコードを途中で強制終了します。ffmpeg-staticやfluent-ffmpegがローカルでは通ってもデプロイすると失敗するのは、まさにこれが理由です。
- 解凍後250MBの関数上限:ffmpegとコーデックはNodeのserverlessバンドルに収まりません
- EdgeランタイムにはNode APIもchild_processもなく、バイナリを起動できません
- 関数のタイムアウト(Hobbyで10秒、Proでも上限あり)が長いエンコードを途中で打ち切ります
- ffmpeg-staticやfluent-ffmpegはlocalhostでは動作しても、デプロイした瞬間に壊れます
チームがVercelでffmpegを動かそうとする方法
Fotovid以前は、これらが選択肢でした — どれも自分では抱えたくない作業です。
| Option | What it costs you | Verdict |
|---|---|---|
| ffmpegをVercel関数にバンドルする | 250MBの関数上限を超えてしまいます。Edgeにはchild_processもありません。 | |
| コンテナやVMを自前でホストする | 常時稼働のコストに加え、パッチ適用・スケーリング・監視も必要です | |
| ジョブキュー+ワーカーを運用する | 新たなインフラが必要です:キュー、ワーカー、リトライ、デッドレター処理 | |
| ブラウザ内でトランスコードする(WASM) | 遅く、メモリを大量に消費し、モバイルではクラッシュします | |
| Fotovid APIを呼び出す | HTTPSリクエスト1回だけで完了:実行もパッケージ化もスケーリングも不要です |
最初の呼び出しを3ステップで
- 1無料のAPIキーを取得する
サインアップしてキーを作成します。カードは不要です。p6_<key_id>:<secret>という形式のトークンが発行されるので、Authorizationヘッダーに Bearerトークンとして渡します。Vercelプロジェクトの環境変数に設定しておけば、関数が実行時に読み込めます。
- 2動画をwatermarkエンドポイントにPOSTする
Vercel関数から、https://api.fotovid.co の POST /v1/video/watermark を標準のエンベロープで呼び出します:入力動画を指す source_url に加えて、オーバーレイの内容(画像またはテキストの透かし、position、opacity、scale)を記述する params オブジェクトです。関数内にバイナリもバンドルもエンコード処理も一切ありません。ffmpegの処理はFotovid側のインフラで行われるため、あなたの関数のタイムアウトは問題になりません。
- 3返されたホスト済みURLを使う
レスポンスは id、type、完成した動画の fotovid でホストされた url、expires_at を含むフラットなJSONで返ってきます。そのファイルは自分の側にも保存しておくか、そのままフロントエンドにURLを渡してください。同じエンベロープは trim、extract-audio、extract-cover、probe など、他のAPIでも共通して使えます。
