Cloudflare Workers で ffmpeg を動かすなら、バンドルせずに呼び出しましょう。
Workers は V8 isolate 上で動作するため、ファイルシステムもネイティブバイナリもなく、CPU 時間にも厳しい制限があります。Worker は Fotovid に URL を HTTPS で渡すだけ。エンコード処理は isolate の外側で実行され、結果はホスト済みリンクとして返ってくるので、CPU 予算を一切消費しません。
export default {
async fetch(req: Request, env: { FOTOVID_API_KEY: string }): Promise<Response> {
const { videoUrl, logoUrl } = await req.json();
const res = await fetch("https://api.fotovid.co/v1/video/watermark", {
method: "POST",
headers: {
Authorization: `Bearer ${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 Response.json({ url });
},
};Worker が ffmpeg で詰まる理由
Cloudflare Workers はコンテナ上ではなく、V8 isolate の中で動作します。一時ファイルを書き込むファイルシステムはなく、ネイティブバイナリをシェルアウトして実行する手段もなく、リクエストごとの CPU 時間にも厳格な制限があります。ffmpeg バイナリはそもそもそこに存在できません。WASM 版は技術的にはロードできますが、isolate のメモリと CPU の予算に抑え込まれ、ちょっとしたクリップを超えると処理が止まってしまいます。現実的な選択肢はホスト型 API だけです。
- ファイルシステムなし: ffmpeg は入力の読み込みと出力の書き込みに一時ファイルが必要ですが、Workers にはそれがありません。
- ネイティブバイナリなし: V8 isolate 内では ffmpeg バイナリをインストールも実行もできません。
- WASM 版の ffmpeg はロードできても isolate のメモリと CPU の上限に阻まれ、実際の動画では処理が止まるかタイムアウトします。
- リクエストごとの厳しい CPU 予算により、トランスコード規模の処理はそもそも成立しません。
Cloudflare Workers で ffmpeg を動かそうとする際のよくある手段
Fotovid が登場する前は、これらが選択肢でした — どれも本来自分で抱えたくない作業です。
| Option | What it costs you | Verdict |
|---|---|---|
| ffmpeg を Cloudflare Workers の関数にバンドルする | Workers はそもそもネイティブバイナリを一切実行できません | |
| コンテナや VM を自前でホストする | 常時稼働のコストに加え、パッチ適用・スケーリング・監視の負担 | |
| ジョブキュー + ワーカーを構築する | 新たなインフラが必要: キュー・ワーカー・リトライ・デッドレターの処理 | |
| ブラウザ側でトランスコードする (WASM) | 処理が遅くメモリを大量消費し、モバイルではクラッシュします | |
| Fotovid の API を呼び出す | HTTPS リクエスト1回だけ。実行も、パッケージ化も、スケーリングも不要 |
3ステップで最初の呼び出しを試す
- 1無料の API キーを取得する
サインアップしてキーを作成します。取得できる Authorization: Bearer p6_<key_id>:<secret> トークンで、https://api.fotovid.co へのすべての呼び出しを認証できます。インフラ構築も ffmpeg のビルドも不要で、必要なのはヘッダーだけです。
- 2Worker から動画を POST する
標準のエンベロープで POST /v1/video/watermark を呼び出します。入力動画の HTTPS URL を指す source_url と、params オブジェクトを渡します。params では type に image、text、combo のいずれかを指定し、さらに position (例: bottom-right)、opacity、scale を設定します。Worker 内からの単純な fetch なので、isolate のリクエストモデルにそのまま収まります。
- 3ホストされた結果 URL を使う
Fotovid はフラットな JSON を返します: { id, type, url, expires_at, duration }。url は完成した透かし入り動画が置かれた Fotovid のホスティング先を指します。そのままクライアントに渡すか、永続的に保存したい場合は自分のバケットにコピーしてください。ホストされた結果は一時的なものです。
