1. 简介
大部分网络摄像机,比如海康威视都支持rtsp协议视频流,但是web一般是无法直接播放rtsp协议视频流的,需要在服务器上把rtsp视频流转换成web其他协议。本篇博客介绍利用ffmpeg、nginx、flvjs实现web浏览rtsp视频流。主要参考了文章【入门】无插件web直播解决方案,ffmpeg+nginx-http-flv-module+flv.js、Nginx+FFmpeg 海康、大华NVR实现rtsp转flv实时预览+录像回放
所用到的服务器操作系统为ubuntu20.04。
2. 安装ffmpeg
sudo apt update && sudo apt install ffmpeg
3. 安装nginx
nginx需要安装nginx-http-flv-module以支持flv格式视频流,需要下载该模块,并从源码重新编译nginx,在编译nginx前还需要下载一些必要的依赖,以下参考了nginx源码编译教程
3.1 安装nginx依赖
3.1.1 pcre
教程中给的pcre下载链接无法使用,我更换成了以下链接https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz pcre官方不再维护,这是镜像地址https://sourceforge.net/projects/pcre/files/pcre/8.44/
1 | wget https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz |
3.1.2 zlib
1 | wget http://zlib.net/zlib-1.2.11.tar.gz |
3.1.3 openssl
再次按照该文档编译时,发现编译nginx执行configure命令无法找到编译的openssl(经测试发现–prefix=/usr改为–prefix=/usr/local即可),改为用sudo apt-get install libssl-dev
直接安装,以下为原来的编译教程
教程中./Configure darwin64-x86_64-cc –prefix=/usr配置后有问题,我参考stackoverflow解决方案,做了更改
1 | wget http://www.openssl.org/source/openssl-1.1.1g.tar.gz |
3.2 编译nginx
3.2.1 下载nginx
1 | wget https://nginx.org/download/nginx-1.18.0.tar.gz |
3.2.2 下载nginx-http-flv-module
git clone https://github.com/winshining/nginx-http-flv-module.git
3.2.3 编译
下方/path/to应该修改成你的nginx-http-flv-module文件夹的位置,比如我在home目录hfy下执行的git clone命令,nginx-http-flv-module文件夹位于我的家目录中,配置命令应该写成./configure --add-module=/home/hfy/nginx-http-flv-module
1 | cd nginx-1.18.0 |
4. 配置nginx
sudo vi /usr/local/nginx/conf/nginx.conf
打开nginx配置文件,删除原来的配置内容,替换为nginx-http-flv-module github readme最后给出的example configuration
4.1 重点配置介绍
1 | ... |
4.2 完整配置(方便复制粘贴)
1 | worker_processes 1; #should be 1 for Windows, for it doesn't support Unix domain socket |
5. ffmpeg推流
5.1 海康威视网络摄像机推流命令
ffmpeg推流命令主要参考了文章:Nginx+FFmpeg 海康、大华NVR实现rtsp转flv实时预览+录像回放,详细介绍了如何使用ffmpeg对海康威视网络摄像机推流
1 | ffmpeg -rtsp_transport tcp -i rtsp://user:password@ip:port/Streaming/channels/101 -c copy -f flv rtmp://127.0.0.1:1935/myapp/mystream |
参数解析
-rtsp_transport tcp: 固定写法
user:用户名
password:密码
ip:摄像头或NVR的IP地址
port:摄像头或NVR的RTSP端口,默认是554,具体的RTSP取流规则可以百度
-c copy: 输出直接复制,不转换格式
-f flv:转成flv
rtmp://127.0.0.1:1935/myapp/mystream:根据Nginx配置文件生成,端口号1935与nginx配置中的listen 1935对应;myapp对应配置文件中的application myapp;mystream名字不固定,会在后续用flvjs取流时用到
附海康威视网络摄像机rtsp取流地址
1 | 【新版本】 |
5.2 rtsp视频流公共测试地址
如果手头没有现成的网络摄像头供测试,可以使用公共的rtsp视频测试地址rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov
相应的推流命令如下
1 | ffmpeg -rtsp_transport tcp -i rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov -c copy -f flv rtmp://127.0.0.1:1935/myapp/mystream |
6. flvjs播放
flvjs是哔哩哔哩开源的web播放器,使用方法可以参考官方demo。但是官方给出的demo代码比较多,如果只是想简单实现的话可以参考下方的完整代码,注意flvjs是通过bootcdn引入的。
6.1 关键代码说明
1 | var flvPlayer = flvjs.createPlayer({ |
url格式 http://example.com:80/live?port=1935&app=myapp&stream=mystream
example.com:80中的80端口与nginx配置中listen 80对应,后面的三个get参数port=1935&app=myapp&stream=mystream是固定格式,1935与nginx配置listen 1935对应,myapp与nginx配置中application myapp对应,mystream与ffmpeg推流命令最后的rtmp://127.0.0.1:1935/myapp/mystream 对应
6.2 完整代码(方便复制粘贴)
1 |
|
7. 其他问题
至此已经完成了整个实现过程,但是还有一些问题需要注意。
7.1 累积时延问题
由于网络波动或者网页切换到后台等原因,flvjs播放会有累积时延,这在摄像头监控画面中是无法忍受的,主要参考了github issues以及【入门】无插件web直播解决方案,ffmpeg+nginx-http-flv-module+flv.js给出的解决方案:video对象可以获取currentTime以及endTime,设置一个定时器比较一下二者时间差,时间差小于60s时倍速播放,大于60s时直接跳帧,因为视频监控的用户更关心最近的画面,代码已经在6.2中给出,如下:
1 | setInterval(function () { |
7.2 自动播放问题
有时候可能一个web页面需要展示好几个监控视频画面,让用户依次点击开始播放不太方便,需要在video标签中加入autoplay 属性实现自动播放,但是一些浏览器比如chrome禁止音频内容的自动播放,可以在video标签中加入muted属性,如下:<video id="videoElement" class="centeredVideo" muted autoplay width="1024" height="576">Your browser is too old which doesn't support HTML5 video.</video>
7.3 flvjs播放器要主动销毁
该问题是我在使用Vue进行前端开发时遇到的,在离开某个Vue页面后并没有主动销毁flvjs的播放器,后台仍然在接受数据,导致再次回到该页面时无法重复创建flvjs播放器,加载不出监控画面。解决方法是在离开页面的回调函数中写入销毁的函数
1 | function flv_destroy() { |
7.4 同时在后台启动多个推流
当需要同时在后台启动多个推流命令时,使用screen可能比较麻烦。可以创建一个start_live.sh的脚本,内容如下:
1 | # start_live.sh |
为了防止在nohup.out中写入巨量的日志信息,可以在ffmpeg推流命令中加入-loglevel quiet
参数。