在 Supabase Edge Functions 上執行 ffmpeg

在 Supabase Edge Functions 上使用 ffmpeg,整段工作交給一次 HTTPS 請求。

Edge Functions 跑在 Deno 上,沒有 child_process 可以用來啟動 ffmpeg 二進位檔。你的函式維持原樣,把編碼工作交給一次 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 });
});

為什麼 ffmpeg 在你的 Edge Function 裡跑不起來

Supabase Edge Functions 跑在 Deno 執行環境上,而 Deno 沒有 child_process 或 subprocess API——就算你把 ffmpeg 二進位檔一起打包進去,也沒有任何方式可以把它啟動起來。除此之外,CPU 與總執行時間的上限是為輕量的請求邏輯而設計,撐不起媒體編碼那種動輒數秒到數分鐘的持續運算。檔案一落地就用 Storage 觸發器把工作「啟動」起來確實再適合不過,但真正的轉碼必須放在跑得動真正編碼器的地方。

  • Deno 上沒有 child_process / subprocess,你無法執行 ffmpeg 二進位檔
  • CPU 與總執行時間上限是為快速邏輯設計的,不是為媒體編碼
  • Storage 觸發器很適合用來啟動工作,但實際運算必須放在別處
  • 靜態編譯的 ffmpeg、WASM 與 layer 全都卡在執行環境本身,不只是檔案大小的問題

開發團隊在 Supabase 上執行 ffmpeg 的幾種嘗試

在 Fotovid 出現之前,你只有這些選項——每一個都是你不會想自己扛下來的工作。

OptionWhat it costs youVerdict
把 ffmpeg 打包進你的 Supabase 函式Deno 沒有 child_process,根本啟動不了二進位檔
自架容器或 VM全天候的機器成本,再加上更新、擴充與監控
自建任務佇列 + worker多一整套基礎設施:佇列、worker、重試、死信處理
在瀏覽器裡轉碼(WASM)速度慢、吃記憶體,在手機上還會直接當掉
呼叫 Fotovid API一次 HTTPS 請求;不用自己跑、不用打包、不用擴充
How it works

三個步驟完成第一次呼叫

  1. 1
    免費取得 API 金鑰

    註冊後建立一組金鑰。Fotovid 以用量計費的 credits 運作——$1 = 100 credits,多數操作只花 1 credit——所以你可以先把主打的浮水印呼叫串起來、從頭到尾完整測過一輪,再決定要不要花錢。

  2. 2
    從你的函式呼叫浮水印端點

    在同一個 Edge Function 裡(或是上傳時觸發的 Storage 觸發器裡),帶上 Authorization: Bearer p6_<key_id>:<secret> 標頭,POST 到 https://api.fotovid.co/v1/video/watermark。送出標準的請求格式:一個指向影片 HTTPS URL 的 source_url——Supabase Storage 的簽章 URL 可以直接用——再加上描述疊加內容的 params 物件,例如 type 設為 image、一個 watermark_image_url、像 bottom-right 這樣的 position,以及 opacity 或 scale。你的函式只發出一次 HTTPS 請求;ffmpeg 的工作由 Fotovid 在平台外執行,所以你完全碰不到 Deno 的 CPU 與時間上限。

  3. 3
    使用託管的結果 URL

    回應是扁平的 JSON:一個 id、一個 type,以及指向成品影片(由 Fotovid 託管)的 url。你可以把這個 url 直接回傳給呼叫端,或是下載下來、在 Supabase Storage 存一份自己的副本。請把託管 URL 視為暫時的——它帶有 expires_at——需要長期保存就自己留一份。

常見問題

一次 API 呼叫就能上線

拿一把免費金鑰,五分鐘內完成你的第一次呼叫。