前言
rtsp的视频流调取是一个非常常见的应用场景。在具体的实施过程中,更多的是通过客户端或者浏览器插件实现的。但是,这些主流技术都需要装这个或者那个,这是很不爽的。在实际的场景中,还是希望可以通过html页面直接打开。
- 客户端:一般来说各自厂商都会提供这样的客户端。但是,这个客户端对于我系统的集成和接入其实是非常不友好的,所以我们就此略过不提。
- flv插件:主流的主要是flv实现的插件。flv这东西,马上所有浏览器就都不支持了,也就不考虑了。
- 收费插件:其实不是flv实现的插件也是有的,但基本都是收费的。破解就不考虑了,毕竟主要考虑商业用途,剑走偏锋的就算了。
- 收费服务:典型的有h5Stream。我们合作的外包公司为了快速解决问题用的就是它们家的服务。结果没有license,只能持续使用一个小时。现在服务器上还是用的定时任务重启(总有对策的嘛,开句玩笑,本次折腾就是为了解决这个问题)
之前一直被事情压着,没有时间和精力来静下来心来详细调试这件事。这次专门腾出一周的时间来搞定这个问题。好了,废话到此为止,开整。
搭建视频环境
其实这件事之所以是问题是因为我们播放的是摄像头通过录像机出来的视频,格式是rtsp的视频流。这个视频流无法在web端直接被解析,于是才有了各种各样的客户端(无论是系统客户端还是插件,都是此类)。另一种思路就是将rtsp转码成web段能播放的视频流,于是就有了各种收费免费的服务,坑了我们的h5Stream就属于此列。当然,转码的方案是有延迟的。不过这种延迟,在视频解决方案中是常见的,还是看具体使用场景的要求把,一般来说,秒级别的其实都是可以接受的,毕竟视频传输光带宽就会造成不小的延迟。
为此,我们先搭建一个套视频环境。之所以会在这里专门开章节写这个,也是因为这其中有坑,我都至少趟过两遍了,每次都忘了上次怎么回事。
先说设备:
摄像头
海康威视DS-IPC-B12-l,类型是网络摄像机,属于枪机。大概长下图这个样子
前面镜头的部分就不说了,平常见得多。大多数不知道的是后面这两个插头。从样子上来说就可以判断出来,一个是网口,一个是直流供电口。有些交换机的网口是可以进行POE供电的。这个时候就不需要插供电口就可以直接驱动摄像头,否则的话就需要插上供电口进行供电。
网络硬盘录像机(NVR)
海康威视DS-7804NB-K1/4P,设备类型是网络硬盘录像机。摄像头其实就是单纯的通过镜头捕捉画面,将画面通过网线传输出来的设备。对于摄像头有一系列的管理和操作,这个时候我们就需要一台录像机来做这些事情。可以把网络录像机理解成摄像头专有的服务器。离开了录像机,理论上来说也能使用摄像头,但是面对的是一零散的需求,就不太好弄了。管理数量多的摄像头也不好管理。我们这次的rtsp的视频流就是从录像其中拉取的,而不是直接从摄像头里面。
录像机上面还是有很多接口的,背面大概长下面这个样子:
没错,前面摄像头照片下面那个就是录像机,这张图片里面主要照了下背面。背面有四个网口,都带POE供电,有VGA和HDMI口,可以接摄像头。有个USB口,正面还有一个usb口,可以接鼠标键盘。右边这个单独的网口是将录像机接入网络的网口。最右边是电源口。录像机在显示器中的界面如下所示:
上面这个图可能很多人都是见过的。没错,这个是直接从录像机接出来画面。
接线
接线图大约如下:
基本的逻辑就是,网络录像机的摄像头网口连接摄像头,自身的网口连接局域网。另外可以接入显示器、鼠标、键盘控制对录像机设备进行控制。
而我的电脑需要和网络录像机接入统一个网络,才能确保自己能访问到我需要的视频流。
访问视频流
访问工具
我们要打开的视频流是rtsp的视频流,并不是什么客户端都能打开的。推荐下载一个VLC的播放器,调试这东西,这个播放器还是很好用的。VLC官网
访问视频流
这是一个我被坑的核心环节。首先,我们看看在哪里可以看到我们的视频流的访问地址。去我们的录像机里找找。
首先进入,鼠标右键->主菜单->通道管理
可以看到四个通道,但只有一个通道的状态是连上摄像头的。这四个通道对应的就是录像机背后的四个网口。这里我们在通道D1那行点击编辑,弹出界面再选择协议管理。
这里可以看到协议的类型,端口。还有下面有个示例。记住,这真的就只是个示例,它的ip,以及它的路径,半个字都不要信。我实际拉取到视频的路径是:
rtsp://NVR用户名:NVR密码@192.168.1.191:554/Streaming/Channels/101
这个路径,不同厂商的规则是不一样的,海康威视的应该是有过一次大的升级,所以网上很多资料都是不对的。这种东西,从官方文档中找。但是,我没找到,还是在网上找海康威视rtsp地址格式。地址如下,可去详细看看https://codesir.cn/read/hikang-video-camera-rtsp-get-address-collect.html
这里就仅详细解释我们用的这个url。
- rtsp:说明协议为rtsp
- NVR用户名:NVR密码 :用来通过认证用的。如果不输入,VLC会弹窗提示输入用户名密码。
- @:如果没有用户名密码的话,是不用输入的
- 192.168.1.191:554 :这就是IP+端口号。IP就是录像机在局域网中的IP,端口号就是上面协议管理里面的端口号
- Streaming/Channels/ :这个似乎是固定的
- 101 :第一个1是指通道号,最后一个一是指主码流。中间的0应该是为码流超过10个而预留的。
在VLC中,通过打开网络串流选项,把url粘贴进去,就可以打开视频流了。至此,用来测试的视频环境搭建完毕。
安装转码服务
是的,最终我还是选择了通过服务器转码,将转码后的码流推送出去供web端访问。由于我最初遇到这个问题的时间比较早,经过了这些年的积累,市面上似乎已经有了可用的开源项目了。经过对比后,决定尝试Kurento这个项目。Kurento官方教程
经过查询,似乎这个项目只能装在ubuntu系统上,而且另一个开源项目也是如此,因为ubuntu上有个他们的依赖。但是,我的目标服务器的操作系统是centos,所以我决定尝试docker的部署方式。官方docker部署说明
安装操作系统
安装操作系统及基础配置
首先要安装操作系统,这里就模拟产线环境安装centos7。具体可参考另一篇博文centos7基础配置
安装docker
sudo yum install docker -y
后面我们遇到了一些问题,因为解决方法是与docker相关的,所以放到这里统一处理。
遇到的问题主要是在拉取镜像时报如下错误:
Using default tag: latest Error response from daemon: error parsing HTTP 408 response body: invalid character '<' looking for beginning of value: "<html><body><h1>408 Request Time-out</h1>\nYour browser didn't send a complete request in time.\n</body></html>\n\n"
以上报错我添加了换行,否则看起来很不方便。
首先尝试增加加速源,虽然没有解决问题,但是对于增加下载速度是有好处的,所以也就记录在此
首先是打开配置文件
sudo vim /etc/docker/daemon.json
原来里面只有一对空的大括号,删除掉,换成如下内容:
{"registry-mirrors": ["http://hub-mirror.c.164.com"]}
还有几个镜像可选:
- https://registry.docker-cn.com :国内官方镜像,但是因为这个域名我ping不通,所以就没用
- https://docker.mirrors.ustc.edu.cn :中国科技大学的
保存退出后。关闭进程,重载服务,启动进程
sudo systemctl stop docker
sudo systemctl daemon-reload
sudo systemctl start docker
是的,还是没通。真正解决问题的是通过修改网卡的MTU,具体原理我也是很清楚。首先查询网卡
ip addr
内容如下
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1280 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:2c:4d:1f brd ff:ff:ff:ff:ff:ff
inet 192.168.1.30/24 brd 192.168.1.255 scope global noprefixroute ens192
valid_lft forever preferred_lft forever
inet6 fe80::278e:6818:ee5d:f0de/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:e6:ce:4d:40 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
第一个是机器的内循环,不管。第三个是docker添加的网卡也不管,内网网卡用的是第二个,ens192。可以看到默认的MTU是1500
centos7修改网卡配置,指令如下
sudo vim /etc/sysconfig/network-scripts/ifcfg-ens192
在末尾添加
MTU="900"
我试过9000,是不ok的,900,是可以解决问题的。
sudo systemctl restart network
通过上述指令重启网络服务,就可以成功拉取镜像了。
安装Kurento
拉取镜像
sudo docker pull kurento/kurento-media-server:6.16.0
运行实例
sudo docker run -d --name kms --network host kurento/kurento-media-server:latest
验证是否运行成功
curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Host: 127.0.0.1:8888" \
-H "Origin: 127.0.0.1" \
http://127.0.0.1:8888/kurento
得到如下响应就说名成功了
HTTP/1.1 500 Internal Server Error Server: WebSocket++/0.7.0
KMS日志追踪
docker logs --follow kms
设置容器随docker服务自动启动
sudo docker update --restart=always kms
开机启动docker服务
sudo systemctl enable docker
Hello World
git clone https://github.com/Kurento/kurento-tutorial-java.git
cd kurento-tutorial-java/kurento-hello-world
git checkout master
mvn -U clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dkms.url=ws://192.168.1.30:8888/kurento"
要注意这个是个前台进程,Ctrl+C就退出了。想要后台访问,可以先用maven将项目编译了
mvn clean package
然后到target目录里去执行如下命令
nohup java -jar kurento-player-6.16.0-exec.jar spring-boot:run -Dspring-boot.run.jvmArguments="-Dkms.url=ws://192.168.1.30:8888/kurento" &
接下来访问的网址如下:
https://192.168.1.30:8443/
需要注意的是这个demo是没有http地址的,一定需要访问的是https。打开页面以后,点击start,它就会调用你本地的摄像头,然后再给你看一个转码的画面,基本没看到延迟。
补充说明以下几点:
- mvn能执行的前提是你机器上安装了mvn并且将mvn添加到了path路径里。由于配置比较简单,这里就不另行说明了
- mvn里面8888端口的那个地址,是我们之前使用docker部署的服务地址,官方文档里也成为kms地址。
- 最后https访问的地址,是demo的运行地址,我这里是在同一台机器上,注意不好混淆。端口的修改在pom文件里。application.yml里也能修改,但是不推荐,它引用的是pom文件里的。
测试转码
本来网上找了个转码的demo,但是因为bower始终install不了,也就放弃了。在官方的例子中,我们运行它的player的Demo,就可以看到转码的效果。
git clone https://github.com/Kurento/kurento-tutorial-java.git
cd kurento-tutorial-java/kurento-player
git checkout master
mvn -U clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dkms.url=ws://192.168.1.30:8888/kurento"
我们可以看到官方的这些demo的启动过程都是类似的,只是目录不同罢了。访问地址也是一样的:
https://192.168.1.30:8443/
打开后界面如下
start、stop那些按钮下面那个地方输入你的流地址。我是选择了Video only后,点击的start。然后就ok了,延迟大概一两秒吧。刚开始有丢帧,后面就好了。
至此,打完收工。至于Kurento的具体调试过程,等我详细看了代码研究之后再说。本帖的过程到此结束。
最后的补充
官方的java demo,如果要调试的话,用jdk9或者更高版本可能会报一个错误,如下:
java: 错误: 选项 -source 不能与 --release 一起使用
这时idea的选项导致build失败的,如下图:
红框部分默认是勾选了的。去掉它,你就成功了。