RTSP 协议基础:从一次真实的推流事故说起
我记得刚入行那会儿,接手过一个远程监控项目。摄像头在千里之外,我这边用 FFmpeg 拉流,画面死活出不来。折腾了两天,最后发现是 RTSP 的 DESCRIBE 请求被防火墙拦了。嗯,从那以后我就养成了一个习惯——搞流媒体,先把协议啃透。
RTSP 是流媒体世界的「遥控器」。它不负责传视频数据,只管「播放、暂停、快进、停止」这些控制指令。说白了,它就是个指挥家,真正演奏的是 RTP 和 RTCP。
RTSP 与 HTTP 的区别
很多新手会把 RTSP 和 HTTP 搞混。毕竟它们都用文本格式,都像在「发请求-收响应」。但本质上,HTTP 是「拿来」,RTSP 是「控制」。
| 对比维度 | RTSP | HTTP |
|---|---|---|
| 核心目的 | 控制媒体流(播放/暂停/停止) | 传输文档/资源 |
| 状态性 | 有状态(维护会话状态机) | 无状态(每个请求独立) |
| 默认端口 | 554 | 80 / 443 |
| 数据传输 | 不直接传数据,由 RTP 承载 | 直接在响应体传数据 |
| 方向性 | 双向控制(客户端↔服务器) | 请求-响应模式 |
| 典型方法 | SETUP, PLAY, PAUSE, TEARDOWN | GET, POST, PUT, DELETE |
关键点:RTSP 的 URL 以 rtsp:// 开头,而 HTTP 是 http://。但 RTSP 也可以承载在 HTTP 之上(RTSP over HTTP),用于穿透防火墙。我在项目中就遇到过这种场景——摄像头在内网,只能走 HTTP 80 端口出去,这时候就得用 RTSP 隧道。
RTSP 消息格式
RTSP 消息分两种:请求和响应。格式和 HTTP 非常像,都是文本行 + 头部 + 空行 + 消息体。
一个典型的 RTSP 请求长这样:
DESCRIBE rtsp://192.168.1.100:554/live/stream RTSP/1.0
CSeq: 1
Accept: application/sdp
User-Agent: FFmpeg/4.4
响应呢?
RTSP/1.0 200 OK
CSeq: 1
Content-Type: application/sdp
Content-Length: 456
v=0
o=- 123456 789012 IN IP4 192.168.1.100
s=Live Stream
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
...
注意几个细节:
- CSeq:序列号,请求和响应必须配对。我见过有人忘了递增 CSeq,结果服务器一直返回旧响应。
- Content-Type:通常是
application/sdp,描述媒体参数。 - 空行:不能少,少了服务器解析会出错。
RTSP 核心方法
RTSP 定义了多个方法,但实际推流拉流中,这六个方法是必用的。我按它们在一次完整会话中的调用顺序列出来:
| 方法 | 作用 | 典型场景 |
|---|---|---|
| OPTIONS | 查询服务器支持哪些方法 | 客户端刚连接时,先问一下「你支持啥?」 |
| DESCRIBE | 获取媒体描述(SDP) | 拿到视频编码、分辨率、码率等信息 |
| SETUP | 建立传输通道(UDP/TCP) | 指定 RTP 端口、传输模式 |
| PLAY | 开始播放 | 告诉服务器「可以发数据了」 |
| PAUSE | 暂停播放 | 临时停止,但不关闭会话 |
| TEARDOWN | 终止会话 | 关闭连接,释放资源 |
个人经验:OPTIONS 不是必须的。很多客户端(包括 FFmpeg)会直接发 DESCRIBE,如果服务器不支持,再回退。但我建议你在调试阶段先发 OPTIONS,能快速确认服务器是否活着。
RTSP 状态机
RTSP 是有状态的。服务器会维护每个会话的状态,客户端必须按顺序调用方法。状态机其实不复杂,就四个状态:
- INIT:初始状态,刚建立 TCP 连接。
- READY:SETUP 完成后,准备好接收媒体流。
- PLAYING:正在播放中。
- RECORDING:正在录制(推流场景)。
状态转换规则:
- INIT → 发 DESCRIBE → 仍在 INIT
- INIT → 发 SETUP → 进入 READY
- READY → 发 PLAY → 进入 PLAYING
- PLAYING → 发 PAUSE → 回到 READY
- 任何状态 → 发 TEARDOWN → 回到 INIT(或断开)
避坑指南:我曾经在代码里犯过一个低级错误——在 PLAYING 状态下又发了一次 SETUP。结果服务器直接返回 455 Method Not Valid In This State。记住:SETUP 只能在 READY 或 INIT 状态下调用。
下面这张图把整个流程串起来了,你一看就明白:
你看,整个流程其实很清晰。客户端先连上来,发 DESCRIBE 问清楚媒体信息,然后 SETUP 建立通道,最后 PLAY 开始拉流。推流的话,把 PLAY 换成 RECORD 就行。
核心要点:RTSP 本身不传视频数据。它只负责「控制」。真正的音视频数据走的是 RTP(实时传输协议),而 RTP 的传输参数(端口、编码格式)就是在 SETUP 和 DESCRIBE 阶段协商好的。这个设计理念很重要——控制面和数据面分离。