1. RTSP 协议基础:从一次真实推流失败说起

各位好,我是老周。做流媒体这行十几年了,RTSP 算是我最早接触的协议之一。记得刚入行那会儿,我负责一个安防项目,摄像头输出的 RTSP 流在 VLC 里播得好好的,换成我们自研的播放器就卡死。查了三天,最后发现是 RTSP 的 DESCRIBE 请求里少带了一个 Accept 头——服务器返回了 MPEG-TS 描述,而我们只解析了 SDP。嗯,从那以后我就养成了一个习惯:搞 RTSP 推流,先把协议交互流程刻在脑子里。

今天这一章,我们就从 RTSP 协议本身讲起。你可能会问:WebRTC 推流为什么要学 RTSP?说白了,RTSP 是控制信令,RTP 是数据载体,RTCP 是质量监控——这三兄弟配合好了,才能把摄像头、编码器的数据送到 WebRTC 的轨道里。下面我们一个一个拆开看。

1.1 RTSP 协议概述

RTSP(Real Time Streaming Protocol)是 IETF 在 RFC 2326 里定义的。它本质上是一个应用层控制协议,负责多媒体流的建立、播放、暂停、录制等操作。你可以把它想象成电视遥控器——按播放键、暂停键、快进键,但电视画面本身是通过其他通道传过来的。

核心要点:RTSP 不传输媒体数据,只传输控制命令。媒体数据走 RTP,控制走 RTSP,两者通过 Session ID 关联。

RTSP 的语法和 HTTP 很像,都是请求-响应模式,也支持类似 OPTIONS、DESCRIBE、SETUP、PLAY 这些方法。但有个关键区别:RTSP 是有状态的。服务器需要记住每个会话当前处于什么阶段——是刚建立、正在播放、还是暂停了。HTTP 是无状态的,每次请求都是独立的。

我个人习惯把 RTSP 的状态机画成一张图,方便调试时对照。下面这张 SVG 就是 RTSP 推流最核心的交互流程:

RTSP 推流交互流程 RTSP 推流交互流程(客户端 → 服务器) 客户端 (Client) 服务器 (Server) ① OPTIONS (询问支持哪些方法) ← 200 OK (返回支持的方法列表) ② DESCRIBE (请求媒体描述) ← 200 OK (返回 SDP 描述) ③ SETUP (建立传输通道,指定端口) ← 200 OK (返回 Session ID + 端口) ④ PLAY (开始播放/推流) ← 200 OK (开始传输 RTP 数据) RTP 数据流 ⑤ 持续传输音视频 RTP 包 RTCP 控制流 ⑥ 周期性 RTCP 报告(丢包率、抖动等) ⑦ TEARDOWN (结束会话) ← 200 OK (释放资源) 说明:绿色虚线为 RTP 数据通道,紫色虚线为 RTCP 控制通道,实线为 RTSP 信令交互

1.2 RTSP 与 RTP/RTCP 的关系

很多初学者会把 RTSP 和 RTP 搞混。我打个比方你就明白了:

  • RTSP 是遥控器——负责按播放、暂停、停止
  • RTP 是电视信号线——负责传输音视频数据
  • RTCP 是信号质量监测仪——告诉你信号有没有丢包、延迟多少

这三者配合工作的典型场景是这样的:

  1. 客户端通过 RTSP 发送 SETUP 请求,告诉服务器「我要用 UDP 端口 5000 和 5001 收数据」
  2. 服务器在端口 5000 上发送 RTP 包(音视频数据),在端口 5001 上发送 RTCP 包(质量报告)
  3. 客户端通过 RTCP 的 Sender Report (SR) 和 Receiver Report (RR) 计算丢包率、抖动、RTT
  4. 如果丢包率太高,客户端可以通过 RTSP 的 SET_PARAMETER 请求调整编码参数

我的经验:在 WebRTC 推流场景中,RTSP 的 RTP 数据通常需要经过转码或重封装才能送入 WebRTC 的 PeerConnection。直接透传 RTP 包是不行的——WebRTC 有自己的 RTP 扩展头和 FEC 机制。我踩过这个坑,后来在中间加了一层 RTP 解包再组包才解决。

下面这张表总结了 RTSP、RTP、RTCP 的核心差异:

特性 RTSP RTP RTCP
功能 会话控制(播放/暂停/停止) 媒体数据传输 质量监控与反馈
传输层 TCP(默认)或 UDP UDP(常用)或 TCP UDP(与 RTP 同端口或 +1)
可靠性 可靠(TCP 保证) 不可靠(UDP 无重传) 不可靠,但周期性发送
端口 554(默认) 动态协商(通过 SETUP) RTP 端口 + 1
关键字段 CSeq, Session, Transport SSRC, Sequence Number, Timestamp SSRC, Fraction Lost, Cumulative Lost

1.3 RTSP 消息格式与交互流程

RTSP 的消息格式和 HTTP 1.1 几乎一样。一个典型的 RTSP 请求长这样:

DESCRIBE rtsp://192.168.1.100:554/live/ch1 RTSP/1.0
CSeq: 2
Accept: application/sdp
User-Agent: MyRTSPClient/1.0

服务器响应:

RTSP/1.0 200 OK
CSeq: 2
Content-Type: application/sdp
Content-Length: 142

v=0
o=- 1234567890 1234567890 IN IP4 192.168.1.100
s=Live Stream
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=42e01f;sprop-parameter-sets=Z0IACpY1QFAe2A==,aM4G4g==

这里有几个关键点:

  • CSeq:序列号,请求和响应必须配对。我见过有人忘了递增 CSeq,结果服务器一直返回 400 Bad Request
  • Session:会话 ID,在 SETUP 响应中返回,后续请求都要带上
  • Transport:传输参数,包括协议(RTP/AVP)、传输方式(unicast/multicast)、端口号、interleaved 模式等

注意:RTSP 的 Transport 头字段非常容易出错。我曾经在 SETUP 请求里写错了端口范围,服务器返回了 461 Unsupported Transport。正确的格式应该是:Transport: RTP/AVP/UDP;unicast;client_port=5000-5001。注意端口是成对出现的——偶数给 RTP,奇数给 RTCP。

完整的 RTSP 交互流程,我习惯用「五步握手」来记忆:

  1. OPTIONS:客户端问服务器「你支持哪些方法?」服务器回复「我支持 DESCRIBE, SETUP, PLAY, TEARDOWN」
  2. DESCRIBE:客户端问「你的媒体流是什么格式?」服务器回复 SDP 描述(编码、分辨率、帧率等)
  3. SETUP:客户端说「我要在端口 5000-5001 收数据,请准备好」服务器回复 Session ID 和确认的端口
  4. PLAY:客户端说「开始推流!」服务器开始发送 RTP 数据
  5. TEARDOWN:客户端说「结束会话」服务器释放资源

你可能会问:为什么需要 OPTIONS 这一步?直接 DESCRIBE 不行吗?嗯,有些老旧摄像头只支持基本方法,不支持 PAUSE 或 RECORD。OPTIONS 可以让你提前知道服务器的能力,避免后续请求失败。我在对接海康和大华的摄像头时就发现,它们的 OPTIONS 响应里方法列表不一样——海康支持 GET_PARAMETER,大华不支持。

1.4 实际推流中的常见问题

最后分享几个我在 RTSP 推流中踩过的坑:

  • UDP 端口被防火墙拦截:很多生产环境只开放了 554 端口(RTSP 控制),但 RTP 数据走的是随机高位端口。解决方案是用 RTSP over TCP(interleaved 模式),把 RTP 数据也封装在 TCP 连接里传输
  • SDP 中的 sprop-parameter-sets 缺失:H.264 的 SPS/PPS 必须通过 SDP 传给客户端。如果服务器没带,客户端就无法解码。我遇到过摄像头固件 bug,SDP 里 sprop-parameter-sets 是空的,后来在 SETUP 之后手动发了一个 GET_PARAMETER 才拿到
  • RTCP 超时导致会话断开:有些服务器会监控 RTCP 报告,如果一段时间没收到就认为客户端挂了。我在做 WebRTC 转 RTSP 推流时,因为 WebRTC 的 RTCP 间隔和 RTSP 标准不一致,导致服务器频繁断开连接。后来在中间件里模拟了 RTCP 报告才解决

调试技巧:抓包是排查 RTSP 问题最有效的手段。我常用 Wireshark 的 rtsp 过滤器和 rtp 过滤器。重点关注 CSeq 是否连续、Transport 头是否正确、SDP 是否完整。另外,很多 RTSP 服务器会在响应里带 Server 头,比如 Server: Live555 Streaming Media v2023.01.19,这能帮你快速定位是哪个开源库。