海康威视视频流rtsp,需要在web(Vue)页面显示,探索了很多方法,考虑到兼容,最终确定
ffmpeg+nginx-http-flv-module+flv.js
这一套方案,也推荐大家使用这一套方案。
简介
特此声明:本文主要记录我web直播海康视频的探索过程,如文中概念阐述有不正确的地方望留言指正
业界cs视频流方案还是比较多的,不再赘述。以下是web支持主流视频流协议
考虑到flash的会完全禁止(win10即将禁止,chrome,firfox已经禁止),rtmp这种基于flash的协议也不适合了。
我的实现方案是本地推rtsp流到阿里云搭建的流服务器(后面会介绍),然后再用 flv.js
播放
最后效果
延迟2~5s可以接受
正文
需要下载
vlc player(检测转流地址可用性)
ffpmeg(本地视频转码推流用)
nginx 包 (建议选择1.13以上版本,流服务搭建使用)
nginx-http-flv-module (nginx的flv直播流模块)
附: ffmpeg下载方法
附: 百度网盘链接(以上后面三个包) ud8d
附: rtmp测试地址
流服务器的搭建
可能会遇到一些奇怪的错误,复制问百度,基本都能解决
我买了一个月阿里云服务器(ubuntu 16),也可以用虚拟机本地搭建(我不会呀)。 用 xshel l连接服务器再安装 nginx
服务器: 阿里云 终端:xshell6 系统ubuntu , #为注释,不要写
更新(新的服务器才需要)
apt-get update
apt-get upgrade
安装支持上传解压的命令 rz
, unzip
(解压zip)
apt install lrzsz
apt install unzip
安装基础包(提示没有权限时前面加sudo),关于包的作用推荐 这里
sudo apt-get install openssl libssl-dev
sudo apt-get install libpcre3 libpcre3-dev
sudo apt-get install gcc
apt-get install libpcre3 libpcre3-dev
apt-get install zlib1g zlib1g-dev
上传解压 nginx,nginx-http-flv-module
cd /usr/local/src
rz #选择你的文件
tar -zxvf nginx-1.18.0.tar.gz
unzip nginx-http-flv-module-master.zip
配置和安装
cd nginx-1.18.0
./configure --prefix=/usr/local/nginx --add-module=/usr/local/nginx/nginx-http-flv-module-master
make && make install
配置nginx为全局变量
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/
nginx -v #检查
接下来是nginx.conf的配置,
cd /usr/local/nginx/conf
vim nginx.conf # 按 i 编辑,编辑完成按 Esc 然后输入 :wq 退出保存
nginx -s reload # 最后更新配置
worker_processes 1; #运行在Windows上时,设置为1,因为Windows不支持Unix domain
error_log logs/error.log error;
#如果此模块被编译为动态模块并且要使用与RTMP相关的功
#能时,必须指定下面的配置项并且它必须位于events配置
#项之前,否则NGINX启动时不会加载此模块或者加载失败
#load_module modules/ngx_http_flv_live_module.so;
events {
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
server {
listen 80;
server_name ip; #服务端ip
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
root html;
}
location /live {
flv_live on; #打开HTTP播放FLV直播流功能
chunked_transfer_encoding on; #支持'Transfer-Encoding: chunked'方式回复
add_header 'Access-Control-Allow-Origin' '*'; #添加额外的HTTP头
add_header 'Access-Control-Allow-Credentials' 'true'; #添加额外的HTTP头
# add_header Access-Control-Allow-Headers X-Requested-With;
# add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
# add_header 'Cache-Control' 'no-cache';
}
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root html;
add_header 'Cache-Control' 'no-cache';
}
location /dash {
root /html;
add_header 'Cache-Control' 'no-cache';
}
location /stat {
#push和pull状态的配置
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root /usr/local/src/nginx-http-flv-module-master; #指定stat.xsl的位置
}
#如果需要JSON风格的stat, 不用指定stat.xsl
#但是需要指定一个新的配置项rtmp_stat_format
#location /stat {
# rtmp_stat all;
# rtmp_stat_format json;
#}
location /control {
rtmp_control all; #rtmp控制模块的配置
}
}
}
rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp;
rtmp {
out_queue 4096;
out_cork 8;
max_streams 128;
timeout 15s;
drop_idle_publisher 15s;
log_interval 5s; #log模块在access.log中记录日志的间隔时间,对调试非常有用
log_size 1m; #log模块用来记录日志的缓冲区大小
server {
listen 1935;
server_name ip; #用于虚拟主机名后缀通配
application myapp {
live on;
#record off; # 不记录视频
gop_cache on; #打开GOP缓存,减少首屏等待时间
}
application hls {
live on;
hls on;
hls_path /usr/local/nginx/html/hls;
}
application dash {
live on;
dash on;
dash_path /usr/local/nginx/html/dash;
}
}
}
ffmpeg推流
将下载好的ffmpeg解压到自定义的文件夹,
复制bin文件夹路径到环境变量,右键我的电脑,属性
检测 ffmpeg.我用的 cmder
⇲ , cmd 也行
推流
ip1表示摄像头的公网ip,ip2是我的阿里云服务器ip2
ffmpeg -i rtsp://admin:password@ip2 -vcodec copy -acodec copy -f flv -s 500x300 rtmp://ip2:1935/myapp/24
需要主要这样会产生两个地址(vlc player可以观看)
rtmp://ip2:1935/myapp/24
http://ip2/live?port=1935&app=myapp&stream=23 // 注意这个port、app 、stream与上面地址一一对应
vue中显示
安装 flv.js
cnpm install flv.js -S
video.vue
<template>
<div id="flv01">
<p>视频测试</p>
<div class="video-box">
<video
v-for="(url, idx) in params"
:id="'myvideo' + idx"
@click="click(idx)"
controls
muted
:key="idx"
></video>
</div>
</div>
</template>
<script>
import flv from "flv.js";
export default {
name: "app",
data() {
return {
players: [null, null, null, null],
playing: false,
params: [
"http://ip2/live?port=1935&app=myapp&stream=23",
"http://ip2/live?port=1935&app=myapp&stream=24",
],
};
},
mounted() {
this.innitPlayer(this.params);
},
methods: {
innitPlayer(initParams = []) {
const _this = this;
initParams.length &&
initParams.forEach((item, idx) => {
const video = document.querySelector(`#myvideo${idx}`);
if (flv.isSupported()) {
if (
typeof _this.players[idx] !== "undefined" &&
_this.players[idx] != null
)
_this.players[idx].destroy();
_this.players[idx] = flv.createPlayer({
type: "flv",
isLive: true,
enableWorker: true, //浏览器端开启flv.js的worker,多进程运行flv.js
hasAudio: false, //关闭音频
hasVideo: true,
enableStashBuffer: false, //播放flv时,设置是否启用播放缓存,只在直播起作用。
url: item,
});
}
this.players[idx].attachMediaElement(video);
this.players[idx].load();
this.players[idx].play();
});
},
click(idx) {
if (this.playing) {
this.players[idx].pause();
this.playing = false;
} else {
this.playeridx[x].play();
this.playing = true;
}
},
},
};
</script>
<style lang="scss">
#flv01 {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
.video-box {
display: flex;
flex-wrap: wrap;
justify-content: center;
width: 100%;
video {
margin: 20px;
width: 500px;
height: 300px;
}
}
}
</style>
以上。
上面步骤完成,视频也就能出来了,当然我能想到的还有以下问题:
- 首开时间虽然短,画面延迟差不多20s,不太理想,应该是我代码的原因
- 同时展示四个视频流,并且点击另外的如何切换(四个里)其中一个,页面离开销毁播放器。(深入了解flv.js)
- 到时项目上线,ffpmeg需要服务器上推流,如何动态推流,因为rtsp地址是固定的,如果需要一个服务器上运行一个ffppmeg会很繁琐,还需要在vue中动态改http地址(了解nginx动态配置)
针对以上问题,我会另起博文更新。
【一些参考】
FFmpeg + nginx-http-flv-module + flv.js 实现视频流播放(博客风格我还挺喜欢的)
平台开发——搭建Nginx + nginx-http-flv-module + Ffmpeg 实现推流视频到nginx服务器