海康威视使用FFmpeg+Nginx-rmtp进行按需推流(web端播放)

懵懂的女人 提交于 2020-12-28 01:21:09

海康威视使用FFmpeg+Nginx-rmtp进行按需推流

1.简介

很多朋友不太理解海康威视的官方sdk的使用方法博主也是,因为官方提供的是C/S版的,提供的web开发包,对浏览器的兼容性也是极差,还有一种办法是使用ffmpeg进行视频推流,

但是缺陷也是比较明显的,同时推三到四个流出来的视频也是相当卡顿对服务器资源消耗极大

所以博主另辟稀路,可不可以进行按需推流(傻瓜式监控视频对接)
(点击视频先关流再推流做到按需播放)呢?

主要思路:

  1. 利用FFmpeg推流软件进行视频RTSP转RTMP流
  2. 再利用video-player播放rtmp流,
  3. 点击播放时,判断ffmpeg进程是否存在,存在则获取进程的pid号
  4. 利用进程号关闭进程以达到关流的的效果

RTSP格式详见
https://blog.csdn.net/zhouyongku/article/details/45073443?ops_request_misc=%25257B

FFmpeg推流命令

 ffmpeg -i "rtsp://USERNAME:PASSWORD@IP:PROT/Streaming/Channels/<通道ID>"
   -b 4096k -f flv -r 25 -s 1920x1080 -an "rtmp://127.0.0.1:1935/live/自定义名称

JAVA 实现FFmpeg推流

public static void convertProtocol(String rtsp, String rtmp,String s){
   
   
//rtsp:海康rtsp地址
//rtmp:转换后的rtmp地址
//s: 分辨率

        ProcessBuilder builder = new ProcessBuilder(); //创建系统进程
        List<String> commend = new ArrayList<>();
        commend.add("F:/nginx-ffmpeg/ffmpeg/bin/ffmpeg.exe");
        commend.add("-i");
        commend.add("\""+rtsp+"\"");
        commend.add("-f");
        commend.add("flv");
        commend.add("-r");
        commend.add("25");
        commend.add("-s");
        if (s==null)
        {
   
   
            s="1920x1080";
        }
        commend.add(s);
        commend.add("-an");
        commend.add(rtmp);
        builder.command(commend);
        builder.redirectErrorStream(true);
        try {
   
   


            Process start = builder.start();//启动进程
            InputStream inputStream = start.getInputStream();
            InputStreamReader gbk = new InputStreamReader(inputStream);
            int len = -1;
            char[] c = new char[1024];
            StringBuffer outputString = new StringBuffer();

            //读取进程输入流中的内容
            while ((len = gbk.read(c)) != -1) {
   
   
                String ss = new String(c, 0, len);
                outputString.append(ss);
                System.out.print(ss);
            }


            gbk.close();
            inputStream.close();
        } catch (Exception e) {
   
   
            e.printStackTrace();

        }

    }

JAVA实现关流

//pid ffmpeg的进程pid号
 public void closeLiu(String pid) {
   
   
        try{
   
   
            Runtime.getRuntime().exec("taskkill /F /PID "+pid+"");

        }catch (Exception e)
        {
   
   
            e.printStackTrace();
        }

    }

获取FFmpeg的进程PID号

 public String getPid() {
   
   
        String pid = null;
        try{
   
   
            Process process=Runtime.getRuntime().exec("tasklist /fi \"imagename eq ffmpeg.exe\" /fo list");
            InputStream inputStream = process.getInputStream();
            BufferedReader bf=new BufferedReader(new InputStreamReader(inputStream,"GBK"));
            String line;
            while((line=bf.readLine())!=null)
            {
   
   
                    if (line.startsWith("PID")){
   
   
                        String[] array = line.split(":");
                        pid = array[1].trim();
                    }

                }
            System.out.println("PID:"+pid);


        }catch (Exception e)
        {
   
   
            e.printStackTrace();
        }

        return pid;
    }

到这里已经可以使用Java推流关流了
下面是使用vue的video-player在网页上播放

**安装支持插件**
npm install --save vue-video-player 
npm install --save videojs-flash

vue使用

<videoPlayer
      ref="videoPlayer"
      :options="videoOptions"
      class="vjs-custom-skin videoPlayer"
      :playsinline="false"
      @play="onPlayerPlay()"
    />
    videoOptions: {
   
   
        playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
        autoplay: false, //如果true,浏览器准备好时开始回放。
        muted: false, // 默认情况下将会消除任何音频。
        loop: false, // 导致视频一结束就重新开始。
        preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
        language: 'zh-CN',
        aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
        techOrder: ['flash', 'html5'], // 兼容顺序
        sources: [
          {
   
   
            // 流配置,数组形式,会根据兼容顺序自动切换
            type: 'rtmp/hls',
            src: '你的rtmp地址',
          },
        ],
        poster: image, //你的封面地址
        // width: document.documentElement.clientWidth,
        notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
        controlBar: {
   
   
          timeDivider: true,
          durationDisplay: true,
          remainingTimeDisplay: false,
          fullscreenToggle: true, //全屏按钮
        },
      }

videoPlayer标签事件说明
http://docs.wex5.com/videoplayer/

点击播放事件之后

data() {
    return {
      videoSrc: '',
      liuSta: false,
      pid: '',
      // 视频播放
      videos: {
        rtsp: '你的rtsp地址',
        rtmp: '你的rtmp地址',
        fenbianlv: '1920x1080',
      }
  }
onPlayerPlay() {
      //暂停其他视频
      this.$refs.videoPlayer.player.pause()
      //判断流进程是否存在
      videoPlay.isLiu().then((response) => {
        this.liuSta = response.result
 		//如果进程存在则获取进程的pid号
        if (this.liuSta) {
          videoPlay.getFFpid().then((response) => {
            this.pid = response.message
            //再使用pid号关闭流
            videoPlay.closeLiu(this.pid).then(() => {
            //最后再调用推流接口
              videoPlay.openLiu(this.videos).then(() => {
                console.log('step1', '播放成功!')
              })
            })
          })
        } else {
        //如果进程不存在则直接推流
          videoPlay.openLiu(this.videos).then(() => {
            console.log('step1', '播放成功!')
          })
        }
      })
    }

到此已经成功实现监控视频按需播放,有问题欢迎下方留言

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!