
前言本人最近在学习音视频相关的知识目前学到了RTP协议写下这篇博客加深自己的理解同时希望能够帮助大家加深对RTP的理解。这篇博客我会从是什么、为什么、怎么办三个角度由浅入深地讲解 RTP 协议的所有核心知识点包括RTP 的本质与设计哲学RTP 包头每个字段背后的权衡RTCP 的核心作用与反馈闭环为什么必须把音频和视频分开传输音视频同步的完整原理附数值例子一、先搞懂 RTP 的本质 —— 它到底解决了什么问题为什么不能直接用 TCP 传视频通话在开始学习 RTP 之前请先认真思考你用 TCP 传一个 1GB 的电影文件丢了一个包会怎么样TCP 会不断重传直到对方确认收到保证数据100% 完整且按序到达。你和朋友视频通话丢了一个视频帧的包TCP 重传需要 200ms等这个帧传过来的时候画面已经跳到 3 秒后了你还需要这个过时的帧吗答案非常明确实时音视频最核心的需求不是 不丢包而是 低延迟。过时的数据比丢失的数据更可怕。这就是 RTP 诞生的根本原因TCP可靠但延迟高队头阻塞问题严重不适合实时传输UDP低延迟但什么都不管丢包、乱序、没有时间同步RTP运行在 UDP 之上专门为实时音视频设计填补了 UDP 的功能空白1.1 RTP 的官方定义与核心设计哲学RTPReal-time Transport Protocol实时传输协议是一个应用层传输协议注意它不是传输层协议定义在 RFC 3550 中专门用于在 IP 网络上传输对实时性要求高的数据比如音频、视频、游戏画面、工业传感器数据等。RTP 永远不会单独出现它总是和RTCPRTP Control ProtocolRTP 控制协议成对工作RTP负责媒体数据的传输RTCP负责传输质量的反馈和控制记住这三句话你就抓住了 RTP 的灵魂只做实时传输最需要的事不保证可靠、不保证按序、不提供拥塞控制这些都交给上层应用和 RTCP为每个媒体数据包打上精确的 时间戳让接收方知道什么时候播放这个数据给每个数据包编号让接收方知道丢了哪些包以及这些包的正确顺序二、RTP 包头深度解析 —— 每个字段都是为了解决一个问题RTP 最精妙的地方就是它的包头设计用最少的字节解决了实时传输最核心的三个问题丢包乱序检测、时间同步、流区分。2.1 RTP 包头标准格式这是 RTP 包头的标准格式12 字节固定头 可选扩展我们用表格来拆解每个字段的含义和它解决的问题字段长度含义解决的核心问题V2 位版本号固定为 2区分不同 RTP 版本P1 位填充位满足加密算法对数据块大小的要求X1 位扩展位表示后面有自定义扩展头CC4 位CSRC 计数表示后面有几个 CSRC 字段M1 位标记位最重要标记一个完整帧的最后一个包PT7 位负载类型表示这个包承载的是什么媒体H.26496, AAC97sequence number16 位序列号解决乱序检测和丢包检测问题timestamp32 位时间戳解决时间同步和播放节奏控制问题SSRC32 位同步源标识符解决不同媒体流区分问题CSRC32 位 ×CC贡献源标识符用于视频会议的混流器场景2.2 三个核心字段的深度思考1序列号sequence number每次发送一个 RTP 包序列号加 1初始值随机。接收方收到包后对比自己维护的 预期序列号就能立刻知道如果收到的序列号 预期中间丢了包如果收到的序列号 预期这是一个迟到的包直接丢弃问题 1为什么序列号只有 16 位最多 65535如果传输速度很快会不会很快就溢出了16 位是延迟与开销的最优权衡而且溢出完全不会影响正常工作。实际传输中溢出速度比你想象的慢得多1080P30fps 的 H.264 视频每秒大约 3300 个 RTP 包溢出时间约为 19.8 秒即使是 4K60fps 视频溢出时间也在 3 秒以上。序列号溢出的处理极其简单序列号是循环递增的65535 的下一个就是 0。只要最大网络延迟 溢出时间的一半就不会有任何歧义。32 位序列号会增加 2 字节的包头开销对于每秒几千个包的实时流来说这是一笔不小的带宽浪费且没有任何实际收益。2时间戳timestamp绝对不是系统时间是相对于流开始时间的采样时刻。时间戳的增长速度由采样率决定音频采样率 48kHz时间戳每秒增加 48000视频帧率 30fps时间戳每秒增加 90000所有视频统一用 90kHz 时钟问题 2为什么视频统一用 90kHz 时钟而不是 25kHz 或者 30kHz90kHz 是所有常见视频帧率的最小公倍数保证了整数时间戳间隔避免了浮点误差。90000 ÷ 24 3750电影、÷253600PAL、÷303000NTSC、÷501800、÷601500所有常见帧率都能被 90000 整除。如果时间戳间隔不是整数长期累积会产生严重的播放漂移。3SSRC同步源标识符每个 RTP 流都有一个唯一的 32 位随机数作为 SSRC。即使音频和视频流用同一个 UDP 端口传输接收方也能通过 SSRC 区分它们。问题 3如果两个不同的发送方随机生成了相同的 SSRC 怎么办RFC 3550 定义了完整的SSRC 冲突检测与解决机制。冲突概率极低32 位随机数的冲突概率约为 1/(2^32)即使 1000 人会议中也不到百万分之一。冲突检测接收方收到 RTP 包时会检查 SSRC 对应的 CNAME规范名是否相同。冲突解决发现冲突的发送方会发送 BYE 报文通知旧 SSRC 失效然后生成新的随机 SSRC 重新开始发送。三、RTCP——RTP 的另一半没有它 RTP 就是个废物很多人以为 RTCP 只是个辅助协议其实不然。没有 RTCP 的 RTP 只能实现数据传输无法实现自适应的实时传输。3.1 RTCP 的五大报文类型RTCP 主要有五种报文类型各司其职SRSender Report发送方报告包含发送包数、字节数、NTP 时间戳与 RTP 时间戳的映射关系音视频同步的核心RRReceiver Report接收方报告包含丢包率、抖动、往返延迟等关键质量指标SDESSource Description源描述包含 CNAME规范名、用户名、邮箱等信息BYE结束报告告诉对方 我要退出会话了APP应用自定义报文用于扩展功能3.2 RTPRTCP 的自适应传输闭环RTP 只管发数据RTCP 负责反馈质量两者配合才能实现根据网络状况动态调整的自适应传输发送方每隔 5 秒默认发送 SR 报文接收方收到 SR 后计算出往返延迟RTT接收方每隔 5 秒发送 RR 报文把丢包率、抖动、RTT 反馈给发送方发送方根据反馈信息动态调整编码码率丢包率 5% 降码率1% 升码率四、为什么必须把音频和视频分开传输—— 不是设计选择是必然结果很多人觉得分开传输增加了复杂度但实际上这是实时音视频系统经过几十年发展得出的最优解背后有 6 个不可替代的核心原因。4.1 编码与解码特性完全独立音频和视频是两种本质不同的媒体它们的特性天差地别特性音频视频采样率8kHz/16kHz/44.1kHz/48kHz统一 90kHz 时钟码率范围8kbps电话~ 128kbpsCD500kbps标清~ 20Mbps4K单帧大小几十字节几百字节几千字节几百千字节解码复杂度极低手机 CPU1%极高手机 CPU30%丢包容忍度极低3% 就有杂音较高10% 可补偿如果强行合并传输小尺寸的音频包会被大尺寸的视频包 拖累导致音频延迟增加这是绝对不能接受的。4.2 网络 QoS 可以针对性优化不同的媒体流对网络质量的要求完全不同音频流优先级最高人耳对音频中断和延迟极其敏感视频流优先级次之可以容忍一定的延迟和丢包在企业网络中可以通过DSCP差分服务代码点标记不同的 RTP 流音频流标记为 EF加速转发获得最低的延迟和抖动视频流标记为 AF41获得较高的优先级普通数据标记为 BE尽力而为4.3 带宽自适应的灵活性这是视频通话体验好坏的关键。当网络变差时我们总是希望优先保证音频清晰再考虑视频质量网络极好1080P30fps 128kbps AAC网络一般720P25fps 64kbps AAC网络较差480P15fps 32kbps Opus网络极差关闭视频仅保留音频如果音视频合并传输就无法实现这种精细化的码率调整。4.4 其他重要原因播放控制独立可以单独静音、单独关闭视频、调整音量错误隔离视频花屏不会影响音频播放音频卡顿也不会影响视频多流转发效率高视频会议中MCU 可以直接转发视频流只需要混合音频流五、RTP 音视频同步终极详解 ——90% 的人都理解错了音视频同步也叫 唇音同步是实时音视频系统中最核心也最容易被误解的部分。它的本质不是让音频和视频同时到达接收方而是让它们在正确的时刻同时播放。5.1 先搞清楚为什么音视频会不同步不同步的原因主要有四个采集不同步摄像头和麦克风的硬件时钟有微小差异传输不同步音频包和视频包走的网络路径不同延迟和抖动不同解码不同步视频解码比音频解码慢得多播放不同步音频和视频的播放缓冲大小不同5.2 同步的最大障碍两个独立的 RTP 时间轴每个 RTP 流都有自己独立的时间戳系统音频流时间戳增长速度 音频采样率视频流时间戳增长速度 90000 / 秒两个流的时间戳初始值都是随机的互相之间没有任何关系这就产生了一个核心问题接收方收到一个时间戳为 100000 的音频包和一个时间戳为 200000 的视频包怎么知道它们是不是应该同时播放答案就是RTCP SR发送方报告报文。这是整个同步机制的灵魂。5.3 核心原理用 SR 报文建立统一时间轴SR 报文中有三个决定同步成败的关键字段Sender Report (SR) Packet Format: -------------------------------- | SSRC of sender | -------------------------------- | NTP timestamp, most significant word | | (绝对时间戳秒) | -------------------------------- | NTP timestamp, least significant word | | (绝对时间戳微秒) | -------------------------------- | RTP timestamp | | (对应上述NTP时刻的该流的RTP相对时间戳) | --------------------------------最重要的一句话SR 报文建立了 发送方绝对时间 和 该流 RTP 相对时间戳 之间的一一映射关系。发送方会每隔 5 秒为每个 RTP 流发送一个 SR 报文。也就是说音频流和视频流会各自发送自己的 SR 报文。5.4 同步的完整步骤整个同步过程完全不需要接收方和发送方的系统时间同步只需要发送方自己的音视频时钟是同步的。步骤 1建立时间映射表接收方收到第一个 SR 报文时会记录下音频流(NTP_a1, RTP_a1)视频流(NTP_v1, RTP_v1)步骤 2校准时钟频率通过两个 SR 报文精确计算实际的时钟频率修正硬件漂移音频实际时钟频率 (RTP_a2 - RTP_a1) / (NTP_a2 - NTP_a1) 视频实际时钟频率 (RTP_v2 - RTP_v1) / (NTP_v2 - NTP_v1)步骤 3转换为发送方绝对时间对于任何一个 RTP 包都可以计算出它在发送方的生成时间音频发送时间 T_a NTP_a1 (RTP_a - RTP_a1) / 音频时钟频率 视频发送时间 T_v NTP_v1 (RTP_v - RTP_v1) / 视频时钟频率步骤 4抖动缓冲与播放对齐接收方维护一个全局播放时钟和一个统一的播放延迟通常 200ms~500ms。每个流都有自己独立的抖动缓冲包按照发送时间排序。当播放时钟到达某个时刻时接收方会从音频缓冲中取出所有发送时间 ≤ 当前播放时间的音频包解码播放从视频缓冲中取出所有发送时间 ≤ 当前播放时间的视频包解码播放这样发送时间相同的音频和视频包就会在同一个播放时刻被播放出来。一个具体的数值例子假设音频采样率48000Hz发送方在 1000.000 秒发送 SR音频 NTP1000.000RTP123456视频 NTP1000.000RTP789012现在收到一个音频包 RTP147456 和一个视频包 RTP834012音频发送时间 1000.000 (147456-123456)/48000 1000.500秒 视频发送时间 1000.000 (834012-789012)/90000 1000.500秒它们的发送时间相同所以应该同时播放。5.5 同步精度与常见问题人耳对唇音同步的误差有一个可接受的范围音频领先视频 ≤ 80ms几乎感觉不到视频领先音频 ≤ 160ms几乎感觉不到超过这个范围就会明显感觉到 口型对不上常见问题解决SR 报文丢失使用之前的映射关系继续工作直到收到新的 SR时钟漂移定期的 SR 报文会自动校准视频解码过慢丢弃一些非关键的 B 帧让视频跟上音频的节奏七、常见问题为什么 RTP 必须运行在 UDP 之上有没有例外因为 TCP 的重传和队头阻塞与实时性需求本质矛盾。例外情况RTP 交织模式封装在 RTSP TCP 连接中和非实时点播场景。RTP 包头中的 M 位有什么作用如果没有会怎么样M 位标记一个完整帧的最后一个包。如果没有 M 位接收方只能等到下一个帧的第一个包到达才能确定上一个帧结束会导致至少一帧的延迟。RTCP 的 RR 报文里的丢包率是怎么计算的丢包率 两个 RR 报告之间丢失的包数 ÷ 期望收到的包数 × 100%由接收方基于序列号计算得出。为什么时间戳不能直接用系统时间因为不同设备的系统时间同步精度不足NTP 只有几十毫秒而且系统时间可能会跳变无法满足音视频毫秒级的同步需求。网络很差时RTP 本身能做什么不能做什么能做检测丢包、乱序、抖动反馈质量指标。不能做重传、纠正乱序、拥塞控制、丢包补偿。这些都需要上层应用实现。为什么 RTP 不自己实现拥塞控制因为不同的实时应用对拥塞的容忍度和处理方式完全不同视频通话、直播、游戏没有一种通用的算法能满足所有需求。八、总结总结RTP 是专门为实时传输设计的应用层协议运行在 UDP 之上和 RTCP 成对工作RTP 的核心是时间戳、序列号和 SSRC分别解决时间同步、丢包乱序和流区分问题音视频分开传输是必然结果能实现最优的体验和效率音视频同步的核心是通过 SR 报文建立两个独立时间轴之间的映射关系RTP 只提供最基本的功能所有与应用相关的决策都交给上层应用写在最后RTP 协议看起来简单但它的设计思想非常精妙每一个字段都经过了深思熟虑的权衡。学习 RTP 最重要的不是死记硬背而是理解每个设计背后的原因。如果这篇博客对你有帮助欢迎点赞、收藏、评论交流。有任何问题都可以在评论区留言我会一一解答。