4. 推流协议对比:RTMP、SRT、WebRTC、HLS、LL-HLS 的优缺点及适用场景
做流媒体这么多年,我经常被问到同一个问题:到底该用哪个协议?说实话,没有银弹。每个协议都有自己的脾气,选错了,卡顿就是家常便饭。这一章,我把几个主流协议掰开揉碎讲清楚。
核心观点:协议选择 = 延迟要求 × 网络环境 × 终端覆盖。没有最好的协议,只有最合适的。
4.1 RTMP:老将不死,但已显疲态
RTMP 是 Adobe 在 2009 年推出的协议。说实话,它已经 15 岁了。但直到今天,大部分推流软件默认还是 RTMP。为什么?因为它简单、稳定、生态成熟。
RTMP 基于 TCP,走的是长连接。推流端和服务器之间一直保持连接,数据源源不断送过去。延迟大概在 2-5 秒,对于非互动场景完全够用。
我的经验:RTMP 最大的坑是握手慢。TCP 三次握手 + RTMP 握手,加起来要 2-3 个 RTT。如果用户网络质量差,光握手就要好几秒。我曾经遇到一个项目,用户用 4G 网络推流,RTMP 握手超时率高达 15%。后来换成 SRT,问题就解决了。
| 特性 | RTMP |
|---|---|
| 传输层 | TCP |
| 延迟 | 2-5 秒 |
| 弱网表现 | 差(TCP 丢包重传导致延迟飙升) |
| 浏览器支持 | 不支持(需 Flash 或转码) |
| 适用场景 | 推流到服务器、OBS 推流、传统直播 |
注意:RTMP 默认只支持 H.264 和 AAC。如果你要用 H.265 或 Opus,得自己封装。另外,RTMP 的 FLV 封装格式在浏览器端无法直接播放,必须转成 HLS 或 MSE。
4.2 SRT:弱网环境下的救星
SRT 是 Haivision 在 2017 年开源的协议。我第一次用 SRT 是在一个跨国直播项目里,推流端在非洲,服务器在新加坡。RTMP 根本跑不动,延迟飙到 30 秒以上。换成 SRT 后,延迟稳定在 3 秒左右。
SRT 基于 UDP,但加了 ARQ(自动重传请求)和 FEC(前向纠错)。说白了,它知道网络会丢包,所以提前做了准备。丢包时,SRT 会快速重传,而不是像 TCP 那样傻等超时。
# SRT 推流命令示例
ffmpeg -i input.mp4 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-f mpegts 'srt://your-server:1234?mode=caller&latency=200'
| 特性 | SRT |
|---|---|
| 传输层 | UDP + ARQ/FEC |
| 延迟 | 0.5-3 秒(可配置) |
| 弱网表现 | 优秀(丢包 20% 仍可工作) |
| 浏览器支持 | 不支持(需转码) |
| 适用场景 | 卫星传输、跨国推流、弱网环境 |
关键参数:SRT 的 latency 参数决定延迟上限。设 200ms 就是 200ms 内没收到重传包就放弃。设得越小,延迟越低,但丢包率会上升。我一般建议设 500ms 作为起点。
4.3 WebRTC:实时互动的王者
WebRTC 是 Google 在 2011 年开源的协议。它的目标很明确:让浏览器之间能直接视频通话。延迟能做到 200ms 以内,这是 RTMP 和 HLS 想都不敢想的。
但 WebRTC 的代价是架构复杂。你需要部署 STUN/TURN 服务器处理 NAT 穿透,还需要维护信令服务器协调连接。而且 WebRTC 的编码器默认是 VP8/VP9,虽然现在也支持 H.264,但兼容性还是有点麻烦。
避坑指南:我曾经在一个项目中直接用 WebRTC 做万人直播,结果服务器直接崩了。WebRTC 是 P2P 架构,每个观众都会和推流端建立独立连接。万人直播意味着推流端要维护 10000 个连接,CPU 和带宽都扛不住。后来我们改用 SFU(选择性转发单元)架构,才解决了问题。
| 特性 | WebRTC |
|---|---|
| 传输层 | UDP + ICE/DTLS/SRTP |
| 延迟 | 100-500ms |
| 弱网表现 | 良好(内置拥塞控制) |
| 浏览器支持 | 原生支持(Chrome/Firefox/Safari) |
| 适用场景 | 视频会议、互动直播、远程医疗 |
4.4 HLS:兼容性之王
HLS 是 Apple 在 2009 年推出的协议。它的思路很简单:把视频切成一个个小片段(通常是 6 秒一个),然后通过 HTTP 下载播放。因为用的是 HTTP,所以任何 CDN 都能支持,防火墙也不会拦截。
但 HLS 的延迟是个硬伤。传统 HLS 的延迟在 10-30 秒,因为要等整个片段下载完才能播放。你想想看,主播说「大家好」,观众 10 秒后才听到,这互动体验基本为零。
# HLS 切片示例(使用 ffmpeg)
ffmpeg -i input.mp4 \
-c:v libx264 -c:a aac \
-hls_time 6 -hls_list_size 10 \
-hls_segment_filename 'segment_%03d.ts' \
playlist.m3u8
| 特性 | HLS |
|---|---|
| 传输层 | HTTP(TCP) |
| 延迟 | 10-30 秒 |
| 弱网表现 | 良好(自适应码率) |
| 浏览器支持 | 广泛(通过 MSE) |
| 适用场景 | 点播、OTT、大规模直播 |
注意:HLS 的 .ts 片段文件会占用存储空间。如果直播 24 小时,每个片段 6 秒,一天就是 14400 个文件。记得配置清理策略,否则磁盘很快会爆。
4.5 LL-HLS:Apple 的救赎
LL-HLS(低延迟 HLS)是 Apple 在 2019 年推出的改进版。它把片段切得更小(0.5-1 秒),并且支持部分下载(Partial Segments)。说白了,就是不用等整个片段下载完,下载一部分就能开始播放。
LL-HLS 的延迟能做到 2-5 秒,已经接近 RTMP 的水平了。而且它保留了 HLS 的兼容性优势,所有支持 HLS 的设备都能用,只是低延迟特性需要客户端支持。
我的建议:如果你做的是 Apple 生态内的直播(比如 iOS 应用),LL-HLS 是个不错的选择。但要注意,LL-HLS 对服务器和 CDN 的要求更高,因为片段更小,HTTP 请求更频繁。我见过一个项目,LL-HLS 的请求量是传统 HLS 的 10 倍,CDN 费用直接翻番。
| 特性 | LL-HLS |
|---|---|
| 传输层 | HTTP(TCP) |
| 延迟 | 2-5 秒 |
| 弱网表现 | 良好(自适应码率) |
| 浏览器支持 | 有限(Safari 原生,Chrome 需插件) |
| 适用场景 | Apple 生态、低延迟 HLS 需求 |
4.6 选型总结
说了这么多,到底怎么选?我整理了一个对比表,方便你快速决策。
| 协议 | 延迟 | 弱网 | 浏览器 | 复杂度 | 推荐场景 |
|---|---|---|---|---|---|
| RTMP | 2-5s | 差 | ❌ | 低 | 推流到服务器 |
| SRT | 0.5-3s | 优秀 | ❌ | 中 | 弱网推流 |
| WebRTC | 0.1-0.5s | 良好 | ✅ | 高 | 实时互动 |
| HLS | 10-30s | 良好 | ✅ | 低 | 点播/大规模直播 |
| LL-HLS | 2-5s | 良好 | 部分 | 中 | Apple 生态 |
我的个人习惯:推流端用 SRT,播放端用 HLS。SRT 保证推流稳定,HLS 保证播放兼容。中间加一个转码服务器做协议转换。这套架构我用了 3 年,基本没出过大问题。