Go语言本身不支持音视频处理,必须通过os/exec调用FFmpeg二进制实现转码;实时进度需用-progress pipe:1将结构化数据输出到stdout,并用goroutine配合bufio.NewReader逐行解析out_time_ms等字段,结合预查总时长计算百分比。

Go 语言本身不提供视频转码能力,ffmpeg 才是实际干活的;协程(goroutine)只负责监控、读取进度、通知 UI,别指望用 go 关键字自己写个转码器。
怎么让 ffmpeg 输出实时进度给 Go 程序
关键在 ffmpeg 的参数:必须启用详细日志并强制刷新输出缓冲,否则 Go 读不到实时行。默认情况下,ffmpeg 在非交互终端里会缓冲 stderr,导致进度“卡住”几秒甚至更久。
- 加
-progress pipe:1:把结构化进度(key=value 形式)输出到 stdout(注意不是 stderr) - 加
-v quiet -stats或干脆去掉-stats,避免干扰行解析;如果需要控制台显示,用-v info+ 单独处理 stderr 中的百分比行 - 务必加
-y自动确认覆盖,否则卡在 stdin 等输入 - 示例命令:
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4 -y -progress pipe:1 -v quiet
用 goroutine 实时读 progress pipe 并解析进度
cmd.Stdout 是一个 io.ReadCloser,可逐行扫描。不能用 bufio.Scanner 默认的 64KB 缓冲——某些 ffmpeg 版本会一次性刷出多行,超长行可能被截断;建议用 bufio.NewReader + ReadString('\n') 更可控。
- 每行是
key=value格式,如out_time_ms=12345000、progress=end - 关注
out_time_ms和duration_us(或先从ffprobe预查总时长),算百分比;注意单位:ms vs us - 遇到
progress=end或读到 EOF,说明转码完成或出错 - 别在解析 goroutine 里直接更新 UI;通过
chan float64或回调函数往外推进度值
为什么用 cmd.Process.Kill() 而不是 cmd.Wait() 做取消
用户点“取消”,你得立刻停掉 ffmpeg 进程;但 cmd.Wait() 会阻塞到子进程自然退出,而 ffmpeg 可能还在写最后一帧、刷缓存,卡住 1–5 秒。
立即学习“go语言免费学习笔记(深入)”;
- 调用
cmd.Process.Kill()发送 SIGKILL(Unix)或 TerminateProcess(Windows),强制结束 - 之后仍需调用
cmd.Wait()—— 否则进程变成僵尸,且cmd.ProcessState不会就绪 - 注意:Kill 后再 Wait 是安全的,
Wait()会立即返回,ProcessState.Exited()为 true,ProcessState.Success()为 false - 别漏 defer
cmd.Wait(),否则 goroutine 泄漏 + 子进程残留
真正难的不是起 goroutine,而是 ffmpeg 的输出行为随版本、平台、参数组合变化很大;同一行 out_time_ms 在不同场景下可能跳变、重复、滞后。预查时长、平滑滤波、超时兜底,这些才是实际项目里躲不开的活。


















