Go调用FFmpeg需用os/exec,确保ffmpeg已安装并配置PATH;传参加-y避免阻塞,路径含空格或中文需双引号包裹;用StderrPipe实时读取含time=的进度行;关键参数如-map、-vsync、-pix_fmt不可省;并发需用semaphore限流,临时文件用os.CreateTemp。

Go 语言本身不支持音视频处理,必须调用 FFmpeg
Go 标准库没有音视频编解码、封装、转码能力,os/exec 调用外部 ffmpeg 是最常用、最可靠的方式。别被“GoFFmpeg”“gomp4”这类第三方库误导——它们要么只是命令行封装,要么只覆盖极窄场景(如仅读 MP4 头),真要裁剪、加水印、抽帧、转码,绕不开 ffmpeg 二进制。
常见错误现象:exec: "ffmpeg": executable file not found in $PATH;或调用后进程卡住没输出;或中文路径/参数乱码。
- 确保系统已安装 FFmpeg,且
ffmpeg -version可执行(macOS 用brew install ffmpeg,Ubuntu 用apt install ffmpeg) - 用
exec.Command("ffmpeg", "-i", inputPath, "-y", outputPath)启动,**务必传-y**,否则交互式确认会阻塞 - Windows 下路径含空格或中文时,用双引号包裹参数:
"C:\my files\in.mp4"→ 实际传参应为`"C:\my files\in.mp4"`(Go 字符串里写两个反斜杠) - 捕获
cmd.CombinedOutput()而非cmd.Output(),避免 stderr 被丢弃导致看不到关键错误(如 codec not found)
用 os/exec 调用 ffmpeg 时如何实时获取进度
FFmpeg 默认把进度输出到 stderr,但它是行缓冲的,且格式不固定。想做进度条或超时控制,不能靠等整个命令结束。
使用场景:Web 接口接收上传文件后异步转码,需返回当前进度给前端。
立即学习“go语言免费学习笔记(深入)”;
- 用
cmd.StderrPipe()获取管道,启动后立即cmd.Start(),再逐行读取 stderr - FFmpeg 进度行特征是包含
frame=、fps=、time=的行,例如:frame= 1250 fps= 24.0 q=-1.0 size= 4567kB time=00:00:52.12 bitrate= 712.3kbits/s - 注意:第一行可能是警告(如
Guessed Channel Layout for Input Stream),跳过不含time=的行更稳妥 - 别用
bufio.Scanner默认 64KB 缓冲,大日志可能截断;改用bufio.NewReader(pipe).ReadString(' ')更可控
ffmpeg 命令参数选错会导致静音、黑屏或无声输出
不是所有参数组合都安全。尤其涉及音视频流选择、编码器、时间戳对齐时,一个参数偏差就让输出不可播放。
典型错误现象:输出文件能打开但只有音频没画面;或有画面但播放速度飞快;或文件体积极小但无法解码。
- 强制指定音视频流:用
-map 0:v:0(第一个视频流)、-map 0:a:0(第一个音频流),避免 FFmpeg 自动选错流 - 时间基准不一致会崩:如果输入有 B-frame 或变帧率,加
-vsync vfr或-vsync cfr显式控制,别依赖默认 - 硬编码 H.264 时,
-c:v libx264必须配-pix_fmt yuv420p,否则 iOS / 某些播放器直接黑屏 - 抽帧保存图片时,
-vf fps=1和-r 1效果不同:-r是 muxer 级别控制输出帧率,-vf fps是 filter 级别精确抽帧,优先用后者
并发调用 ffmpeg 容易触发资源耗尽或竞争
每个 ffmpeg 进程默认吃满 CPU,多路同时跑会卡死系统,尤其在容器或低配服务器上。
性能影响:1 路 1080p 转码约占 1.2–1.8 个逻辑核;未限制时 4 路就可能把 4 核机器拖到无响应。
- 用 Go 的
semaphore(如golang.org/x/sync/semaphore)限制并发数,例如sem := semaphore.NewWeighted(2)控制最多 2 路同时转码 - FFmpeg 内部也支持线程数控制:
-threads 2可降低单任务 CPU 占用,但别设成 1(性能暴跌) - 避免共享输入文件句柄:不要多个 goroutine 同时读同一个
*os.File,先os.Open再传路径字符串给子进程更稳 - 临时文件务必用
os.CreateTemp,别手写/tmp/out_123.mp4,防止并发覆盖或权限冲突
最常被忽略的是 FFmpeg 日志级别和错误粒度——加 -v quiet -stats 会让进度解析失效,而 -v error 又会吞掉关键的 warning(比如 audio/video timestamp mismatch)。真要兼顾日志和进度,得保留 -v info 并自己过滤行。


















