ffmpeg 在 Vercel 上一部署就挂——改用一个不会挂的 API。
本地跑得好好的,一部署就挂了。问题不在你的代码,而在运行时。让你的 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 Runtime 来绕开体积限制,你就彻底失去了 child_process,根本没有办法启动任何二进制。就算构建侥幸通过,函数超时(Hobby 上是 10s,Pro 上也有上限)也会把任何真实的编码任务拦腰截断。ffmpeg-static 和 fluent-ffmpeg 在本地一路顺利,一部署就失败,原因正在于此。
- 解压后 250MB 的函数上限:ffmpeg 加上编解码器塞不进 Node serverless 打包产物
- Edge Runtime 没有 Node API,也没有 child_process,你无法启动任何二进制
- 函数超时(Hobby 10s,Pro 也有上限)会让耗时长的编码中途被掐断
- ffmpeg-static 和 fluent-ffmpeg 在本地能跑,一部署就挂
团队在 Vercel 上跑 ffmpeg 的几种尝试
在 Fotovid 出现之前,你只有这几个选择——每一个都是你不想自己扛下来的活儿。
| Option | What it costs you | Verdict |
|---|---|---|
| 把 ffmpeg 打包进 Vercel 函数 | 远远超出 250MB 函数上限;Edge 又没有 child_process | |
| 自建容器或虚拟机 | 常驻成本,外加打补丁、扩缩容和监控 | |
| 搭一套任务队列 + worker | 多出一整套基础设施:队列、worker、重试、死信处理 | |
| 在浏览器里转码(WASM) | 又慢又吃内存,在手机上还会崩溃 | |
| 调用 Fotovid API | 一次 HTTPS 请求;没有东西要运维、要打包、要扩容 |
三步完成第一次调用
- 1免费拿一个 API 密钥
注册并创建密钥,无需绑卡。你会拿到一个形如 p6_<key_id>:<secret> 的令牌,通过 Bearer 授权头传入。把它写进 Vercel 项目的环境变量,函数在运行时就能读到。
- 2把视频 POST 到水印端点
在你的 Vercel 函数里,向 https://api.fotovid.co 上的 POST /v1/video/watermark 发起调用,用的是统一的请求结构:一个指向输入视频的 source_url,再加上描述叠加内容的 params 对象(图片或文字水印、位置、不透明度和缩放比例)。不用二进制,不用打包,函数内部也不跑任何编码。ffmpeg 的活儿由 Fotovid 在自己的基础设施上完成,你的函数超时限制根本不会成为问题。
- 3直接使用返回的托管 URL
响应是扁平的 JSON,包含 id、type、指向成片的 fotovid 托管 url,以及 expires_at。你可以自己存一份文件副本,也可以把 URL 直接交给前端。API 的其余能力用的是同一套请求结构:trim、extract-audio、extract-cover、probe 等等。
