本文主要介绍使用 WVP
+ZLMediaKit
+MediaServerUI
实现通过 GB28181
进行海康、大华、宇视等品牌的 IPC
、NVR
、DVR
接入,完成摄像头监控播放,控制,录制。
一、概念
IPC是(IP Camera 即网络摄像机)缩写,由网络编码模块和模拟摄像机组合而成。网络编码模块将模拟摄像机采集到的模拟视频信号编码压缩成数字信号,从而可以直接接入网络交换及路由设备。
NVR是(Network Video Recorder即网络硬盘录像机)缩写,主要是通过网络接收IPC设备传输的数字视频码流, 并进行存储、管理。 通过Nvr,可同时观看、浏览、回放、管理、存储多个网络摄像机。
DVR是(Digital Video Recorder即数字视频录像机)缩写,采用硬盘录像,被称为硬盘录像机。它是一套图像计算存储处理的计算机系统,具有对图像/语音和动态帧等进行长时间录像、录音、远程监视和控制的功能,DVR集合录像机、画面分割器、云台镜头控制、报警控制、网络传输等五种功能于一身,用一台设备就能取代模拟监控系统一大堆设备。
DVR将模拟视频进行数字化编码压缩并储存在硬盘上,主要涉及编码及储存技术,与网络传输关系不大,因此DVR常安装在模拟摄像机附近。而NVR从网络上获取经编码压缩的视频流然后存储转发,因此在NVR设备上一般看不到视频信号的直接连接,其输入、输出都是已编码并添加了网络协议的IP数据。
二、准备工作
1.服务运行环境,Linux / OS X / Windows 均可,但推荐 Linux
2.海康云台摄像头一个
3.运行 sip
服务 WVP
https://github.com/swwheihei/wvp-GB28181
4.运行流媒体服务 ZLMediaKit
https://github.com/xiongziliang/ZLMediaKit
5.运行前端展示项目 MediaServerUI
https://gitee.com/kkkkk5G/MediaServerUI/tree/gb28181/
三、运行 WVP
3.1 安装 Redis
WVP 项目中将设备信息等存放在 Redis 中,所以需安装 Redis。
3.2 配置运行 SIP
首先修改 WVP 项目配置文件:
spring:application:name: iot-vmp-vmanager# 影子数据存储方式,支持redis、jdbcdatabase: redis# 通信方式,支持kafka、httpcommunicate: httpredis: # Redis服务器IPhost: 127.0.0.1#端口号port: 6379datebase: 0#访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接password: 123123#超时时间timeout: 10000datasource: name: eioturl: jdbc:mysql://host.docker.internal:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=trueusername: rootpassword: 123456type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driver
sip:# SIP 所在服务IP,就是本机IPip: 192.168.1.102port: 5060# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)# 后两位为行业编码,定义参照附录D.3# 3701020049标识山东济南历下区 信息行业接入domain: 3701020049id: 37010200492000000002# 默认设备认证密码,后续扩展使用设备单独密码password: 123456
media:# 流媒体服务的IP,内网测试可填内网IP,公网填公网服务器IP并放开端口ip: 177.11.11.111port: 10000
然后登录海康摄像头管理页面,修改配置:
平台接入选择 28181
;传输协议可自选,公网建议TCP;协议版本选择 GB/T28181-2016
(目前WVP只支持该协议,2011后会适配)
SIP服务器ID
和 SIP服务器域
,密码
要和 WVP
项目配置的一致。
SIP服务器地址
填写 WVP
项目的地址,内网写内网IP地址,云服务器填写公网IP,端口写配置文件中配置的端口。
因为摄像头平台接入配置好后,摄像头会请求 SIP 服务,所以这个一定要配置好。
配置完后就可运行项目了!如果 SIP 服务启动成功后,会看到这个日志 “Sip Server 启动成功”
如果摄像头连接到 SIP
服务,项目日志如下,显示 200 OK(公网服务器记得放开sip端口):
建立好连接后,就可控制查询摄像头了。
GET /api/devices
查询所有设备信息
[{"deviceId":"37010200492000000001","name":"IP DOME","manufacturer":"Hikvision","model":"DS-2DC4223IW-D/GLT","firmware":"V5.6.15","transport":"TCP","host":{"ip":"192.168.1.101","port":1609,"address":"192.168.1.101:1609"},"online":1,"channelMap":{"34020000001320000001":{"channelId":"34020000001320000001","name":"IPdome","manufacture":"Hikvision","model":"IP Camera","owner":"Owner","civilCode":"37010123123","block":null,"address":"Address","parental":0,"parentId":null,"safetyWay":0,"registerWay":1,"certNum":null,"certifiable":0,"errCode":0,"endTime":null,"secrecy":"0","ipAddress":null,"port":0,"password":null,"status":1,"longitude":0,"latitude":0}}}
]
POST /api/ptz/{deviceId}/{channelId}
云台控制指定设备通道
http://127.0.0.1:8080/api/ptz/34020000001320000001/34020000001320000001?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=1
zoomSpeed 的数字不能太大,不然运行不了,无效。
WVP 项目所有接口:https://github.com/swwheihei/wvp-GB28181/wiki/API-%E6%8E%A5%E5%8F%A3
四、运行流媒体服务 ZLMediaKit
4.1 获取代码
#国内用户推荐从同步镜像网站gitee下载
git clone --depth 1 https://gitee.com/xiahcu/ZLMediaKit
cd ZLMediaKit
#千万不要忘记执行这句命令
git submodule update --init
4.2 构建项目
项目开发者提供了三个shell脚本在项目根目录:
- build_docker_images.sh 构建为docker镜像
- build_for_linux.sh linux下构建项目
- build_for_mac.sh mac下构建项目
打开以后看到是用CMake编译的,可直接选择运行shell脚本。
构建好后打开 release/xx/Debug
目录,看到 config.ini
是项目的配置文件:https://github.com/xiongziliang/ZLMediaKit/blob/master/conf/config.ini
其中需要特别注意的有两个地方:
一是 [http] 的 port,因为 ZLMediaKit 项目也有很多 API 接口,都要通过这个接口访问,都是这个端口,可自行配置。
二是 [rtp_proxy] 的 port,是上面 SIP 项目配置的 media.port
4.3 运行项目
Linux 下启动:
cd ZLMediaKit/release/linux/Debug
#通过-h可以了解启动参数
./MediaServer -h
#以守护进程模式启动
./MediaServer -d &
使用守护进程模式启动后,通过 ps -axj
来查看进程
运行成功后有如下日志:
可做推流测试,非必须操作,,具体操作查看文档:https://github.com/xiongziliang/ZLMediaKit/wiki/ZLMediaKit%E6%8E%A8%E6%B5%81%E6%B5%8B%E8%AF%95
下载个视频文件 big_buck_bunny.mp4
放在当前目录上,用rtp方式推流,在文件所在目录输入命令(需要先安装ffmpeg):
ffmpeg -re -i "big_buck_bunny.mp4" -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
运行后,查看 ZLMediaKit 项目有类似这样的日志:
使用可播放流的播放器(如:PotPlayer,IINA)打开 http://服务器IP/rtp/xxxxx.flv
就能播放了。
如 http://服务器IP/rtp/061484E1.flv
项目推流
SIP
服务和流媒体服务就绪了,就可以推流了。用 /api/devices
查到 deviceId 和 channelId,然后调 SIP
服务的播放接口
GET /api/play/37010200492000000001/34020000001320000001
预览指定设备通道的音视频
成功调用后会返回ssrc:
{"ssrc":"0102008033"}
ssrc 转换为16进制后为 061484E1
查看流媒体服务的日志如下:
注:公网服务器如没收到推流日志,记得开放端口并检查 wvp
项目的 media
配置是否正确。
那怎么拿到播放地址呢?https://github.com/xiongziliang/ZLMediaKit/wiki/%E6%92%AD%E6%94%BEurl%E8%A7%84%E5%88%99
如果公网IP是177.11.11.111,转换过来就是:
rtsp://177.11.11.111:554/rtp/061484E1?token=abcdefg&field=value
rtmp://177.11.11.111/rtp/061484E1
http://177.11.11.111/rtp/061484E1.flv
http://177.11.11.111/rtp/061484E1/hls.m3u8
此外 ZLMediaKit 还提供录制,截图,动态添加拉流代理等功能。
五、运行MediaServerUI
拉下项目代码:https://gitee.com/kkkkk5G/MediaServerUI/tree/gb28181/
项目启动后,SIP
服务调用 play 接口,流媒体服务收到消息,在项目的“视频广场”中就能看到视频了。
该项目需注意配置,本项目和流媒体服务关联的,调用接口也是流媒体 ZLMediaKit 的 API。
打开项目根目录下的 global.js
:
const serverip="172.16.63.208"
const host = 'http://' + serverip + '/index/api';
const secret = '035c73f7-bb6b-4889-a715-d9eb2d1925cc';
const baseMediaUrl='ws://' + serverip + '/';
function genApiUrl(method){return host+method+"?secret="+secret;
}
export default{serverip,host,secret,genApiUrl,baseMediaUrl
}
serverip是流媒体服务IP,如果 ZLMediaKit 配置文件中 [http] 配置项的端口改成其它,记得在这里加端口号。
secret
需要和流媒体服务配置一样。
baseMediaUrl
是拉流的url,可改成如 rtsp,rtmp,http。
六、整个视频请求的流程图
其中流媒体模块指 ZLMediaServer
,接口模块与信令模块指 WVP
,视频设备指 IPC、NVR
七、FFmpeg 源码结构
FFMPEG中结构体很多。最关键的结构体分成以下几类:
a) 解协议(http,rtsp,rtmp,mms)
AVIOContext,URLProtocol,URLContext主要存储视音频用的协议类型及状态。URLProtocol存储输入视音频使用的封装格式。每种协议都对应个URLProtocol结构。(注意:FFMPEG中文件也被当做一种协议“file”)
协议 | httpflv | rtmp | hls | dash |
---|---|---|---|---|
传输方式 | http流 | tcp流 | http | http |
视频封装格式 | flv | flv tag | Ts文件 | Mp4 3gp webm |
延时 | 低 | 低 | 高 | 高 |
数据分段 | 连续流 | 连续流 | 切片文件 | 切片文件 |
Html5播放 | 通过html5解封包播放(flv.js) | 不支持 | 通过html5解封包播放(hls.js) | 如dash文件列表是mp4webm文件,可直接播放 |
-
用HTTP方式: 通过服务器将FLV下到本地,然后通过NetConnection的本地连接播放,这种方法是播放本地视频,在本地缓存可找到该FLV。
将直播流模拟成FLV文件,通过HTTP协议下载模式实现流媒体传输的协议,端口号80。建议用HTTP FLV,实时性和RTMP相等。
优点:服务器下完FLV,服务器就无消耗了,节省服务器消耗,HTTP比RTMP省去协议交互时间,首屏时间更短。HTTP可拓展;
缺点:FLV缓存客户端,对FLV保密性不好。 -
用RTMP方式: 通过NetConnection连到FMS(Flash Media Server)或Red5服务器,并实时播放服务器FLV文件,可任意选择视频播放点,并不象HTTP方式需缓存整个FLV文件到本地才可选择播放点。
由上可知,Http方式是本地播放,而RTMP方式是服务器实时播放。目前的CDN都是基于RTMP的。端口号1935,网络用户均可用,包括非IOS平台用户,对非80端口(如1935)无限制的网络环境用户。
RTMP(Real Time Messaging Protocol 实时消息传输协议),是 Adobe Systems 公司为 Flash 播放器与服务器音频、视频和数据传输开发的开放流媒体传输协议。
RTMP 协议基于 TCP,是个协议族,包括 RTMP 基本协议及 RTMPT/RTMPS/RTMPE 等变种,由Adobe公司为Flash播放器和服务器之间音频、视频传输开发的实时数据通信的网络协议。
优点:FLV 不缓存在客户端,FLV 保密性好,防 HTTP 下载,延时短;
缺点:消耗服务器资源,连接始终是实时的。 -
RTSP: RTSP 1.0标准没预测到互联网的快速增长 、IPv4 地址短缺导致的 NAT 技术广泛使用 及代理服务器大量存在,它在传输可靠性和易用性上都有缺陷。虽然各家厂商都有修补,如支持 RTSP over HTTP、NAT 穿透等,但2005 网络视频大爆炸时,RTSP 1.0并没得到youtube, hulu, 土豆,优酷等视频服务提供商的青睐,相反,Adobe公司的私有流媒体技术 RTMP 以其优秀的易用性和富媒体的一体化集成,得到多数视频服务提供商追捧,成为事实的标准.
缺点:web端播放rtsp流的话,需写插件,且对浏览器也很挑剔,flash不支持rtsp,需做 activeX 插件
-
HLS(Http Living Streaming): 是苹果公司实现的基于 HTTP 的流媒体传输协议。2010 苹果在 iOS 设备支持”Live HTTP”的流媒体技术,并不再支持 RTSP 和 Flash 。Live HTTP 本质跟基于 HTTP 的文件分段下载接近。在带宽充裕时,live HTTP 能实现跟RTSP和RTMP同样的流媒体播放效果,有更好的易用性,更简单的控制。在HTML5中,视频文件的点播也采用HTTP作为其承载协议。
HLS 可支持流媒体的直播和点播,主要应用在 iOS 系统,为 iOS 设备(如 iPhone、iPad)提供音视频直播和点播方案。
HLS: IOS平台下的流媒体传输协议 ,端口号80
优点:H5浏览器支持较好,IOS,安卓原生支持。
缺点:延迟较大。HLS 基本原理是当采集推流端将视频流推送到流媒体服务器时,服务器将收到的流信息每缓存一段时间就封包成一个新 ts 文件,同时服务器建立个 m3u8 索引文件来维护最新几个 ts 片段索引。当播放端获取直播时,它是从 m3u8 索引文件获取最新 ts 视频文件片段播放,保证用户在任何时候都看到较新内容,实现近似直播体验。相对于常见流媒体直播协议,如 RTMP 协议、RTSP 协议等,HLS 最大不同在于直播客户端获取到的并不是个完整的数据流,而是连续的、短时长的媒体文件,客户端不断的下载并播放这些小文件。这种方式理论最小延时为一个 ts 文件的时长,一般情况为 2-3 个 ts 文件的时长。HLS 分段策略,基本上推荐是 10 秒一个分片,这就看出了 HLS 的缺点:
- 通常 HLS 直播延时会达到 20-30s,而高延时对需实时互动的直播是不可接受的。
- HLS 基于短连接 HTTP,意味着 HLS 需不断与服务器建立连接,TCP 每次建立连接时的三次握手、慢启动过程、断开连接时的四次挥手都会产生消耗。
不过 HLS 也有它的优点:
- 数据通过 HTTP 协议传输,采用 HLS 时不用考虑防火墙或代理问题。
- 使用短时长的分片文件播放,客户端可平滑的切换码率,以适应不同带宽的播放。
- HLS 是苹果推出的流媒体协议,iOS 平台获得天然的支持,采用系统提供的 AVPlayer 就能直接播放,不用开发播放器。
-
HTTP FLV 则是将RTMP封装在HTTP协议之上,可更好的穿透防火墙等。
目前,有两种Http-Flv的实现方式:一种是基于文件方式,一种是基于包方式
Http_flv & RTMP
这两个协议实际传输的数据一样,数据都是flv文件的tag。http_flv是个无限大的http流文件,只能直播,而rtmp还可推流和更多操作。但http的好处是以80端口通信的,穿透性强,且rtmp是非开放协议。
这两个协议是如今直播平台主选的直播方式,主要原因是延时极低。
RTMP延迟1s左右,HTTPFLV延迟1-2s左右,可用于对延迟较苛刻的场景,但要注意兼容性。
b) 解封装(flv、avi、rmvb、mp4)
AVFormatContext 主要存储视音频封装格式中的信息;AVInputFormat 存储输入视音频用的封装格式。每种视音频封装格式都对应个AVInputFormat 结构。
c) 解码(h264、mpeg2、aac、mp3)
每个 AVStream 存储一个视频/音频流的相关数据;每个 AVStream 对应个AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个AVCodecContext 中对应一个AVCodec,包含该视频/音频对应的解码器。每种解码器都对应个AVCodec结构。
d) 存数据
视频一般每个 AVPacket 是一帧;音频可能有好几帧
解码前数据:AVPacket(h264、aac)
解码后数据:AVFrame(yuv、pcm)
他们间的对应关系如下: