跳到主内容

别再手动录屏了:一套 FFmpeg 直播流录制自动化方案,算清楚再动手

“能不能不加人,把每天晚上八点那场直播自动录下来,第二天早上我到公司就能在文件夹里看到?”——这是一位做培训的客户在需求会上提的原话,后面还补了一句:“别让我再惦记着按录制键。”

能。用 FFmpeg 加一个定时任务就够了,不需要写播放器、不需要买录屏软件。这篇把我们在一个真实项目里跑通的方案拆开讲:为什么选 FFmpeg、命令怎么配、切片和音画同步这两个坑怎么绕、哪些部分值得抄、哪些部分我建议你别学。涉及的参数都对照了官方文档与公开资料,版本差异请以你机器上 ffmpeg -version 的实际输出为准。

项目背景与目标

客户的诉求拆开是三条:直播开始时自动开始录,直播结束后自动停;录完的文件要能直接剪辑,不能是一整个几十 GB 的巨型文件;断流重连之后不能出现音画不同步。

第三条是他们之前自己试过没搞定的。他们最初的想法是找个人坐着开录屏软件,试了两天就放弃了——人不可能每天准点坐在电脑前,录屏还占着机器。

这类需求其实很常见:培训机构的课程留存、直播带货的复盘素材、竞品直播的合规取证(前提是你有权利这么做)。核心都是同一件事——把「录」这个动作从人手里拿掉。

约束条件

动手之前先把边界定清楚,不然后面全是返工:

  • 源流协议:HTTP-FLV / HLS(m3u8) / RTMP 三种入口的命令行参数不一样,得先确认源是什么。这次拿到的主用地址是 HLS,备用是 RTMP。
  • 录制时长:单场 2 小时左右,不能落一个 2 小时的整体文件,剪辑拖不动,一旦中断就全丢。
  • 机器资源:一台常年开着的 Windows 办公机,没有独显,所以不能用需要硬件编码的方案。
  • 合规性:只录客户自己拥有版权或已获授权的内容;涉及第三方平台的直播流,必须遵守该平台的用户协议与相关法律法规,不采集与业务无关的内容,录下来的素材不对外分发。

有一点我原本判断错了:我以为难点在编码参数,后来才发现难点在进程怎么优雅地启动和退出。编码这事 -c copy 一行就完了。

执行过程

第一步:确认源流能拉

先跑一次最短的录制验证链路通不通,别上来就写脚本:

ffmpeg -i "直播流地址" -t 30 -c copy -f mp4 test.mp4

能播、有声、时长对得上 30 秒,再往下走。-c copy 表示不重新编码,直接封装,CPU 占用极低,这是整件事能在一台办公机上跑的前提。

第二步:切片

两个思路,看你要什么。要边录边能看的,用 HLS 的 hls muxer:

ffmpeg -i "直播流地址" -c:v copy -c:a copy \
  -f hls -hls_time 60 -hls_list_size 0 \
  -hls_segment_filename "seg_%03d.ts" out.m3u8

要直接给剪辑用的整段文件,用 segment muxer 按时间切块:

ffmpeg -i "直播流地址" -c copy \
  -f segment -segment_time 3600 -reset_timestamps 1 \
  rec_%03d.mp4

官方文档里对 hls muxer 的几个默认值写得很明确:hls_time 默认 2 秒,hls_list_size 默认 5(设 0 表示播放列表保留全部分片)。设 -hls_list_size 0 是为了录完能拿到完整的点播列表,别被默认的滑动窗口吃掉。

另外官方文档特别提醒:编码时要使用闭合 GOP,并让 GOP 大小与切片时长匹配,否则切片边界和关键帧对不齐,切出来的片头会花屏。如果源流是 copy 的,这一点你控制不了,只能在切片时长上取一个源 GOP 的整数倍(常用 2 秒、4 秒、6 秒的 GOP,切片就取 60 秒这类能整除的值)。

第三步:断线重连

长时间录制最怕的是网络抖一下进程就退了。HLS/RTMP 走 HTTP 协议,可以打开内置的重连:

ffmpeg -i "直播流地址" -c copy \
  -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 10 \
  -f segment -segment_time 3600 -reset_timestamps 1 rec_%03d.mp4

-reconnect_delay_max 10 表示重试间隔上限 10 秒。这个值别设太小,源站短暂 5xx 的时候会把请求打得更凶。

第四步:音画同步

这是客户自己踩过、我们也没能一次过的部分。直播流的时间戳经常是不连续的,重连之后更是直接跳变,直接封装出来的文件会「嘴型对不上」。

两个参数基本能解决大部分情况:

-fflags +genpts -avoid_negative_ts make_zero

+genpts 让 FFmpeg 重新生成缺失的时间戳,avoid_negative_ts make_zero 把起始时间戳归零,避免负数时间戳被某些播放器当成 0 处理导致第一段的音画错位。重连造成的跳变,则靠 -reset_timestamps 1 在每个切片开始时重置时间戳来隔离——一个片内的错位不会传染到下一个片。

如果源流本身音频采样率和容器不匹配,再补一个 -af aresample=async=1 做重采样对齐。这个不是万能的,遇到源本身音画就偏的情况,录制端救不回来。

第五步:定时与守护

Linux 上用 cron 最省事:

0 20 * * 1-5 ffmpeg -i "直播流地址" -c copy -reconnect 1 \
  -reconnect_streamed 1 -f segment -segment_time 3600 \
  -reset_timestamps 1 /data/record/rec_$(date +\%Y\%m\%d)_%03d.mp4

Windows 上用任务计划程序配同样的命令。这里有个坑值得单独说:如果你的宿主程序是通过标准输入往 FFmpeg 写帧(比如自己做采集再喂给它),写给 StandardInput.BaseStream 在写几千帧之后可能会卡住不返回——这个现象我们在WinForm 4.8 + WebView2 劫持直播流:CDP 抓包与 FFmpeg 落盘实战里详细记过,根因是管道缓冲区满了没人读。所以能用命令行直接拉源流,就别绕一层管道,这是这次项目里最值钱的一条经验。

结果数据:跑出来的是什么

一场 2 小时的直播,按 3600 秒切片,产出 rec_000.mp4、rec_001.mp4 这样的序列文件,命名里的序号由 %03d 决定位数。片数等于「录制总时长 ÷ segment_time」向上取整,每个片的实际体积取决于源流码率——这个数各家差异很大,我不写死一个值,你跑一次就知道了。

用 -c copy 的情况下,办公机 CPU 占用基本在个位数,录制期间机器还能正常干别的活。换成 libx264 重编码(-crf 23 -preset medium 这类参数)会立刻把 CPU 吃满,除非必须压缩体积,否则不建议。

至于音画,重连过的场次在加了 +genpts 和 -reset_timestamps 1 之后,客户那边反馈剪辑时没再出现错位。这个结论的边界是:源流本身时间戳是健康的。源流本身有问题的话,录制端只能缓解,不能根治。

可复用的部分与不值得复制的部分

  • -c copy 优先:不重编码是低资源占用的关键,也是这套方案能塞进一台办公机的前提。
  • 切片而非整段:既方便剪辑,又把中断的损失限制在一个片内。
  • 重连三件套:-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max N,长录必备。
  • 时间戳归零 + 逐片重置:-fflags +genpts -avoid_negative_ts make_zero 配 -reset_timestamps 1,解决重连后的音画漂移。
  • 取舍要果断:如果场景简单、试错成本低,其实只留第一步和第四步就行(拉流验证 + 定时),中间那些优化可以等真出问题了再加——这个「够用就停」的判断方式,在快手指数查询这件事,快手和抖音的指数到底差在哪?里也提到过,别为了完整而完整。

顺带一句,自动化省下来的人力是实打实的。我们另一篇复盘里记过,一套流程跑顺之后单篇内容的生产时间从 4 小时压到 1.8 小时(见当AI开始"点名"推荐,我们用GEO重构内容),量级不同,但道理一样:把重复动作交给进程。

不值得复制的部分

  • 自己写程序托管 FFmpeg 进程:除非你要做桌面端产品,否则 cron / 任务计划程序就够了。绕一层宿主程序只会多出管道堵塞、进程僵死这类问题。
  • 为了「万一」上重编码:我们第一版加了 libx264,理由是怕源流编码格式剪辑软件不认,结果机器卡到影响别的活,最后删掉了。剪辑软件认不了的情况一次都没出现。
  • 把切片时长设成 60 秒以下:片太碎,剪辑时导入几十个文件很痛苦。除非你真的要做近实时的分发,否则按小时切更实用。

相关工具

如果你要的不只是「录下来」,还想把直播中的弹幕、商品、互动数据一起结构化存下来,可以看小红书直播数据采集工具,字段和采集频率在页面里有说明。FFmpeg 本身的参数细节,建议以你本地 ffmpeg -version 对应版本的官方文档为准,网上的命令片段版本差异不小。

常见问题

录下来的文件能不能直接剪?

-c copy 出来的 MP4 主流剪辑软件都能认。如果导入报错,先检查是不是用了 .ts 封装需要转封装,或者源流编解码比较冷门,这种情况再考虑重编码。

直播没开始时启动 FFmpeg 会怎样?

会直接报连接失败退出。要么把定时任务设在开播之后几分钟,要么在外层套一个重试循环(间隔 30 秒,最多试 N 次)。后者更稳,但别忘了给循环设上限,否则源站挂了会一直空转。

为什么切出来的片头会花屏?

切片边界和关键帧没对齐。源流 copy 模式下你改不了 GOP,把 -segment_time 或 -hls_time 设成源 GOP 时长的整数倍通常能解决。如果是自己编码的场景,按官方文档的建议设闭合 GOP 并让 GOP 大小匹配切片时长。

音画不同步但源流看着是好的,怎么排查?

先加 -fflags +genpts -avoid_negative_ts make_zero,再确认切片时带了 -reset_timestamps 1。还不行就单独录 30 秒用播放器逐帧看,确认是不是源流本身就偏——录制端修不了源的问题。

录第三方平台的直播合规吗?

只录你有权利录制的内容,遵守目标平台的用户协议与相关法律法规,录制素材限内部使用、不对外分发。涉及取证用途的,先咨询专业人士,别仅凭技术可行就动手。

相关阅读

分享到:

本文链接:https://www.biyeyuanma.cn/post/229.html

服务热线

加我微信

加我微信