在 Cloudflare Workers 上用 ffmpeg:用呼叫的,不是打包進去。
Workers 跑在 V8 isolate 裡:沒有檔案系統、不能跑原生二進位檔、CPU 時間卡得死死的。你的 Worker 只要透過 HTTPS 把一個 URL 交給 Fotovid,編碼會在 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 });
},
};為什麼 ffmpeg 在你的 Worker 上跑不動
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 | 全天候常駐的成本,外加修補、擴容與監控 | |
| 架一套任務佇列 + worker | 多一整套基礎設施:佇列、workers、重試、死信處理 | |
| 在瀏覽器裡轉檔(WASM) | 慢、吃記憶體,在手機上還會直接當掉 | |
| 呼叫 Fotovid API | 一個 HTTPS 請求,不用跑、不用打包、不用擴容 |
三步完成第一次呼叫
- 1取得免費 API 金鑰
註冊後建立一把金鑰,你會拿到一組 Authorization: Bearer p6_<key_id>:<secret> token,每一次對 https://api.fotovid.co 的呼叫都用它驗證。不用架任何基礎設施,也不用自己編譯 ffmpeg,只要一個 header。
- 2從 Worker 把影片 POST 出去
用標準的請求格式呼叫 POST /v1/video/watermark:source_url 指向你輸入影片的 HTTPS URL,再帶一個 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 託管空間上那支加好浮水印的成品影片。你可以直接把它交給前端,或複製到自己的儲存桶留一份永久備份——託管的結果是暫時性的。
