
做音视频开发这么多年被问得最多的一个问题就是WebRTC、HLS、HTTP-FLV 到底选哪个问的人从刚入行的前端到做直播平台的后端再到给客户做 POC 验证的集成商都有。坦白讲这三个东西虽然名字里都带“流”但设计目标和适用场景完全不是一回事。选错方向的代价也不一样选错延迟控不住选错兼容性砸口碑选错连 CDN 成本都扛不住。这篇文章我想用从业者的视角把三者的本质区别、底层原理、选型决策和实操坑一次讲透适合所有正在做直播、视频会议、互动课堂、监控上墙等音视频相关项目的同学。即使你用的是别人封装好的 SDK也需要理解这几个协议背后的取舍才能真正做好技术选型和问题排查。1. 先捋清楚这三个协议到底在解决什么问题做技术选型别急着比参数得先搞清楚每个协议是冲着什么问题来的。如果只记结论遇到实际场景还是会蒙。1.1 设计目标一个要实时通话一个要“随时看回放”一个要“跑在网页里”HTTP-FLV 最早是靠 Flash 流媒体生态起来的用 FLV 格式包装音视频数据走 HTTP 传输。后来 Flash 死了但 live 流媒体需求还在HTTP-FLV 因为实现简单、切片延迟可控被很多直播平台捡起来继续用。它本质上是一个“HTTP 长连接一点一点拉数据”的方案拿到一点播一点所以能做到秒级延迟但播放器需要处理连续的流式数据。HLS 的核心设计目标是“兼容性”和“可靠分发”。苹果为了让 Safari 不用装插件就能播放视频发明了 m3u8 索引加 TS/MP4 分片的方式把所有媒体切成小文件播放器像读网页一样一个个下载、顺序播放。因为切片的粒度通常是 2 到 6 秒再加上播放器为了保证流畅会主动加缓冲延迟天然就高。但只要 HTTP 缓存和 CDN 能做得好的地方HLS 几乎都能跑。WebRTC 是另一个维度的东西。它的目标是浏览器与浏览器之间直接进行音视频实时通信不是“播一段流”而是“互相传送连续的音视频”。所以它在 UDP 之上做了一整套抗丢包、抖动缓冲、回声消除、带宽估计的机制追求几百毫秒内的互动体验。它的复杂度也明显高于前两者信令、ICE 穿透、媒体协商一个都不能少。用一个生活化的类比HLS 是网盘存好的压缩包你下载完解压不快但稳HTTP-FLV 是打开一个持续更新的网页边刷边看简单直接WebRTC 是打电话你必须保证双方都在线、线路畅通还要实时处理嘈杂环境。这三者的设计基因不同决定了它们后续的各种表现。1.2 典型场景从视频会议到直播带货看到这里你应该明白没有谁一定比谁高级只有谁更适合什么场景。WebRTC 几乎统治了互动场景视频会议、连麦直播、互动小班课、远程桌面、屏幕共享、在线问诊。这些场景的共同点是“人需要在里面交流”延迟超过 1 秒就很难受而且通常需要双向音视频流。HLS 最适合的是“大规模观看、兼容性优先”的场景视频网站点播、电视剧综艺、OTT 大屏直播、演唱会慢直播、监控录像回放。观看者只关心“能不能秒开、是否卡顿”不太在乎那几秒延迟。并且 HLS 天然分片支持在 HTTP/CDN 上大规模分发几百万并发也能扛。HTTP-FLV 则卡在中间想要“还能接受的延迟”又不想上 WebRTC 那么重。早期直播平台最常见的方案就是 RTMP 推流 HTTP-FLV 播放配合成熟播放器做低延迟直播、体育赛事、电商直播、在线教育大班课等。移动端 App 里有成熟的 ijkplayer/ExoPlayer 方案支持浏览器里用 flv.js 也能播放。业界常说一句口水话能开会的选 WebRTC只能看的选 HLS想边看边要求低延迟就选 HTTP-FLV。话糙理不糙这就是第一层选型逻辑。2. 技术底层拆解延迟到底差在哪封装和传输分别做了什么想彻底明白这三者的差别只看应用场景还不够必须知道它们在传输层和封装层分别做了什么。很多面试题也喜欢从这两个角度考。2.1 传输层UDP 和 TCP 的性格差异WebRTC 的绝大多数媒体通道建立在 UDP 之上具体是经过 DTLS 加密的 SRTP。UDP 不做可靠传输和顺序保证丢包了就丢了但这恰恰是实时通信需要的数据必须尽快发出去越快越好。如果因为网络拥塞就重传就会越积越多通话直接没法用。为了避免丢包WebRTC 维护了一整套估计机制并在应用层通过 NACK 重传关键包、通过 FEC 恢复部分丢失数据再把抖动通过 Jitter Buffer 吸收掉。HLS 和 HTTP-FLV 却都跑在 TCP 之上。TCP 的可靠传输和拥塞控制确实好但也引入了队头阻塞问题一个包丢了或乱序后续所有包都得等。对于实时性要求极高的通话场景TCP 并不友好这也是为什么很多 WebRTC 团队宁可深度优化 UDP 也不换 TCP 的原因。不过对播放场景来说TCP 带来的稳定性能让播放器更流畅尤其是在弱网下TCP 重传反而能保证画面不花、不破音。一句话总结传输差异WebRTC 选择用“无序不可靠但快”的通道再用上层智能去弥补HLS/HTTP-FLV 躲在 HTTP 的可靠传输里换来稳但慢半拍。2.2 封装与索引HLS 的切片、HTTP-FLV 的 Tag、WebRTC 的 RTPHLS 的核心是“分片 索引”。编码器生成视频流后服务端会把连续流按固定时间切成许多小的媒体片段例如每 2 秒或 6 秒切一次常用 TSMPEG-TS格式现在也有 fMP4。同时生成一个 m3u8 索引文件像目录一样列出所有分片的名字和顺序。播放器先下载索引再按顺序拉取分片。因为每个分片都是一个独立的 HTTP 请求CDN 缓存和负载均衡做起来非常顺手。HTTP-FLV 则是把 FLV 格式的流用 HTTP 承载。FLV 内部是由一个个 Tag 组成每个 Tag 携带音频、视频或脚本数据。播放器建立 HTTP 连接后服务端持续把 Tag 写进响应体播放器在客户端“吞掉”这些 Tag实时渲染。因为不需要切片和索引延迟可以做到很低但坏处是单个连接的生命周期比较长服务端需要维护更多 TCP 连接断流重连也需要额外处理。WebRTC 走的是 RTP 协议。每个音视频帧被拆成若干个 RTP 包携带时间戳、序列号、负载类型等信息专门的 RTCP 包用于统计丢包、抖动、往返时间并反馈给发送端控制码率。媒体协商用 SDP 描述音视频格式、编解码能力、传输候选地址等。可以说 WebRTC 是“每一条连接都是实时会话”而不是“拉一个文件流”。封装上的差异也解释了为什么 WebRTC 能随时切换清晰度、动态适应带宽而 HLS 切换码率则需要等切片边界HTTP-FLV 甚至没有原生的多码率切换支持。2.3 延迟的账这么算为什么 HLS 总是最慢我们经常说 HLS 延迟高到底高在哪里可以把延迟账拆开算首片延迟 服务端切片时机 CDN 缓存 播放器缓冲 播放器安全缓冲。假设服务端每 6 秒切一个 TS 分片那从客户端请求到服务端生成完当前分片可能就得等最多 6 秒。同时播放器为了保证流畅往往会预下载至少 3 个分片后再起播这又是十几秒。如果 CDN 节点缓存策略还比较保守会进一步放大延迟。所以传统 HLS 做到 10 秒以内就算是优化得不错了。很多直播平台对 HLS 的 SLA 是“延迟在 12~15 秒内可接受”。HTTP-FLV 没有切片等待服务端一边收流一边转发播放器建立连接就能实时收到数据延迟主要来自服务端缓冲区、TCP 传输、播放器解码缓冲一般 2~5 秒。WebRTC 因为从采集、编码、传输到渲染全过程都在为实时性优化端到端可以做到 300~800 毫秒音画同步也会更加严格。明白了延迟的构成你就能理解为什么有人会为了把 HLS 延迟从 10 秒压到 3 秒而做 LL-HLS它不是把切片变成 FLV而是把切片切得更小、支持按字节部分下载。这个后面第 5 节再展开。3. 选型指南别再背八股按这四问来定我这人不喜欢列一堆“WebRTC 好、HLS 好”的结论因为脱离场景谈优劣没意义。下面给出一套可执行的选型流程你按顺序问自己四个问题基本能逼出答案。3.1 四个关键问题直接把方案逼出来第一个问题到底是单向观看还是双向互动如果是视频会议、连麦、在线答疑这类需要双向甚至多路流的场景直接上 WebRTC别浪费时间考虑 HLS 和 HTTP-FLV。它们天生适合单向分发做双向要绕很大弯子。第二个问题延迟容忍度是多少如果端到端超过 800 毫秒就没法用WebRTC如果能接受 2~5 秒HTTP-FLV如果 10 秒以上都无所谓HLS。这里要特别提醒不要高估用户对延迟的容忍度电商直播里主播说“三二一上链接”观众 5 秒后才看到这就很尴尬但在短视频回放场景中延迟对体验几乎没有影响。第三个问题你的目标终端和分发型式是什么WebRTC 在现代浏览器和 App 上支持很好但需要信令服务、STUN/TURN在大规模分发时需要和 CDN 配合HTTP-FLV 在桌面浏览器和 Android 平台友好但在 iOS 的 Safari 上没有原生支持必须用 flv.js、或用 HLS 替代HLS 几乎能跑在所有能看视频的终端上包括各类电视、机顶盒、小程序。如果你的观众主要在微信小程序、电视机顶盒、老 iOS 设备HLS 会是稳妥之选。第四个问题团队有多大的维护意愿和成本WebRTC 不是一个“只要引入 SDK 就能跑好”的协议它涉及网络穿透、弱网优化、SFU 选型、带宽估计等问题后期调优是个大工程。HTTP-FLV 和 HLS 相对简单推流端用 ffmpeg 或 SRS播放端用成熟播放器CDN 也便宜。但 HTTP-FLV 在弱网下的表现一般HLS 在大规模直播中的延迟优化也比较麻烦。这四个问题想清楚选型方向基本就锁定了。如果四个问题回答完还是有多个候选再看下一节的具体对比。3.2 优缺点对比没有完美的协议只有合适的协议我做了一张常用对比表方便你们在设计评审时直接用。维度WebRTCHLSHTTP-FLV端到端延迟300~800ms传统 8~15sLL-HLS 1~3s2~5s传输层UDP 为主SRTPTCPTCP封装格式RTP/SCTPTS/fMP4 分片FLV Tag 流双向互动原生支持不支持不支持浏览器兼容Chrome/Firefox/Edge 良好Safari 部分支持几乎所有 H5 播放器都支持桌面浏览器 flv.js 支持iOS Safari 不支持原生播放移动端需要封装 SDK支持较好iOS 原生支持好Android 需要播放器Android 使用 ijkplayer/ExoPlayer 扩展iOS 需启用播放器内核CDN 分发成本高需要专业 SFU 和级联非常成熟HTTP 缓存友好支持较好但长连接对边缘节点有一定压力弱网抗性强有丢包抑制/带宽估计中靠 TCP 重传中弱连续流断网易卡实现复杂度高低低多码率自适应支持动态码率/分辨率切换支持多码率切换HLS原生态并不支持需借助多路流切换这张表的核心信息是WebRTC 把复杂度和成本放在“客户端服务器”换来最低延迟和最好互动体验HLS 把复杂度放在“切片与索引”换来无敌兼容性和分发规模HTTP-FLV 则是一个“既想要低延迟、又不想太复杂”的折中方案但它在跨端兼容上有隐患。3.3 按场景划分的推荐组合上面表格是理论实际项目中往往是组合使用。我按常见场景给几套可以直接落地的组合视频会议/连麦客户端 WebRTC 服务端 SFUJanus / mediasoup / LiveKit 都行 信令服务。SFU 负责多路转发、录制、合流信令用 WebSocket 或自定义协议。电商直播/秀场直播主播端用 WebRTC 推流来降低上行延迟服务端做转封装下行观众端选 HTTP-FLV浏览器/Android App或 HLSiOS/小程序。这套组合现在比较主流。监控大屏/安防直播通常对实时性要求高但观众是单向观看优先 HTTP-FLV如果网络环境太差降级到 HLS。点播/回放/OTT直接用 HLS不用纠结成本最低兼容性最好。在线课堂大班课讲师推流用 WebRTC几百上千个学生端用 HTTP-FLV/HLS 收流配合 WebSocket 做消息和课件同步。这些组合不是拍脑袋而是兼顾延迟、兼容性和分发成本的结果。记住协议是工具不是信仰。4. 实操验证与踩坑记录三种协议怎么快速上手选型最终要落实到实验。我建议你花一两天时间把三种协议的 demo 都跑一遍亲眼看延迟和兼容性比读十篇文章都管用。下面分享一套我常用的快速验证方案和一些真实踩坑经验。4.1 WebRTC浏览器里跑通一个最小 Demo现在跑 WebRTC demo 最简单打开一个支持 WebRTC 的浏览器用本地信令交换一下 SDP 就行。下面是一个极简到不能再简的本地点对点 demo 概念// 本地模拟两个 RTCPeerConnection 直接交换 SDP实际项目用信令服务器 const pc1 new RTCPeerConnection(iceServers); const pc2 new RTCPeerConnection(iceServers); navigator.mediaDevices.getUserMedia({ video: true, audio: true }) .then(stream { stream.getTracks().forEach(track pc1.addTrack(track, stream)); pc1.createOffer().then(offer { pc1.setLocalDescription(offer); pc2.setRemoteDescription(offer); pc2.createAnswer().then(answer { pc2.setLocalDescription(answer); pc1.setRemoteDescription(answer); }); }); }); // 注意以上代码仅供理解流程生产环境必须走信令服务器和 ICE 候选交换实际项目里媒体协商需要信令服务器中转 SDPICE 候选也要通过信令交换。如果你只是在本机验证直接调用两个 pc 交换是能跑的但一旦跨网络就会遇到 NAT 穿透问题这时候需要部署 STUN/TURN 服务器最常用的开源方案是 coturn。切记不要在公网环境裸跑 TURN最好加上认证和传输层安全。另外很多人不知道WebRTC 在高版本浏览器中会启用 mDNS 防泄漏策略默认不再暴露本机真实 IP。这对隐私是好事但也导致一些老旧的信令服务无法正确收集 ICE 候选排查问题时会觉得莫名奇妙。如果你遇到“localhost 下总是正常、局域网内就不行”的情况先检查一下 iceServers 配置和 mDNS 限制。再有就是 3A 问题也就是回声消除 AEC、噪声抑制 NS、自动增益 AGC。WebRTC 内部的音频处理模块默认会开启这些但很多团队把音频采集封进 SDK 后没注意关闭或配置结果出现“对方听到自己的回声”或“音量忽大忽小”。如果你用自定义采集一定要确认 AudioProcessing 模块是否正确接入。最后提一句关于关闭 WebRTC 的隐私设置有些用户担心裸连 WebRTC 会暴露内网 IP会在浏览器层面禁用 WebRTC或者用 WebRTC leak prevent 之类的扩展插件。这会影响你基于 WebRTC 的应用所以如果需要检测用户是否启用了 WebRTC最好提供 HTTP-FLV/HLS 的降级播放方案。这个也是很多音视频客服团队会遇到的售后问题。4.2 HTTP-FLV用 SRS 或 Nginx 搭建一个能看的直播流HTTP-FLV 验证起来最简单。假设你已经有一台 Linux 服务器装了 docker直接跑 SRSdocker run -d -p 1935:1935 -p 8080:8080 ossrs/srs:5然后推流ffmpeg -re -i sample.mp4 -c copy -f flv rtmp://localhost:1935/live/stream播放端用浏览器打开 flv.js 的官方 demo地址写http://localhost:8080/live/stream.flv整个过程大概几分钟就能看到画面。延迟能看到大概 2~4 秒具体取决于播放器的缓冲设置和服务端 gop cache 的设置。如果推流是摄像头实时采集建议设置编码器关键帧间隔GOP为 2 秒左右。很多人推流时不设 GOP默认一关键帧可能好几秒才出现结果播放端起播要等很久甚至黑屏。一般建议在编码器上把 GOP 设成 2 秒。4.3 HLS手动切片生成测试流顺便排掉两个老坑HLS 也是用 ffmpeg 就能生成ffmpeg -re -i sample.mp4 -c:v libx264 -c:a aac -f hls -hls_time 6 -hls_list_size 0 -hls_segment_filename segment_%04d.ts playlist.m3u8这条命令会生成一个 m3u8 索引文件和一系列 TS 切片。你用任意 H5 播放器访问 playlist.m3u8 即可播放。但要做低延迟 HLS 的话切片时要把 -hls_time 设到 1~2 秒并加上 -hls_flags independent_segments 等参数让播放器尽快起播。公共测试流地址网上确实很多但不少已经过期最稳的方法就是自己生成或者找开源社区长期维护的测试流仓库。踩坑点之一播放 HLS 时如果发现起播后前几秒有花屏多半是切片没有对齐关键帧。HLS 对切片的完整性要求严格最好不要任意切应该让切片边界落在关键帧上。ffmpeg 切片默认会强制关键帧对齐但如果你用其他工具生成一定要检查每个分片是否从关键帧开始。踩坑点之二HLS 测试时发现延迟比预期高很多先看播放器缓存策略。很多播放器在默认策略下会缓存好几个分片才起播。你可以把播放器的 liveSyncDuration 和 liveMaxLatencyDuration 调小能明显降低延迟。4.4 兼容性速查表终端WebRTCHTTP-FLV (flv.js)HLS (hls.js/原生)Chrome 桌面版很好很好很好Firefox很好很好很好Safari/iOS部分支持iOS 14.5 以后较好不支持原生播放原生支持Android Chrome很好flv.js 需要依赖 MSE部分旧机型不支持hls.js 或 ExoPlayer 均可微信小程序/内嵌 WebView需要原生 SDK 或小程序 live-player通常不支持使用 video 标签支持智能电视/OTT少数支持通常不支持原生支持这张表是我实际业务中最常遇到的情况也是很多技术方案讨论的起点。建议在写方案时直接把终端矩阵列出来再用协议去填坑。5. 混合架构与演进当前直播平台的常见做法如果你只做单协议选型那前面的内容已经够用。但真实的大型项目极少只用一种协议而是多种协议配合形成混合架构。这里聊一下我看到的实际用法和几个值得关注的技术演进点。5.1 为什么主流方案是“WebRTC 上行 HTTP-FLV/HLS 下行”现在很多平台都采用“主播端 WebRTC 上行观众端 HTTP-FLV/HLS 下行”的混合架构。原因很现实主播上行对延迟和互动要求极高主播要看到弹幕、连麦、PK不能接受几秒延迟观众下行则要兼顾几百万并发、复杂终端和 CDN 成本。上行用 WebRTC 的好处是它能通过带宽估计和码率自适应在弱网上尽量保持通话流畅。比如 WebRTC 内部会根据 RTT 和丢包动态调整发送码率类似 LossBasedBweV2 这类新带宽估计算法也在不断被引入。这些细节普通业务团队不用背但你要知道选 WebRTC 推流意味着网络抖动时画面质量会动态变化而不是傻乎乎以固定码率推流。下行用 HTTP-FLV 或 HLS 的好处是CDN 生态太成熟了。CDN 节点对 HTTP 流做缓存和负载均衡非常省心连传统 HTTP 预取都能用扩容也只是加节点。而且如果用 HLS终端兼容性几乎一网打尽。媒体服务器端负责把 WebRTC 推上来的流重新转封装成 FLV 或 HLS如果已经有 RTMP/CDN 链路也可以用 SRS 或 MediaMTX 做协议转换再送到原有分发网络去。一套架构下来互动、规模、成本都照顾到。5.2 WebRTC 与 LL-HLS 带来的新变化技术永远是流动的。最近几年有两个变化比较值得关注。一是 LL-HLS低延迟 HLS逐渐落地它通过极小分片和按字节范围请求把 HLS 延迟从十几秒压到了 1~3 秒。如果你对延迟要求介于“可接受”和“实时”之间以前只能选 HTTP-FLV现在也可以考虑 LL-HLS尤其是在苹果生态下推 LL-HLS兼容性会更好。但 LL-HLS 对播放器和服务器的实现要求较高传统 HLS 播放器普遍不支持需要专门适配。二是 WebRTC 本身的弱网能力在增强。之前提到的 LossBasedBweV2 就是一个典型的带宽估计算法演进方向它对基于丢包率的码率调节做了更精细的建模让视频会议在 4G/弱 Wi-Fi 下更不容易糊。对开发者来说这不是“换协议”的理由而是“为什么 WebRTC 值得长期投入”的背景。将来会有更多实时音视频场景开始用 WebRTC 做上行接入甚至部分下行观看场景也会逐步向低延迟 WebRTC 分发演进。从我个人的实操体会来看选型时不要被这些新概念冲昏头。如果你的业务还在验证阶段最稳妥的做法是选择一套能快速试错的方案先用 SRS 同时支持 WebRTC 上行和 HTTP-FLV/HLS 下行几天内就能搭出全链路 demo。等验证完业务模型再根据上面那些延迟、兼容性和成本账去精调协议和服务器配置。这种迭代方式踩坑最少也最容易说服团队和客户。