26、直播流处理:RTMP/RTSP/HLS协议、拉流与推流、直播转码

说到直播流处理,这可能是音视频工程师日常工作中最「接地气」的一块了。我入行那会儿,直播还没现在这么火,但协议那套东西已经打得不可开交。RTMP、RTSP、HLS,这三个名字你肯定不陌生。它们各有各的脾气,也各有各的用武之地。

今天这一章,我就带你把这些协议掰开揉碎,再聊聊拉流、推流和直播转码的那些坑。嗯,都是实战里摸爬滚打出来的经验。

直播协议三剑客:RTMP、RTSP、HLS

先说说这三个协议到底干嘛用的。说白了,它们就是音视频数据在网络上传输的「规矩」。不同的规矩,决定了延迟、兼容性、稳定性都不一样。

RTMP(Real-Time Messaging Protocol)

RTMP 是 Adobe 搞出来的,最初为了 Flash 播放器服务。现在 Flash 早没了,但 RTMP 在推流端依然坚挺。为什么?因为它延迟低,交互性好。

  • 传输层:基于 TCP,长连接。数据包小,实时性高。
  • 延迟:通常在 1-3 秒,适合互动直播。
  • 缺点:默认端口 1935 容易被防火墙拦截。而且浏览器原生不支持,得靠插件或转码。
  • 我的经验:我做过一个户外直播项目,推流端用 RTMP 到服务器,服务器再转 HLS 给观众。RTMP 推流非常稳,但一旦网络抖动,画面会卡住几秒,不像 HLS 那样能自适应。
小提示:RTMP 推流地址格式通常是 rtmp://your-server.com/live/stream-key。stream-key 是流标识,别泄露,否则谁都能往你频道推流。

RTSP(Real-Time Streaming Protocol)

RTSP 是网络摄像头和安防领域的「老大哥」。它本身不传数据,只负责控制(播放、暂停、快进),真正的音视频数据走 RTP 协议。

  • 传输层:控制用 TCP,数据用 UDP(默认)。所以延迟极低,可以做到 0.5 秒以内。
  • 适用场景:安防监控、视频会议、低延迟直播。
  • 缺点:UDP 传输容易丢包,网络差时画面会花屏。而且防火墙对 UDP 不友好。
  • 避坑指南:我曾经在部署 RTSP 拉流时,发现画面每隔几分钟就卡一下。查了半天,原来是路由器对 UDP 包做了限速。后来改成 TCP 模式(?tcp 参数),问题解决。

HLS(HTTP Live Streaming)

HLS 是苹果推出的,现在几乎成了「通用语言」。它把直播流切成一个个小文件(.ts 或 .m4s),通过 HTTP 分发。说白了,就是把直播伪装成「文件下载」。

  • 传输层:HTTP,能过任何防火墙。CDN 支持极好。
  • 延迟:通常 6-30 秒。因为要等切片生成和下载,延迟天然高。
  • 优点:兼容性无敌。浏览器、手机、电视盒子都能播。
  • 我的看法:如果你做的是「一对多」的大规模直播,比如演唱会、教育直播,HLS 是首选。延迟高一点,但稳定性和覆盖范围没得比。
核心对比:RTMP 推流强,HLS 播放强,RTSP 延迟强。选哪个,看你的场景偏「生产」还是偏「消费」。

拉流与推流:数据怎么流动

搞清楚了协议,接下来就是「怎么把流弄进来」和「怎么把流送出去」。这两个动作,在 FFmpeg 里就是一行命令的事,但背后的逻辑你得懂。

推流(Publish/Stream Out)

推流,就是把本地的音视频数据,通过某种协议发送到服务器。最常见的推流协议就是 RTMP。

FFmpeg 推流命令示例:

ffmpeg -re -i input.mp4 -c:v libx264 -c:a aac -f flv rtmp://server/live/stream
  • -re:以原始帧率读取。不加这个,FFmpeg 会以最快速度推完,直播就变成「录播」了。
  • -f flv:RTMP 推流通常封装成 FLV 格式。
  • rtmp://...:推流地址。
注意:推流时一定要控制码率。我见过有人用 20Mbps 码率推流,结果观众端全卡死。建议根据网络情况设置 -b:v 2M 或更低。

拉流(Pull/Stream In)

拉流,就是从服务器或摄像头获取直播流。FFmpeg 可以拉 RTMP、RTSP、HLS 等任何协议。

拉 RTSP 流并保存为文件:

ffmpeg -i rtsp://camera-ip:554/stream -c copy output.mp4

拉 HLS 流并实时转码:

ffmpeg -i https://example.com/live/playlist.m3u8 -c:v libx264 -b:v 1M output.ts

我个人的习惯是,拉流时先加个 -timeout 10000000(单位微秒),防止网络不好时 FFmpeg 一直卡着不动。

直播转码:从「源」到「端」的桥梁

直播转码,说白了就是把一路输入流,转成多种分辨率、多种码率、多种格式的输出。为什么要转?因为观众的网络和设备千差万别。

你想想看,有人用 5G 手机看 4K,有人用 2G 网络看 360p。如果只推一路流,那体验肯定不行。

转码的核心流程

  1. 解码:把输入的压缩数据(H.264/H.265)解成原始 YUV 帧。
  2. 滤镜处理:缩放、裁剪、加水印、调色等。
  3. 编码:重新压缩成目标分辨率/码率的流。
  4. 封装:输出为 FLV、TS、MP4 等格式。

FFmpeg 实现多路转码的经典命令:

ffmpeg -i rtmp://input/live/stream \
  -c:v libx264 -b:v 2M -s 1280x720 -c:a aac -b:a 128k -f flv rtmp://output/live/720p \
  -c:v libx264 -b:v 1M -s 854x480 -c:a aac -b:a 96k -f flv rtmp://output/live/480p \
  -c:v libx264 -b:v 500k -s 640x360 -c:a aac -b:a 64k -f flv rtmp://output/live/360p

这条命令同时输出三路流:720p、480p、360p。每个输出都独立编码,CPU 压力很大。我建议用硬件编码(-c:v h264_nvenc-c:v h264_vaapi)来减轻负担。

实战技巧:如果服务器性能有限,可以用 -filter_complex 先缩放,再编码,避免重复解码。比如:-filter_complex "[0:v]split=3[v1][v2][v3];[v1]scale=1280:720[v1out];[v2]scale=854:480[v2out];[v3]scale=640:360[v3out]"

直播流处理的核心逻辑图

下面这张图,是我自己总结的直播流处理全链路。从推流端到播放端,每一步都离不开 FFmpeg。

推流端 摄像头/编码器 RTMP/RTSP FFmpeg 转码服务器 拉流 → 解码 → 滤镜 → 编码 多分辨率/多码率输出 HLS/RTMP CDN 分发 HTTP/HLS 观众 协议对比 RTMP TCP长连接,低延迟(1-3s) 适合推流,浏览器不原生支持 RTSP UDP传输,极低延迟(<0.5s) 适合安防/会议,防火墙不友好 HLS HTTP切片,高延迟(6-30s) 兼容性最好,CDN友好 直播转码流程 输入流 解码 滤镜/缩放 编码 输出流

实战中的几个坑

最后,分享几个我踩过的坑,希望能帮你省点时间。

  • 推流断连:RTMP 推流时,如果网络闪断,FFmpeg 不会自动重连。我一般写个脚本循环检测,或者用 -reconnect 1 参数(部分版本支持)。
  • 音视频不同步:转码时如果用了 -vsync-async 参数不当,很容易导致音画不同步。我建议尽量用 -c copy 保持原始时间戳,除非必须转码。
  • HLS 切片太大:默认 HLS 切片时长是 2 秒,但如果你不设置 -hls_time,有些版本会切出 10 秒的片,导致延迟飙升。我习惯设成 -hls_time 2
  • RTSP 拉流超时:摄像头 RTSP 流如果断掉,FFmpeg 会一直等。加个 -stimeout 10000000(10秒超时),超时后自动退出,方便脚本重启。
一句话总结:直播流处理的核心就是「推得稳、转得好、播得顺」。协议选对,参数调好,FFmpeg 就是你手里最趁手的工具。
公众号:蓝海资料掘金营,微信deep3321