0%

RTSP协议及其推拉流

随着时代的发展,现在安防系统都需要通过通用浏览器来观看监控画面。但大部分安防系统使用的都是RTSP协议的摄像头,但相通过浏览器接收视频流必须使用WebRTC协议,显然传输协议的不同导致它们无法直接实现互联互通。

既然通过底层传输协议无法互通,那有没有其它方案呢?

RTSP与WebRTC互通

当然是有的,其中最为成熟的一种方案是通过服务器中转实现两者的互通,架构如下所示:

上面的架构还可再简化,将RTSP服务与WebRTC服务融合到一起,这样当两个不同的终端连接到同一个服务器节点时,就可以在其内部直接转流,效率更高。

关于WebRTC协议、应用、源码等相关的内容我之前已经说了很多,有兴趣的同学可以翻看一下我以前的文章,今天我重点讲讲RTSP。

RTSP协议

RTSP(Real Time Streaming Protocol)是一个非常古老的协议,它与SIP协议类似,分为信令和传输两部分。其中信令用于建立数据通道,而传输用于发送音视频数据。

首先咱们来看一下RTSP信令相关的内容,RTSP协议支持以下几种信令:

  • OPTIONS:用于查询服务器支持的RTSP方法,类似于HTTP的OPTIONS方法。
  • DESCRIBE:用于客户端从服务端获取流媒体资源的描述信息,通常使以SDP格式来表示,包含媒体类型、编码格式、传输协议、目标地址、端口号等信息。
  • ANNOUNCE:用于客户端发布新的流媒体描述信息,它将这些信息存放在SDP文件中,并传给服务端。
  • SETUP:用于建立流媒体传输的会话,指定传输协议、端口号、通道号等参数。而且需要为每个媒体流单独发送一次SETUP信令。这就是为什么我们抓包时会看到发送多次SETUP信令的原因。
  • RECORD:用于向服务端推流。开始或恢复流媒体推流,并通过它指定录制的范围和速度等参数。类似于拉流中的PLAY信令。
  • PLAY:用于开始或恢复流媒体的播放,并通过它指定播放的范围和速度等参数。
  • PAUSE:用于暂停流媒体的播放,并通过它指定暂停的位置等参数。
  • TEARDOWN:用于终止流媒体的会话,释放相关的资源。
  • GET_PARAMETER:用于获取流媒体资源的参数值。
  • SET_PARAMETER:用于设置流媒体资源的参数值。
  • REDIRECT:用于重定向流媒体的会话,指定新的服务地址和生效时间等参数,通常由服务器向客户端发送。

RTSP协议支持的信令还是蛮简单的,那么如何使用这些信令进行音视频的推拉流呢?

向服务端推流

下面我就详细描述一下如何使用RTSP协议推/拉音视频流。RTSP客户端向RTSP服务端推流的过程如下图所示:

在推流之前,RTSP客户端向服务端发送OPTIONS信令,查询服务端支持哪些RTSP信令。服务端收到OPTIONS信令后,将其所支持的所信令发送给客户端,如OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, RECORD, SET_PARAMETER, GET_PARAMETER。

之后客户端向服务端发送ANNOUNCE信令,并带上推送流的描述信息,也就是SDP文件(关于SDP相当的内容我将在后面向你做详细介绍)。服务端收到ANNOUNCE信令并成功解析SDP文件后,向客户端返回200,表示成功。

再下来,客户端向服务端发送SETUP信令。需要注意的是,推送的每一路媒体流都要发送一个SETUP信令,如推送了一路音频和一路视频,那么就要发送两个SETUP,一个是音频的SETUP,另一个是视频的SETUP。

当分别收到音频和视频SETUP的成功响应消息后,客户端需要发送RECORD信令,告之服务端马上我就开始向你推流了。

同样的,当客户收到服务端的RECORD成功响应消息后,RTSP客户端就开始向服务器发送音视频流了。至此,我们就将RTSP推流的过程介绍清楚了,下面咱们再来看一下RTSP客户端拉流的过程。

从服务端拉流

RTSP客户端从服务器上拉流的过程与推流过程是类似的,如下图所老示:

它还是先发送OPTIONS信令向服务器查询其所支持的信令。之后发送DESCRIBE信令获取可以拉取的音视频流,服务端收到DESCRIBE信令后,返回成功的Reply消息,同时将可以获取的媒体信息以SDP的格式返回。

RTSP客户端收到SDP数据后,对其进行解析,取出可以拉取的音视频流信息,之后为每一路媒体发送一个SETUP信令到服务器。紧接着,发送PLAY信令到服务端拉取音视频流,当收到服务端返回的成功消息后,就可以接收数据了。

以上就是RTSP客户端拉流的基本流程。再接下来咱们了解一下RTSP协议中使用的SDP数据格式。

SDP

SDP(Session Description Protocol),也是一种比较老的协议,它是一种描述会话的协议。

它由两部分组成,会话层和媒体层。会话层包括版本、名子、会话时间等内容,而且在SDP中只有一个会话层。媒体层用来表示此次会话包括哪些媒体,如音频、视频。在SDP中可以包括多个媒体层,而且SDP主要描述的就是媒体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 59.33.100
m=video 0 RTP/AVP 96
b=AS:3298
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=J2QAKqxWwHgCJ+WagICAgQ==,KO48sA==; profile-level-id=64002A
a=control:streamid=0
m=audio 0 RTP/AVP 97
b=AS:319
a=rtpmap:97 MPEG4-GENERIC/48000/2
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=1190
a=control:streamid=1

如上这段代码就是一段标准的SDP内容。其中第一个m=行之前的内容属于会话层,之后的属于媒体层。例子中包括两个媒体描述,一个是对视频的描述,另一个是对音频的描述。

m=video 0 RTP/AVP 96表示是对视频的描述,它指明使用的传输协议是 RTP,AVP(Audioa Video Profile)表示RTP包中的数据格式是由后面定义的。另外,数据负载类型,也就是PayloadType为96。

再下来,b=AS:3298表示带宽的最大值是3298,AS是Application Specific的意思。

a=rtpmap:96 H264/90000是媒体属性的描述,它指明视频(PT = 96)使用的是H264编码,时钟频率是 1/90000。

a=fmtp:96 packetization-mode=1; ...的作用是设置H264编码参数。

a=control:streamid=0指定控制媒体流播放、暂停等操作的streamid。

后面m=audio 0 RTP/AVP 97是对音频的描述,各参数的含义与视频类似,这里我就不做赘述了。

搭建RTSP环境

现在有不少开源的RTSP服务器可以搭建RTSP环境,比较有名的如 EasyDarwin、ZLMediaKit等。

这里我以ZLMediaKit为例简单介绍一下如何使用它来搭建RTSP环境,具体步骤如下:

  • 下载ZLMediaKit源码
  • 编译ZLMediaKit
  • 运行ZLMediaKit

我们可以通过下面的命令完成上面三步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#国内用户推荐从同步镜像网站gitee下载 
git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
cd ZLMediaKit
#千万不要忘记执行这句命令
git submodule update --init

#编译ZLMediaKit
cd ZLMediaKit
mkdir build
cd build
cmake ..
make -j4

#运行ZLMediaKit
cd ZLMediaKit/release/xxx/debug
./MediaServer -d &

当ZLMediaKit运行起来后,我们就可以使用ffmpeg命令进行推流了,推流命令如下:

1
ffmpeg -re -i xxx.mp4 -c:v copy -c:a copy -f rtsp -rtsp_transport udp rtsp://127.0.0.1/live/test

这条命令中各参数的含义如下:

  • re,按视频帧率推流
  • i,指定推流的多媒体文件
  • c:v,指定视频编解码器。copy 表示不进行编解码,直接用原来的数据
  • c:a,指定音频编解码器
  • f,指定使用的协议类型
  • rtsp_transport,指定传数数据时使用的协议

RTSP流推送成功后,我们可以使用ffplay来拉流观看,拉流命令如下:

1
ffplay rtsp://127.0.0.1/live/test

拉取RTSP流还是比较简单的,直接告诉ffplay拉流的地址即可。

这里需要说明一下,当我们使用ffmpeg推流时,在其内部就会发送前面我们所讲的RTSP信令,开始与RTSP服务器进行协商要传送哪些流。协商时,就会将要推送的音视频流信息整合到SDP中,并将合成好的SDP发送给服务端。服务端成功解析SDP文件后,会根据里边的媒体信息创建通道,并在ffplay拉流时,将接收到的数据中转给ffplay进行播放。

RTSP与WebRTC互通

刚才我介绍的ZLMediaKit也是支持WebRTC协议的,但对WebRTC协议支持到哪种程度我并没有进行测试。不过大体原理还是很简单的,当一个WebRTC客户端连到ZLMediaKit上来之后,它会通过URL告之ZLMediaKit要观看(拉取)哪路流。

之后,ZLMediaKit会将通过RTSP协议收到的音视频包按WebRTC的要求重新打包,之后转发给WebRTC客户端,这样WebRTC客户端就可以看到通过RTSP协议上传的音视频流了。

这里有的细节暂时我就不深入剖析了,等后面有时间的时间再向大家做详细的介绍。

小结

本文重点讲解了RTSP协议的工作流程,让你知道向RTSP服务器推流和拉流的具体步骤是怎样的。特别是有些企业希望通过浏览器监控RTSP摄像头的功能,目前已经有了非常好的解决方案。

当然本文对RTSP的分析主要是从宏观的角度出发的,很多细节都没有触及,比如说如何解析SDP,发送信令和应答信令时要主意CSeq的对应关系等。如果你对这些细节比较感兴趣的话,可以翻看一下EasyDarwin或ZLMediaKit代码,它们的实现都不复杂,可以让你更快速的了解具体细节。

欢迎关注我的其它发布渠道