web实时视频流从0到1(ffmpeg+nginx-http-flv-module+flv.js)

海康威视视频流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 也行
ffmpeg版本查看
推流

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服务器

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值