一、概述
RTSP,全称时 Real Time Streaming Protocol,实时流媒体协议,是TCP/IP协议体系中的一个应用层协议
RTSP 协议的语法和操作参考了 HTTP/1.1,基于文本的协议,采用ISO10646字符集,使用UTF-8编码;承载RTSP的传输层协议为TCP,默认端口554;如果是RTSP-over-HTTP tunneling,则默认TCP端口为8080;一般与RTP/RTCP协议搭配使用,由RTP协议传输实时流数据,RTCP协议完成数据流和控制命令的传输
RTP协议:全称Real-time Transport Protocol,实时传输协议,由IETF的多媒体传输工作小组1996年在RFC 1889中公布的。RTP协议详细说明了在互联网上传递音频和视频的标准数据包格式。它是创建在UDP协议上的。
RTCP协议:全称Real-time Transport Control Protocol,实时传输控制协议,与RTP配合使用。RTP 使用一个偶数的 UDP 端口;而RTCP 则使用 RTP 的下一个端口,也就是一个奇数端口。RTCP与RTP联合工作,RTP实施实际数据的传输,RTCP则负责将控制包送至会话中的每个人。其主要功能是就RTP正在提供的服务质量做出反馈
二、RTSP 方法
RTSP常用的方法包括:OPTIONS、DESCRIBE、SETUP、PLAY、PAUSE、TEARDOWN、ANNOUNCE、GET_PARAMETER和SET_PARAMETER等。详细使用介绍如下:
OPTIONS:客户端向服务器获取服务器支持的方法。它不影响服务器的状态;
DESCRIBE:客户端向服务器获取URL指定的媒体对象的描述,其中Accept字段指定了描述格式;
SETUP:客户端向服务器请求建立会话并准备传输。请求信息主要包括传输协议和客户端的端口号;
PLAY:客户端主动通知服务器以SETUP指定的机制开始发送数据。其中Range字段指定了播放的起止时间(实时流Range一般为Range: npt=0.000-),当多个PLAY请求到达时,服务器会将PLAY请求排成队列,顺序执行,即必须等待第一个PLAY的时间完成后,才会继续处理第二个PLAY消息。
PAUSE:客户端请求服务器的媒体流传输临时暂停。可以通过Range参数在指定时间点暂停,也可以指定某股流暂停,例如,如果指定音频流暂停,则播放将是无音状态
RECORD:RECORD通知服务器,客户端将会根据之前的描述开始记录媒体数据。 其中 timestamp 字段反映开始和结束时间 (UTC)。如果该字段不存在,则会使用媒体描述中的开始或结束时间。 如果会话已经开始,则立即开始录制。
服务器决定是将记录的数据存储在 request-URI 下还是另一个 URI 下。 如果服务器不使用 request-URI,则响应应该是 201(已创建)并包含描述请求状态并引用新资源的实体和 Location 标头。
TEARDOWN:客户端请求停止指定URL流发送,释放相关资源。
REDIRECT:重定向请求,服务端通知客户端它必须连接到另一个服务器位置。 它包含强制标头 Location,它指示客户端应该发出对该 URL 的请求。 它可能包含参数Range,表示重定向何时生效。 如果客户端想要继续发送或接收此 URI 的媒体,客户端必须为当前会话发出 TEARDOWN 请求,并在指定主机上为新会话发出 SETUP。
ANNOUNCE:当客户端向服务器发送时,表示的是将通过请求 URL 识别的表示描述或者媒体对象提交给服务器
当服务器向客户端发送时,表示的是通知客户端更新会话信息
GET_PARAMETER:GET_PARAMETER 请求检索 URI 中指定的表示或流的参数值。 回复和响应的内容留给实现。 没有实体主体的 GET_PARAMETER 可用于测试客户端或服务器的活跃度(“ping”)。
SET_PARAMETER:这个方法请求设置演示或URL指定流的参数值。请求仅应包含单个参数,允许客户端决定某个特殊请求为何失败。如请求包含多个参数,所有参数可成功设置,服务器必须只对该请求起作用。服务器必须允许参数可重复设置成同一值,但不让改变参数值。注意:媒体流传输参数必须用SETUP命令设置。将设置传输参数限制为SETUP有利于防火墙。
上面总共介绍了 11 个RTSP方法,其中,SETUP、PLAY、TEARDOWN三个命令是 RTSP 流程中必须的,其他方法非必须。而ANNOUNCE、GET_PARAMETER、SET_PARAMETER三个命令既可以是客户端发给服务端,也可以是服务端发给客户端,其他命令都是客户端发给服务端的
三、RTSP 的 请求报文 与 响应报文
RTSP 的 请求报文
RTSP请求报文由请求行、请求头部和请求体三个部分组成。其中,请求行是必须的,而请求头部和请求体则根据具体情况可选。
请求行:请求行包含一个方法、一个请求URI和一个协议版本,它们之间以空格分隔,并以CRLF(即:\r\n)结束。
方法:就是上面介绍的RTSP方法。包括OPTIONS、DESCRIBE、SETUP、PLAY、PAUSE、TEARDOWN等。
请求URI:标识要操作的媒体资源,格式通常为rtsp://example.com/path/to/stream。
协议版本:表示请求遵循的RTSP协议版本,一般为RTSP/1.0或RTSP/2.0。
下面是一个完整的请求行的示例:
OPTIONS rtsp://192.168.3.225:554/wbc RTSP/1.0
请求头部:请求头部包含一些附加信息,比如:CSeq(用于标识请求的序列号)、Session ID(会话标识符)、Transport(传输协议)等。每个头部字段由字段名、冒号和字段值组成,各头部字段之间以CRLF分隔。
下面是一个完整的请求头部的示例:
CSeq: 2
User-Agent: LibVLC/3.0.19 (LIVE555 Streaming Media v2016.11.28)
请求体:请求体是用于传输额外的数据。请求体的具体内容,取决于请求行中所使用的RTSP方法。注意:在请求头部之后,需要插入一个空行(CRLF),用于区分请求头部与请求体。大部分请求报文是没有请求体的。
RTSP 的 响应报文
RTSP请求报文由状态行、响应头部和响应体三个部分组成。其中,状态行是必须的,而响应头部和响应体则根据具体情况可选。
状态行:状态行包含一个协议版本、一个状态码和一个状态文本,它们之间由空格分隔,并以CRLF(即:“\r\n”)结束。
协议版本:表示响应遵循的RTSP协议版本,一般为RTSP/1.0或RTSP/2.0。
状态码:三位数字,比如:200、401、500等,用于指示请求的处理结果。第一位数字代表响应类别:2xx表示成功,4xx表示客户端错误,5xx表示服务器错误。
状态文本:简短的文字描述,解释对应状态码的具体含义,比如:OK、Unauthorized等
下面是响应行例子:
RTSP/1.0 200 OK
智能体编程
响应头部:响应头部包含与请求头部类似的信息,比如:CSeq(用于标识请求的序列号)、Session ID(会话标识符)、Transport(传输协议)等。每个响应头部字段的格式与请求头部相同,故这里不再赘述。
CSeq: 2
Date: Wed, Feb 04 1970 03:25:10 GMT
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER
响应体:某些RTSP响应(比如:DESCRIBE)可能包含响应体,用于传输额外的数据。注意:在响应头部之后,需要插入一个空行(CRLF),用于区分响应头部与响应体。
下面是一个完整的响应体的示例。
v=0
o=- 8913478 1 IN IP4 192.168.3.91
s=LIVE555 Streaming Media v2016.07.19
i=1080
t=0 0
a=tool:LIVE555 Streaming Media v2016.07.19
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:LIVE555 Streaming Media v2016.07.19
a=x-qt-text-inf:1080
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:5000
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=64002A;sprop-parameter-sets=Z2QAKq2EAQwgCGEAQwgCGEAQwgCEO1A8ARPyoA==,aO48sA==
a=control:track1
m=audio 0 RTP/AVP 97
c=IN IP4 0.0.0.0
b=AS:768
a=rtpmap:97 PCMA/48000/2
a=control:track2
四、RTSP 报文的常用字段
RTSP报文的响应头会包含一些字段,下面是一些常用的字段:
Accept: 用于指定客户端通知服务器自己可以接受的实体数据结构类型。例如: Accept: application/sdp,之后服务器通过Content-Type字段返回其实体数据结构类型;
Accept-Encoding:用于客户端通知服务器自己可以接受的数据压缩格式,例如:Accept-Encoding: gzip, compress, br,之后服务器将通过Content-Encoding字段通知客户端它的选择。
Accept-Language: 用于客户端通知服务器自己可以理解的语言及其接受度,例如:Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5 ,之后服务器将通过Content-Language字段通知客户端它的选择
Authorization:客户端请求消息头含有服务器用于验证用户代理身份的凭证
Bandwidth: 用于描述客户端可用的带宽值。例如: Bandwidth: 4000
Blocksize:此字段由客户端发送到媒体服务器,要求服务器提供特定的媒体包大小,服务器可以自由使用小于请求的块大小。 此数据包大小不包括 IP、UDP 或 RTP 等低层标头
CSeq: 指定了RTSP请求响应的序列号,每个RTSP请求都必须包含一个唯一的CSeq值,以便服务器能够正确地识别和处理请求。这个序列号随着请求消息递增。服务器响应必须有CSeq值,指明响应哪个请求。
Cache-Control:通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中
Conference:通知服务器不得更改同一 RTSP 会话的会议 ID
Connection:该字段决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成或者Connection: close。
Content-Length:该字段指明在RTSP协议最后一个标头之后的双 CRLF 之后的内容长度。例如在服务器响应DESCRIBE中,指明sdp信息长度
Content-Type:告诉客户端实际返回的内容的内容类型
Date:提供服务器生成响应的日期和时间,有助于客户端判断响应的新鲜度或进行时间同步。Date字段的格式符合RFC 1123,比如:Sat, 06 Apr 2024 11:15:00 GMT。
User-Agent: 该字段用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。
Expires:指明过期的时间
Rang: 用于指定一个时间范围,可以使用SMPTE、NTP或clock时间单元。
Session: Session头字段标识了一个RTSP会话。Session ID 是由服务器在SETUP的回应中选择的,客户端一当得到Session ID后,在以后的对Session 的操作请求消息中都要包含Session ID.例如:Session: 4581E0AE;timeout=65
Transport: Transport头字段包含客户端可以接受的传输选项列表,包括传输协议,地址端口,TTL等。服务器端也通过这个头字段返回实际选择的具体选项。如: Transport: RTP/AVP/TCPunicast;destination=192.168.31.222;source=192.168.31.222;interleaved=0-1
五、RTSP 响应错误码
RTSP的错误码和RTSP方法是强相关的,详细错误码信息如下:
| 错误码 | 原因短语 | 响应的方法 | 类别说明 |
|---|---|---|---|
| 100 | Continue | All | 信息响应:请求已接收,客户端应继续发送请求。 |
| 200 | OK | All | 成功响应:请求已成功被服务器接收、理解并接受。 |
| 201 | Created | RECORD | 请求已实现,并导致新资源被创建(如通过ANNOUNCE方法)。 |
| 250 | Low on Storage Space | RECORD | 请求成功,但服务器存储空间不足(警告)。 |
| 300 | Multiple Choices | All | 重定向响应:请求的资源有一系列可供选择的反馈信息。 |
| 301 | Moved Permanently | All | 请求的资源已被永久分配新的URI。 |
| 302 | Moved Temporarily | All | 请求的资源临时存在于另一个URI下。 |
| 303 | See Other | All | 对当前请求的响应可在另一个URI上找到。 |
| 305 | Use Proxy | All | 请求的资源必须通过代理访问。 |
| 400 | Bad Request | All | 客户端错误:请求存在语法错误,服务器无法理解。 |
| 401 | Unauthorized | All | 请求需要用户认证。 |
| 402 | Payment Required | All | 保留,未来可能使用。 |
| 403 | Forbidden | All | 服务器理解请求,但拒绝执行。 |
| 404 | Not Found | All | 服务器找不到请求的资源。 |
| 405 | Method Not Allowed | All | 请求行中的方法不被允许用于该资源。 |
| 406 | Not Acceptable | All | 请求内容无法被服务器接受。 |
| 407 | Proxy Authentication Required | All | 需要代理身份认证。 |
| 408 | Request Timeout | All | 服务器等待请求超时。 |
| 410 | Gone | All | 资源已消失。 |
| 411 | Length Required | All | 请求需要有效的Content-Length头。 |
| 412 | Precondition Failed | DESCRIBE, SETUP | 先决条件失败。 |
| 413 | Request Entity Too Large | All | 请求实体过大。 |
| 414 | Request-URI Too Long | All | 请求的URI过长。 |
| 415 | Unsupported Media Type | All | 不支持的媒体类型。 |
| 451 | Invalid parameter | SETUP | 服务器不支持请求中包含的参数。 |
| 452 | Illegal Conference Identifier | SETUP | 媒体服务器无法识别会议标识符。 |
| 453 | Not Enough Bandwidth | SETUP | 由于带宽不足,请求被拒绝。 |
| 454 | Session Not Found | All | 会话标识符丢失、无效或已超时。 |
| 455 | Method Not Valid In This State | All | 在当前状态下,客户端或服务器无法处理此请求。 |
| 456 | Header Field Not Valid | All | 服务器无法对所需的请求头执行操作。 |
| 457 | Invalid Range | PLAY | 给定的范围值(如播放范围)无效。 |
| 458 | Parameter Is Read-Only | SET_PARAMETER | 参数为只读,不可修改。 |
| 459 | Aggregate Operation Not Allowed | All | 请求的方法不能应用于聚合URL。 |
| 460 | Only Aggregate Operation Allowed | All | 请求的方法只能应用于聚合URL。 |
| 461 | Unsupported Transport | All | 传输字段包含不支持的传输规范。 |
| 462 | Destination Unreachable | All | 无法建立数据传输通道(目标不可达)。 |
| 500 | Internal Server Error | All | 服务器错误:服务器内部错误,无法完成请求。 |
| 501 | Not Implemented | All | 服务器不支持实现请求所需的功能。 |
| 502 | Bad Gateway | All | 服务器作为网关或代理时,从上游服务器收到无效响应。 |
| 503 | Service Unavailable | All | 服务不可用。 |
| 504 | Gateway Timeout | All | 网关超时。 |
| 505 | RTSP Version Not Supported | All | 服务器不支持请求中使用的RTSP协议版本。 |
| 551 | Option not supported | All | 服务器不支持Require或Proxy-Require字段中给定的选项 |
RTSP 推流与拉流全流程
- 信令阶段详细对比
| 步骤 | 推流(客户端 → 服务器) | 拉流(客户端 ← 服务器) | 核心差异 |
|---|---|---|---|
| OPTIONS | - 客户端发送 OPTIONS,查询服务器支持的推流方法(如 ANNOUNCE、RECORD)。- 服务器响应 Public 包含推流方法,确认支持。 |
- 客户端发送 OPTIONS,查询服务器支持的拉流方法(如 DESCRIBE、PLAY)。- 服务器响应 Public 包含拉流方法,确认支持。 |
方法集不同:推流需媒体描述提交,拉流需媒体描述获取,体现”上传”与”下载”的逻辑差异。 |
| 媒体描述 | - ANNOUNCE:客户端提交 SDP(含编码、轨道、客户端端口等,如 m=video 0 RTP/AVP 96,表示客户端推流的视频编码为 H.264)。- 服务器响应 200 OK,分配 Session ID。 |
- DESCRIBE:客户端请求服务器返回 SDP(含编码、轨道、服务器端口等,如 m=video 0 RTP/AVP 96,表示服务器拉流的视频编码为 H.264,与推流 SDP 一致)。- 服务器响应 200 OK,返回 SDP 并分配 Session ID。 |
数据流向:推流 SDP 由客户端生成(”告诉”服务器推流参数),拉流 SDP 由服务器提供(”询问”服务器拉流参数),确保两端媒体格式一致。 |
| 通道建立 | - SETUP:客户端协商发送端口(client_port 为客户端 RTP 发送端口,如 33354-33355,服务器接收)。- 服务器响应 200 OK,返回服务器接收端口(如 33712-33713)。 |
- SETUP:客户端协商接收端口(client_port 为客户端 RTP 接收端口,如 19354-19355,服务器发送)。- 服务器响应 200 OK,返回服务器发送端口(如 32708-32709)。 |
端口方向:推流 client_port 是发送端(客户端 → 服务器),拉流 client_port 是接收端(服务器 → 客户端),传输角色完全反转。 |
| 数据启动 | - RECORD:客户端发送请求,开始向服务器推送 RTP 数据(如 H.264 视频帧,通过 client_port 发送到服务器 server_port)。- 服务器响应 200 OK,进入接收状态。 |
- PLAY:客户端发送请求,服务器开始向客户端拉取 RTP 数据(如 H.264 视频帧,通过 server_port 发送到客户端 client_port)。- 服务器响应 200 OK,进入发送状态。 |
动作主体:推流由客户端主动发送数据(”上传”),拉流由服务器主动发送数据(”下载”),数据流向相反。 |
| 会话终止 | - TEARDOWN:客户端发送终止请求,服务器释放推流资源(端口、缓存、Session)。- 服务器响应 200 OK,确认终止。 |
- TEARDOWN:客户端发送终止请求,服务器释放拉流资源(端口、缓存、Session)。- 服务器响应 200 OK,确认终止。 |
一致:均终止会话,确保资源释放,流程对称。 |
- RTP 数据传输对比4f
| 维度 | 推流(客户端 → 服务器) | 拉流(服务器 → 客户端) | 核心差异 |
|---|---|---|---|
| 方向 | RTP 包从客户端端口(如 33354)发送到服务器端口(如 33712) |
RTP 包从服务器端口(如 32708)发送到客户端端口(如 19354) |
完全反转:推流是”上传”,拉流是”下载”,源/目的端口互换。 |
| 载荷内容 | 客户端生成的媒体数据(如摄像头采集的 H.264 视频帧,通过编码器封装为 RTP) | 服务器转发的媒体数据(如从推流端接收的 H.264 视频帧,或本地存储的媒体流,封装为 RTP) | 数据来源:推流数据由客户端生成,拉流数据由服务器提供(可能来自推流端或存储)。 |
| SSRC 标识 | 客户端生成的 SSRC(如 0x57efa63f,标识推流源)。 |
服务器生成的 SSRC(如 0x174EADA,标识拉流源,与推流 SSRC 不同) |
流识别:推流和拉流的 SSRC 独立,避免服务器混淆不同方向的流(如直播中推流端和拉流端的 SSRC 唯一)。 |
SSRC 定义
推流场景:由 客户端(Client) 生成,用于标识推流的媒体流源(如摄像头采集的视频流)。RTP 包中携带客户端生成的 SSRC(如 0x57efa63f),服务器通过此识别推流来源。
拉流场景:由 服务器(Server) 生成,用于标识拉流的媒体流源(如服务器转发的直播流)。RTP 包中携带服务器生成的 SSRC(如 0x174EADA),客户端通过此区分不同拉流轨道。
作用:唯一标识媒体流,避免服务器混淆多推流端的流,或客户端混淆多轨道的拉流数据(如音视频轨道分别有独立 SSRC)。Session ID 来源
推流:客户端发送 ANNOUNCE 后,服务器(Server) 在响应中分配 Session ID(如 e0CEYZFLTePM)。后续 SETUP、RECORD、TEARDOWN 均需携带此 ID,确保推流会话的上下文一致性(如端口协商、资源释放绑定到同一会话)。
拉流:客户端发送 DESCRIBE 后,服务器(Server) 在响应中分配 Session ID(如 iTZh5j8EIkgx)。后续 SETUP、PLAY、TEARDOWN 携带,绑定拉流会话(如媒体描述、通道协商属于同一拉流任务)。
作用:跟踪会话生命周期,管理资源(如端口、缓存),避免跨会话操作(如误终止其他推流/拉流任务)。Transport 字段解析
格式示例(推流):
RTP/AVP/UDP;unicast;client_port=33354-33355;server_port=33712-33713;ssrc=0x57efa63f
协议:RTP/AVP/UDP 表示 UDP 传输 RTP 载荷(音频/视频)。
模式:unicast 单播(一对一传输,适合直播场景)。
端口:
client_port:客户端 发送端口(推流数据从这里发出,如 33354 为 RTP,33355 为 RTCP)。
server_port:服务器 接收端口(如 33712 为 RTP,33713 为 RTCP,接收推流数据)。
SSRC:客户端生成的推流 SSRC(标识此流来源)。
拉流格式示例:
RTP/AVP/UDP;unicast;client_port=19354-19355;server_port=32708-32709;ssrc=0x174EADA
端口方向反转:client_port 为客户端 接收端口(拉流数据到这里),server_port 为服务器 发送端口(拉流数据从这里发出)。
作用:协商 RTP/RTCP 的 传输协议、模式、端口对,明确数据流向(推流:C→S;拉流:S→C),是媒体通道建立的核心配置。RTP 时间戳与 rtptime
时间戳单位:RTP 时间戳以 90kHz 为单位(1 单位 = 1/90000 秒),适用于视频帧同步(H.264 等编码的时间基准)。
作用:
流内时序:RTP 包时间戳递增(如 23439 → 23440),确保媒体帧按序播放(避免乱序导致的画面卡顿)。
抖动缓冲:客户端计算时间戳间隔(ΔT = (当前时间戳 - 前一时间戳)/90000),调整缓冲大小(如 ΔT 过大时增加缓冲,减少丢包影响)。
rtptime:在 PLAY 响应的 RTP-Info 中(如 rtptime=0),表示 RTP 流的 初始时间戳。客户端以此为基准,解析后续包的时间戳(避免时间戳偏移,确保流起始同步)。音视频同步(AV Sync)
时间戳统一:音视频流的 RTP 包使用 同一时间戳源(如推流端的系统时钟),确保音频和视频帧的时间戳一致(如音频 T_audio 与视频 T_video 同步,|T_audio - T_video| < 阈值)。
客户端处理:
缓冲调整:对音频和视频分别设置缓冲,根据时间戳差异调整播放顺序(如先播放时间戳小的帧,后播放大的,实现唇音同步)。
RTSP 辅助:PLAY 响应的 Range 字段(如 npt=0.000-)定义播放范围,客户端基于此初始化同步(从时间戳 0 开始,避免流进度偏移)。NPT(Normal Play Time)
定义:标准化播放时间(以秒为单位),用于 RTSP 控制媒体流的播放范围(如 SEEK npt=10.0 跳转到第 10 秒)。
作用:
会话控制:在 PLAY(启动播放)、PAUSE(暂停)、SEEK(跳转)中,通过 NPT 精确控制播放位置(如直播回放的时间跳转)。
时间映射:NPT 与 RTP 时间戳通过 SDP 中的 clock-rate 关联(NPT = RTP 时间戳 / clock-rate),实现逻辑时间(NPT)与物理时间(RTP 时间戳)的转换,确保用户可见的播放时间与编码层时间一致。
总结
SSRC:推流由客户端定义,拉流由服务器定义,唯一标识流源。
Session ID:由服务器在媒体描述阶段(ANNOUNCE/DESCRIBE)分配,绑定会话。
Transport:协商 RTP 传输的协议、端口和方向,是媒体通道建立的关键。
RTP 时间戳:确保流内时序和音视频同步,rtptime 初始化流时间基准。
NPT:标准化播放时间,实现流的进度控制和时间映射,提升用户体验
常用分析工具
| 项目 | 说明 | 备注 |
|---|---|---|
| MediaInfo | 视频信息查看工具 | |
| VLC media player | 视频流播放工具 | |
| wireshark | 网络抓包工具 | |
| cooledit pro2 | 音频编辑工具、PCM播放工具 | |
| Elecard StreamEye Tools | 分析视频帧的工具 |
抓包工具:easyTshark(基于wireshark)
网络流量分析和还原suricata
https://online.easytshark.com