Go音视频开发需明确角色:服务端接收/转发、转码调度或播放器控制,对应不同技术路径;joy4适合轻量RTMP/HLS服务,但需手动处理多路流和HLS切片清理;exec.Command调ffmpeg需注意日志捕获、超时控制与跨平台路径;goav提供帧级控制但需精细管理内存与时间基。

Go 做音视频开发,不是写个 http.ListenAndServe 就能推流,也不是调个 exec.Command("ffmpeg") 就算完成。真正落地时,你得明确自己在哪个环节:是当服务端接收/转发流?还是做转码调度?或是控制播放器?每个角色对应完全不同的技术路径和坑。
用 joy4 快速搭建 RTMP/HLS 流媒体服务器
joy4 是目前 Go 生态里最轻量、协议支持最全的流媒体库,适合快速验证或中小规模部署。它不依赖 ffmpeg,纯 Go 实现,启动一个 RTMP 接收 + HLS 分发服务只要 10 行代码。
- 直接运行
go run ./cmd/rtmp2hls/main.go(项目自带示例)就能监听:1935推流 +:8080拉流 - 推流地址是
rtmp://localhost:1935/live,拉流地址是@#@#@#@#@#@#@#@#@#@0 - 默认只处理一路流;多路需手动加
Server.RegisterStreamHandler回调,否则新流会静默丢弃 - 它不自动切片或清理过期
.ts文件,HLS目录要自己轮询删除,否则磁盘撑爆
用 exec.Command 调 ffmpeg 做转码或截图
这是最常用也最容易翻车的方式。Go 本身不处理帧,只管起进程、传参数、等退出。
- 必须显式设置
cmd.Stdout和cmd.Stderr,否则ffmpeg进度日志卡住导致阻塞 - 截图命令如
ffmpeg -i input.mp4 -vf "fps=1" out_%03d.jpg,注意-vsync vfr才能按实际关键帧输出,否则可能生成空图 - 转码时若输入流不稳定(如网络拉流),
ffmpeg可能 hang 住,必须加cmd.WaitDelay或用context.WithTimeout强制杀进程 - Windows 下路径含空格必须用双引号包裹,Linux/macOS 则不需要——跨平台时建议统一用
filepath.Join拼路径再传参
用 goav 直接对接 FFmpeg C API
当你需要帧级控制(比如加滤镜、实时美颜、抽特定 PTS 帧),exec 太粗粒度,就得上 cgo 绑定。
-
goav的avcodec模块要求你手动管理解码器上下文、帧缓冲、时间基换算,AV_TIME_BASE和time.Duration之间换算极易出错 -
swscale缩放 YUV→RGBA 时,若源帧宽高不是 2 的倍数,某些缩放算法会 panic;得先用av_image_fill_arrays对齐内存 - macOS 上默认链接
libavcodec.dylib,但 Homebrew 安装的 ffmpeg 动态库名可能是libavcodec.60.dylib,需软链或改CGO_LDFLAGS - 没有自动错误恢复:解码失败一帧,后续所有帧 PTS 可能乱序,必须自己维护
pkt.dts和frame.pts的单调递增逻辑
流媒体真正的复杂点不在“怎么跑起来”,而在于连接中断后怎么续传、多路流之间时钟怎么对齐、HLS 切片怎么保证 EXT-X-DISCONTINUITY 不被误判——这些细节不会报错,但会让客户端花屏、卡顿、反复重连。别急着封装 SDK,先用 tcpdump 抓包看清楚你的 RTMP 握手是否带 chunk size 重协商,再动手写逻辑。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










