ZLMediaKit 协议选型实战指南:TCP 还是 UDP,10 秒定下来,卡顿和延迟一起治
2026/9/10 23:09:31 网站建设 项目流程

ZLMediaKit 协议选型实战指南:TCP 还是 UDP,10 秒定下来,卡顿和延迟一起治

【免费下载链接】ZLMediaKitWebRTC/RTSP/RTMP/HTTP/HLS/HTTP-FLV/WebSocket-FLV/HTTP-TS/HTTP-fMP4/WebSocket-TS/WebSocket-fMP4/GB28181/SRT/STUN/TURN server and client framework based on C++11项目地址: https://gitcode.com/GitHub_Trending/zl/ZLMediaKit

开会时看远端直播,画面突然卡住两秒,切到监控页,端到端延迟已经叠到 8 秒。你的第一反应是网络慢,多半不是——是 TCP 和 UDP 选错了。这篇文章围绕 ZLMediaKit 协议选型展开,把判据、关键配置项和调优值一次摆出来,你看完直接上手。

结论先行:10 秒敲定协议 🔑

不用先背原理,记住下面 5 条,能覆盖九成场景:

  1. RTMP 推流或 HTTP-FLV 播放(最常见的公网直播组合):不用想,天生 TCP,选型问题不存在,你要调的是服务器端的合并写参数。
  2. RTSP 播放,观众在公网或弱网:强制 TCP,rtpTransportType=0。丢包有重传兜底,不用担心花屏。
  3. RTSP 播放,两端在同一局域网(摄像头、NVR、测试台):强制 UDP,rtpTransportType=1。客户端非要走 TCP,服务器回 461 逼它重新协商。
  4. WebRTC 这类互动场景:UDP 打底,内置 NACK 重传补可靠性,是「UDP 低延迟 + 选择重传」的组合。
  5. 客户端后面有严格 NAT 或防火墙,UDP 明确不通:退回 TCP。协议再好,包过不去就是过不去。

绝大多数播放端其实没有选择权,真正的纠结只发生在 RTSP 和 WebRTC 这一层。

原理拆解:一个类比讲清 TCP 与 UDP

这么理解:TCP 像挂号信,每一封都要收件人签收,丢了会补寄,按顺序送到;UDP 像明信片,寄出去就不管了,没人回执,丢了就是丢了,但路上最省时间。

差异摊开就四点:

  • 到达保证:TCP 有确认和重传,保证「一个都到」;UDP 不管,丢包是常态。
  • 到达顺序:TCP 保序,后到的包会等前面缺的(队头阻塞);UDP 允许乱序,上层靠 RTP 序列号自己拼。
  • 延迟代价:TCP 的确认、重传、流控都是实时性开销;UDP 控制环节少,延迟天然低。
  • 头部开销:TCP 拖着头部加控制信息,同样码率下 UDP 把更多带宽留给真正的画面。

换句话说:TCP 买的是完整性,UDP 买的是速度,钱只有一份,你只能选一个。ZLMediaKit 里,RTP 负载可以走 TCP(RTSP interleaved 模式)或 UDP(单播/组播),RTMP 和 HTTP-FLV 天生走 TCP。RTSP 的 UDP 收发与端口复用逻辑在 src/Rtsp/UDPServer.cpp,好奇可以直接看源码。

场景拆解:3 个真实场景怎么选

场景一:公网 / 弱网直播

  • 症状:开播途中偶发 1~2 秒冻结,或观看一段时间后连接被断开。
  • 选谁:TCP(RTMP / HTTP-FLV 默认如此;RTSP 走公网时强制rtpTransportType=0)。
  • 为什么:公网丢包率不可控,只有重传能保证画面完整,多花的那点时间比花屏值钱。
  • 动哪[rtmp]keepAliveSecond默认 15 秒,15 秒内收不到客户端数据或 TCP 发送缓存卡住就断连,断连多就调到 30。

场景二:局域网实时预览

  • 症状:局域网内看摄像头,延迟照样 300ms 以上,操作员点一下反应慢半拍。
  • 选谁:UDP,[rtsp]rtpTransportType=1
  • 为什么:局域网几乎不丢包,重传机制纯属浪费;UDP 逐帧发出去就走,再叠加lowLatency=1关掉 RTP 包缓存,又能省一帧。
  • 动哪:就这两个参数,改完即可。

场景三:高码率大屏播放

  • 症状:单路 4K 流 20Mbps 起步,并发一多,服务器发送队列开始堆积,延迟持续上涨。
  • 选谁:UDP 单播;多台大屏在同一局域网时,直接上组播(rtpTransportType=2)。
  • 为什么:高码率叠 TCP,带宽一抖就队头阻塞,所有人陪着等;UDP 头部小、占用低,组播还能让骨干网只传一份,省下的带宽全留给画面。
  • 动哪[rtp_proxy]udp_recv_socket_buffer默认 4194304 字节(4MB),高码率突发仍丢包就继续加大。

配置清单:可直接抄走

以上参数都在配置文件里,样例即 conf/config.ini。注意:构建后进程实际加载的是 release 目录下的config.ini,改错文件白忙一场。最小可用配置,按段分组如下:

[general] mergeWriteMS=0 # 合并写间隔(ms),0=立即写socket,不引入额外延迟 [rtsp] rtpTransportType=-1 # 强制协商RTP传输 (0:TCP,1:UDP,2:MULTICAST,-1:不限制) lowLatency=0 # 开启后RTSP转发不缓存rtp包,可降一帧延迟 [rtmp] keepAliveSecond=15 # 该秒数内收不到客户端数据即断开 handshakeSecond=15 # 握手须在该秒数内完成,否则断开 [rtp_proxy] udp_recv_socket_buffer=4194304 # UDP接收socket缓冲(字节),4MB [rtc] nackMaxCount=15 # WebRTC NACK最多请求重传次数

改完重启 MediaServer 生效,参数含义以conf/config.ini内的注释为准。

进阶调优:还是卡就看这里 🛠

按症状找参数,一个一个改:

  • 每次开播固定多 100~200ms 延迟[general]mergeWriteMS。设 10 时服务器攒够 10ms 数据再批量写,同时关闭 TCP_NODELAY、开启 MSG_MORE,吞吐上去了延迟也上去了,延迟敏感就改回 0。
  • RTSP 走 UDP 偶发花屏→ 高码率突发装不进系统接收队列,加大[rtp_proxy]udp_recv_socket_buffer,从默认 4194304 调到 8388608(8MB)。
  • WebRTC 通话中花屏→ 看[rtc]的 NACK 组:nackMaxCount默认 15 次,nackMaxMS默认 3000ms(丢包状态只保留 3 秒),maxRtpCacheMS默认 5000ms;重传追不上就把nackRtpSize(默认 8)调小,让重传请求更灵敏。
  • RTSP 转发并发高,想再抠一帧延迟[rtsp]lowLatency=1,用包缓存换并发。
  • H.264 一帧多个 slice,想开低延迟[rtp]lowLatency默认关闭,这种流开启后可能花屏,先确认编码侧没有多 slice 再动。

一句话收束:网络可信选 UDP 换延迟,网络不可信选 TCP 换完整,两个都要就交给 WebRTC。更完整的特性说明见仓库内官方文档 README.md。

【免费下载链接】ZLMediaKitWebRTC/RTSP/RTMP/HTTP/HLS/HTTP-FLV/WebSocket-FLV/HTTP-TS/HTTP-fMP4/WebSocket-TS/WebSocket-fMP4/GB28181/SRT/STUN/TURN server and client framework based on C++11项目地址: https://gitcode.com/GitHub_Trending/zl/ZLMediaKit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询