为什么视频直播平台实际上在用 TCP 而非 UDP?

B站、抖音、YouTube Live 等大型直播平台,主要使用的是基于 TCP 的 HTTP 协议来分发直播流。而"视频直播用 UDP"这句话并不是错的,只是它描述的是另一类场景。要彻底搞清楚这件事,我们需要从几个层面来拆解。


一、先搞清楚:UDP 和 TCP 在传输视频时的核心区别是什么

TCP 的特点

TCP 是一种可靠传输协议。它有三个关键机制:

  1. 保证数据完整到达:每发一个数据包,接收方都要回复确认(ACK)。如果发送方没有收到确认,就会重新发送这个包。
  2. 保证数据顺序正确:即使网络中数据包到达的顺序是乱的,TCP 也会在接收端把它们按正确顺序重新排列好,再交给上层应用。
  3. 拥塞控制:TCP 会根据网络状况动态调整发送速度,网络拥堵时主动降速,避免雪崩。

这三个机制意味着什么?意味着数据一定是完整的、有序的,但代价是——如果某个包丢了,后面所有的包都要等着,直到丢的那个包被重传并补回来。这个现象叫做队头阻塞(Head-of-Line Blocking)。

对于视频传输来说,队头阻塞会带来额外的延迟。

UDP 的特点

UDP 是一种不可靠传输协议。它的设计哲学极其简单:

  1. 不保证数据到达:发出去就不管了,丢了就丢了。
  2. 不保证数据顺序:包到了就到了,先到的先处理。
  3. 没有拥塞控制:应用想发多快就发多快(当然网络本身可能会丢包)。

这意味着 UDP 几乎没有额外延迟,但数据可能不完整。

关键问题来了:视频传输到底能不能容忍丢包?

这取决于场景。这正是理解这个问题的核心所在。


二、两种完全不同的"直播"场景

人们笼统地说"直播用 UDP",是因为把两种截然不同的场景混在了一起。我们必须把它们分开。

场景一:实时互动通信

典型例子:

  • 微信视频通话
  • Zoom / 腾讯会议等视频会议
  • 游戏中的语音聊天
  • 连麦互动(主播和主播之间、主播和观众之间)

这类场景的核心需求是极低延迟,通常要求端到端延迟在 100~500 毫秒以内。为什么?因为这是双向交流。你说一句话,对方要立刻听到并回应。如果延迟超过 500 毫秒,对话就会变得非常别扭,互相抢话。

在这种场景下:

  • 丢了几个包?没关系。画面花一下、声音卡一下,人类大脑可以脑补。
  • 但是如果因为重传一个丢失的包,导致整个画面卡住 200 毫秒等待,那是不可接受的——对方说的话你过了半秒才听到,交流根本无法进行。

所以这类场景确实使用 UDP(或者基于 UDP 构建的协议,比如 RTP/RTCP、WebRTC 内部就跑在 UDP 上)。这里的逻辑是:宁可丢几帧画面,也绝不能有延迟。

场景二:大规模单向直播分发

典型例子:

  • B站直播
  • 抖音直播
  • YouTube Live
  • Twitch
  • 电视台网络直播

这类场景的特征是什么?

  1. 单向的:一个主播,几千、几万、甚至几百万观众同时观看。观众不需要和主播进行毫秒级的实时互动。
  2. 延迟容忍度相对高:大多数观众可以接受 3~10 秒的延迟。你看 B 站直播时,弹幕里有人说"进球了!",你可能两三秒后才看到画面——这完全不影响你的观看体验。
  3. 画质要求高:观众希望看到清晰、流畅、不花屏、不卡顿的画面。丢包导致的花屏和音画不同步是不可接受的。
  4. 规模极大:一个热门直播间可能有几百万人同时观看。

在这种场景下,优先级完全反过来了:宁可多几秒延迟,也绝不能丢数据导致花屏卡顿。

这就是为什么大规模直播分发使用 TCP。


三、m3u8 + m4s 到底是什么?——HLS 协议详解

我们在 B 站直播后台,可以看到许多 m3u8 和 m4s,这是 HLS(HTTP Live Streaming) 协议的组成部分。这是苹果公司在 2009 年提出的一个直播/点播协议。我们来拆解它的工作原理。

基本思路:把直播流切成一段段小文件

HLS 的核心思想极其朴素:

  1. 主播端把连续的视频流实时编码。
  2. 服务器端把这个连续的视频流切成一小段一小段的文件,每段通常是 2~6 秒长。
  3. 服务器同时维护一个播放列表文件,告诉播放器:“目前最新的几个视频片段是什么,去哪里下载它们。”
  4. 观众端的播放器定期去请求这个播放列表,发现有新片段,就去下载、解码、播放。

m3u8 文件:播放列表

m3u8 本质上是一个文本文件,后缀名 .m3u8。它的内容类似这样(简化示意):

#EXTM3U
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:12001

#EXTINF:4.0,
segment_12001.m4s
#EXTINF:4.0,
segment_12002.m4s
#EXTINF:4.0,
segment_12003.m4s

这个文件在说什么?

  • 每个片段大约 4 秒长。
  • 当前最新的三个片段分别是 12001、12002、12003。
  • 播放器应该去下载这三个文件来播放。

播放器每隔几秒就会重新请求一次这个 m3u8 文件,看看有没有新的片段出现。如果出现了 segment_12004.m4s,它就去下载这个新片段,接着播放。

这就是直播的实现方式——不断追踪最新的片段。

m4s 文件:视频片段本身

m4s 是 fMP4(Fragmented MP4) 格式的片段文件。每个 m4s 文件包含了几秒钟的视频和音频数据,编码格式通常是 H.264 或 H.265(视频)和 AAC(音频)。

播放器下载这些 m4s 文件后,解码播放,一个片段接着一个片段,观众就看到了连续的直播画面。

为什么这套方案全部跑在 HTTP/TCP 上?

注意看:播放器获取 m3u8 和 m4s 的方式,就是普通的 HTTP 请求——跟你在浏览器里下载一个网页、一张图片,本质上没有任何区别。

这意味着:

  • m3u8 文件 → 一次 HTTP GET 请求
  • 每个 m4s 文件 → 一次 HTTP GET 请求

HTTP 协议跑在 TCP 上。你看到的 h2 就是 HTTP/2,它是 HTTP 协议的第二个大版本,底层仍然是 TCP。


四、为什么大规模直播选择了基于 TCP 的 HLS/DASH,而不用 UDP?

这不是一个技术能力的限制,而是一个深思熟虑的工程权衡。原因有以下几个层面:

原因一:CDN 基础设施的兼容性

这是最重要的原因。

CDN(Content Delivery Network,内容分发网络) 是大规模直播分发的基石。当 B 站一个直播间有 100 万人同时观看时,不可能让这 100 万人都去连同一台服务器——那台服务器会被瞬间压垮。

CDN 的做法是:在全国(甚至全球)部署成千上万的边缘节点服务器。北京的用户从北京的节点拿数据,广州的用户从广州的节点拿数据。每个节点只需要从上游拿一份数据,然后分发给它附近的成千上万的用户。

而全球现有的 CDN 基础设施(Akamai、Cloudflare、阿里云 CDN、腾讯云 CDN 等),几乎全部是基于 HTTP/TCP 构建的。它们天然支持缓存 HTTP 响应——m3u8 是一个 HTTP 响应,m4s 也是一个 HTTP 响应,CDN 节点可以轻松地缓存这些响应,分发给大量用户。

如果要用 UDP 来做大规模分发,要另起一套完全不同的分发基础设施。这在工程上的成本是极其巨大的。

HLS/DASH 之所以被设计成基于 HTTP 的,正是为了直接复用整个互联网已有的 HTTP/CDN 基础设施。这是一个天才级别的工程决策。

原因二:防火墙和网络穿透

互联网上的大量防火墙、NAT 设备、企业网关,对 UDP 流量非常不友好。很多网络环境会直接封掉 UDP 端口,或者对 UDP 流量做严格的限速。

但是 HTTP/TCP 流量?几乎不会被封。因为整个互联网的网页浏览都跑在 HTTP 上,没有哪个网络管理员会封掉 HTTP。特别是 HTTPS(HTTP over TLS),走的是 443 端口,这是全世界最"通行无阻"的端口。

用基于 HTTP 的直播协议,意味着在任何能上网的地方,都能看直播。这对于面向大众的直播平台来说至关重要。

原因三:大规模分发场景下,TCP 的"缺点"并不致命

前面说了,TCP 的核心缺点是队头阻塞带来的额外延迟。但在 HLS 的架构下,这个缺点被大幅缓解了:

  • HLS 本身就有 3~10 秒的固有延迟(因为要等一整个片段生成完毕才能开始下载)。在这个量级的延迟面前,TCP 重传一个丢失的包所增加的几十毫秒延迟,根本不值一提。
  • 每个 m4s 片段就是一次独立的 HTTP 下载。下载完一个片段后,播放器有充足的时间缓冲,TCP 的重传机制不会造成播放卡顿。

换句话说,HLS 的架构天然就不追求极低延迟,所以 TCP 的延迟代价在这里几乎没有感知。

原因四:数据完整性对观看体验至关重要

直播虽然是"实时"的,但观众看到的本质上是一段段编码后的视频文件。视频编码(如 H.264/H.265)的特点是:

  • 数据是高度压缩的。一个关键帧(I 帧)可能只占几十 KB,但它描述了整个画面。后续的帧(P 帧、B 帧)只记录与前一帧的差异。
  • 如果丢失了一个关键帧的数据,后面几十帧甚至上百帧都无法正确解码,屏幕上会出现大面积花屏、马赛克、色块乱飞的现象。
  • 如果丢失了音频数据,会出现爆音、断音。

在实时视频通话中,丢几个包还勉强能忍,因为对方就在跟你对话,你大脑可以补全。但在看直播时,如果画面频繁花屏、声音频繁断裂,观众会直接关掉——这是不可接受的用户体验。

TCP 保证了每一个字节都完整到达,视频解码器能正确工作,画面清晰流畅。

原因五:自适应码率非常容易实现

HLS 和 DASH 都天然支持自适应码率(ABR, Adaptive Bitrate)。

一个 m3u8 主播放列表可以包含多个不同码率的子播放列表:

#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080
1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720
720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360
360p.m3u8

播放器可以根据当前的网络带宽,动态切换到不同质量的流。网速好就看 1080p,网速差就降到 360p。由于每个片段都是独立的 HTTP 请求,切换码率只需要在下一个片段时请求不同码率的文件即可,非常优雅。

这在 UDP 的流式传输中实现起来要复杂得多。


五、那 UDP 在直播中完全不用了吗?并不是。

实际上,一个完整的直播系统中,UDP 和 TCP 往往同时存在,只是用在不同的环节。

一个典型直播系统的完整链路

主播端 → 推流 → 源站服务器 → CDN 边缘节点 → 观众端播放器

我们分段来看:

第一段:主播推流到源站

主播的推流软件(如 OBS)通常使用 RTMP(Real-Time Messaging Protocol) 协议将视频流推送到平台的服务器。RTMP 底层是 TCP。

但也有平台开始使用基于 UDP 的推流协议(如 SRT、RIST),因为主播的上行网络往往不稳定,用 UDP 可以减少推流端的延迟和卡顿。

第二段:源站到 CDN 边缘节点(内部分发)

平台内部的服务器之间传输视频流,可能使用各种私有协议,有些基于 TCP,有些基于 UDP,取决于平台的技术选型。

第三段:CDN 边缘节点到观众(最后一公里)

这一段就是浏览器里看到的——HLS 的 m3u8 + m4s,走 HTTP/2 over TCP。这是面向几百万观众的大规模分发,用的是 TCP。

但如果观众需要连麦互动(比如 B 站直播的连麦功能),这个连麦的音视频流通常会走 WebRTC,底层是 UDP。因为连麦需要极低延迟的双向通信。

所以实际情况是:

  • 大规模分发(一对多)→ TCP(HLS/DASH over HTTP)
  • 实时互动(一对一/少对少)→ UDP(WebRTC/RTP)

两者可以在同一个直播间里同时存在。


六、近年来的新趋势:试图在 TCP 和 UDP 之间找到平衡

传统 HLS 有 3~10 秒延迟,这对某些场景还是太高了(比如电商直播带货、体育赛事直播、互动抽奖)。于是业界在不断探索降低延迟的方案:

1. LL-HLS(Low-Latency HLS)

苹果推出的低延迟版 HLS。核心思路是:不等一整个片段生成完毕,而是把一个片段再拆分成更小的部分片段(partial segment),一生成就推送。可以把延迟降到 2~3 秒。底层仍然是 HTTP/TCP。

2. LL-DASH(Low-Latency DASH)

与 LL-HLS 类似的思路,应用于 DASH 协议。

3. 基于 QUIC 的方案

QUIC 是 Google 开发的传输协议,底层跑在 UDP 上,但在 UDP 之上自己实现了可靠传输、拥塞控制、加密等功能。HTTP/3 就是基于 QUIC 的。

QUIC 的一个重要优势是解决了 TCP 的队头阻塞问题:在 QUIC 中,不同的数据流(stream)是独立的,一个流的丢包不会阻塞其他流。

一些平台已经开始实验用 HTTP/3(基于 QUIC/UDP)来传输 HLS/DASH 的直播流。从网络层看,这确实走的是 UDP,但从应用逻辑看,它的行为更像 TCP——数据仍然是可靠的、有序的。

4. WebTransport

这是一个新兴的 Web API,允许浏览器通过 QUIC 进行低延迟的数据传输,可以选择可靠模式或不可靠模式。未来可能会用于浏览器中的超低延迟直播。


七、总结:为什么看到的直播是 TCP

让我们把整个逻辑串起来:

  1. "直播用 UDP"这句话来源于实时互动通信场景(视频会议、连麦),在那些场景下,极低延迟比数据完整性更重要,所以用 UDP。

  2. 在 B 站等平台观看的直播,属于"大规模单向直播分发"场景。这个场景的核心需求是:画质清晰、播放流畅、能支撑百万级并发观看。延迟在几秒之内是可以接受的。

  3. HLS/DASH 协议把直播流切成小文件,通过普通的 HTTP 请求分发。这样做可以直接复用全球成熟的 CDN 基础设施,穿透各种防火墙和网络限制,支持自适应码率,保证数据完整性。

  4. HTTP 跑在 TCP 上,所以看到的就是 TCP。HTTP/2(h2)进一步优化了性能(多路复用、头部压缩等),让这套方案更高效。

  5. TCP 在这个场景下的延迟代价微乎其微,因为 HLS 本身的切片机制就有几秒的固有延迟,TCP 的重传时间在这个量级面前可以忽略不计。

所以,不是"视频直播应该用 UDP 但平台偷懒用了 TCP",而是不同的场景有不同的最优解。对于观众看到的那一段链路,TCP 就是正确的选择。

Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐