随着时代的发展,现在安防系统都需要通过通用浏览器来观看监控画面。但大部分安防系统使用的都是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 | v=0 |
如上这段代码就是一段标准的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 | 国内用户推荐从同步镜像网站gitee下载 |
当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代码,它们的实现都不复杂,可以让你更快速的了解具体细节。