ffmpeg 在 Netlify Functions 上:体积太大打不进包,交给托管服务来跑。
Netlify Functions 跑在 AWS Lambda 上,所以 ffmpeg 既撑爆打包体积上限,运行时间也超过默认超时。把这活交给 Fotovid:发出一个请求,拿回一个可用的结果 URL——远远赶在任何超时之前。
// netlify/functions/watermark.mts
export default async (req: Request) => {
const { videoUrl, logoUrl } = await req.json();
const res = await fetch("https://api.fotovid.co/v1/video/watermark", {
method: "POST",
headers: {
Authorization: `Bearer ${Netlify.env.get("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 在 Netlify 上总是跑不起来
Netlify Functions 在 AWS Lambda 上执行,而这正是 ffmpeg 处处碰壁的地方。静态编译的 ffmpeg 二进制远远超出约 50MB 压缩 / 250MB 解压后的打包上限,结果要么部署直接失败,要么二进制悄无声息地根本没被打进去。就算你想尽办法把它塞了进去,默认 10s 的函数超时也会掐断任何真实的转码——后台函数能给到 26s,对大多数视频任务来说依然不够。这就是典型的“本地跑得好好的,上了生产就超时”。
- ffmpeg 二进制加依赖库超出 Lambda 250MB 解压后打包上限
- 默认 10s 超时(后台函数 26s)会在转码跑到一半时掐断
- 冷启动加上反复折腾 layer,既拉高延迟又增加打包的麻烦
- 本地跑通,在部署后的函数里却复现不了
团队在 Netlify 上跑 ffmpeg 的几种常见办法
在 Fotovid 之前,你只有这些选择——每一种都是你并不想自己扛的活。
| Option | What it costs you | Verdict |
|---|---|---|
| 把 ffmpeg 打进你的 Netlify 函数 | 超出 250MB 打包上限,还会撞上 10s 函数超时 | |
| 自建容器或虚拟机 | 常驻运行的成本,外加打补丁、扩容和监控 | |
| 自己跑任务队列 + worker | 多一整套基础设施:队列、worker、重试、死信处理 | |
| 在浏览器里转码(WASM) | 慢、吃内存,在移动端还会崩溃 | |
| 调用 Fotovid API | 一个 HTTPS 请求;没有任何东西要运行、要打包、要扩容 |
三步完成第一次调用
- 1领取一个免费 API 密钥
注册并创建一个密钥。认证只需要一个 Authorization: Bearer p6_<key_id>:<secret> 请求头——不用二进制,不用 Lambda layer,也没有任何东西要打进你的 Netlify Function。
- 2把视频 POST 到水印接口
在你的 Netlify Function 里,调用 https://api.fotovid.co 上的 POST /v1/video/watermark。请求体是统一的信封结构:一个指向输入视频的 source_url,加一个 params 对象——把 type 设为 image、text 或 combo,再选一个 position(比如 bottom-right),还可以带上 opacity、scale 和 padding。ffmpeg 的活由 Fotovid 在平台之外完成,所以你的函数只发一个快速的 HTTPS 请求,而不必去调起一个它根本打不进包的二进制。
- 3直接使用托管的结果 URL
响应是扁平的 JSON,包含 id、type、url 和 expires_at。url 指向处理完成、由 Fotovid 托管的视频。你可以把它直接返回给客户端,也可以自己存一份——结果只临时托管,所以请下载后再持久化到你自己存放素材的地方。
