场景

SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版):

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/121180769

上面实现的在Vue中直接通过单个摄像头的Ip、端口、用户名、密码来预览

摄像头的视频,这里将两个摄像头装在海康威视网络硬盘录像机,即NVR中。

怎样在Vue中进行预览。

去海康威视官网下载web开发包

具体参考上面的博客。

根据其官方文档的说明,Web控件既适应于单个摄像头的预览,也适用于NVR等设备的预览,预览接口和流程是一致的。

 

 

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

1、要实现浏览器能访问NVR中的摄像头的视频,要保证NVR连接了网络,并配置了ip,以及需要访问视频的电脑的网络和nvr网络互通。

在使用Vue进行对接前,先使用海康官方的CH_WEB3.0控件开发包中demo/cn下的demo.html或者demo-easy.html测试预览视频的效果

因为此款摄像头只能用插件加兼容模式预览视频,所以使用支持兼容模式的某60浏览器

 

 

安装了插件后会提示是否允许阻止的内容,点击允许

 

 

2、然后配置nvr的ip、端口号、用户名、密码等信息

 

 

登录成功之后会有提示并且显示通道列表,这里Camera 01和02就是代表的有两个摄像头。

3、选择摄像头1,点击预览

 

 

点击第二个预览格再下拉选中摄像头2点击预览

 

 

4、需要注意的是,在进行预览时要选择预览的码流类型为子码流

那样视频会比主码流流畅。然后浏览器要切换兼容模式

 

 

5、在Vue中实现

首先在前一个页面中获取nvr的ip,因为这里的端口、用户名和密码都是统一配置的,所以不再配置和获取。

下面是在按钮的点击事件中,即methods中

        //NVR视频预览,传递通道号
        nvrPreview(channelNum){
            let self = this;
            //校验NvrIP是否配置正确
            if(self.nvrIp){
                let openVideoData = [];
                let hkvInfo = {
                    ip: self.nvrIp, //海康威视摄像头/硬盘录像机的ip地址
                    port: "80", //海康威视摄像头/硬盘录像机的端口
                    username: "admin", //海康威视摄像头/硬盘录像机的用户名
                    password: "你自己的密码", //海康威视摄像头/硬盘录像机的密码
                    channels: [channelNum], //海康威视摄像头/硬盘录像机的通道
                    nvrPrechannel: channelNum, //NVR预览通道
                };
                openVideoData.push(hkvInfo);
                let routeUrl = this.$router.resolve({
                path: "/carNvrVideo",
                query: {
                    videoData: JSON.stringify(openVideoData),
                    },
                });
                window.open(routeUrl.href, "_blank");
            }else{
                //提示未配置
                this.$message({
                message: '当前车辆nvrip未配置',
                type: 'warning'
                });
            }
        },

6、配置路由跳转参考前面博客。

这里预览基本和上面单个预览的代码一致,优化的地方是

在调用预览方法时多传递了码流类型iStreamType这个字段,指定为子码流,这样预览更流畅。

这里传递了通道id参数,1就代表1号通道,即摄像头1。

    startRealPlay(szDeviceIdentify, iWndIndex, iChannelID) {
      var that = this;
      WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {
        iRtspPort: that.iRtspPort,
        iWndIndex: iWndIndex,
        iChannelID: iChannelID,
        bZeroChannel: that.bZeroChannel,
        iStreamType: 2,//码流类型,2为子码流
        success: function () {
          //   that.$notify({
          //     title: "成功",
          //     message: "开始预览通道" + iChannelID + "成功",
          //     type: "success",
          //   });
        },
        error(status, xmlDoc2) {
          console.log(xmlDoc2); //不能删除
          // that.$notify({
          //   title: "失败",
          //   message: "开始预览通道" + iChannelID + "失败",
          //   type: "error",
          // });
          if (status === 403) {
            console.log("szInfo 设备不支持Websocket取流!");
          } else {
            console.log("开始预览失败 ", status, xmlDoc2);
          }
        },
      });
    },

预览可以参考官方开发文档传参

 

 

7、之前发现在预览前先验证是否切换了兼容模式,然后切换之后如果配置的Ip或者用户名等不正确,即

登录失败时所提示的代码仍然是Vue的ElementUI的语法,在兼容模式中无法执行,所以会导致在预览时如果

登录失败就会网页无响应。所以将其登录失败的回调方法中的提示消息由Vue的代码修改为js的alert代码

    async onLogin() {
      var that = this;
      that.loginLoading = true;
      // 登录设备
      WebVideoCtrl.I_Login(
        that.hkvInfo.ip,
        that.iProtocol,
        that.hkvInfo.port,
        that.hkvInfo.username,
        that.hkvInfo.password,
        {
         
          async: false,
          success: (xmlDoc) => {
            //TODO 获取通道信息
            that.getChannelInfo();
            that.getDevicePort(that.hkvInfo.ip + "_" + that.hkvInfo.port);
            that.loginLoading = false;
            this.clickStartRealPlay();
          },
          error: function () {
            that.loginLoading = false;
            alert("当前摄像头配置不对或不在线,登录失败");
            window.opener=null;
            window.open('','_self');
            window.close();
          },
        }
      );
    },

8、还要注意在页面加载完之后要设置一个延迟初始化插件的代码

如果页面没加载完就初始化插件会报错。

  mounted() {
    this.videoChange();
  },
  methods: {
    videoChange() {
      setTimeout(() => {
        this.videoInitPlugin(); // 初始化video界面
      }, 300);
    },

9、预览页面完整代码

<template>
  <div class="video_box">
    <!-- 摄像头 -->
    <div id="divPlugin" class="plugin"></div>
  </div>
</template>

<script>
import { WebVideoCtrl } from "/static/webVideoCtrl.js";
export default {
  name: "carNvrVideo",
  components: {},
  data() {
    return {
      szInfo: "",
      rowList: {},
      hkvInfo: {},
      mySelectWnd: 0, //当前选中的窗口
      g_bPTZAuto: false,
      iProtocol: 1,
      loginLoading: false,
      startPlayLoading: false,
      bZeroChannel: false,
      iRtspPort: 0,
      index: 0,
      iWndowType: null,
      videoData: [],
      ua: navigator.userAgent.toLocaleLowerCase(),
    };
  },
  created() {

    this.videoData = JSON.parse(this.$route.query.videoData);
    if (this.videoData.length <= 1) {
      this.iWndowType = 1;
    } else if (this.videoData.length > 1 && this.videoData.length <= 4) {
      this.iWndowType = 2;
    }
  },
  mounted() {
    this.videoChange();
  },
  destroyed() {
    this.clickStopRealPlay();
    this.onLogout();
  },
  methods: {
    videoChange() {
      setTimeout(() => {
        this.videoInitPlugin(); // 初始化video界面
      }, 300);
    },
    handleSelectionChange() {},
    submitForm() {},
    cancel() {},
    // 登录
    async onLogin() {
      var that = this;
      that.loginLoading = true;
      // 登录设备
      WebVideoCtrl.I_Login(
        that.hkvInfo.ip,
        that.iProtocol,
        that.hkvInfo.port,
        that.hkvInfo.username,
        that.hkvInfo.password,
        {
         
          async: false,
          success: (xmlDoc) => {
            //TODO 获取通道信息
            that.getChannelInfo();
            that.getDevicePort(that.hkvInfo.ip + "_" + that.hkvInfo.port);
            that.loginLoading = false;
            this.clickStartRealPlay();
          },
          error: function () {
            that.loginLoading = false;
            alert("当前摄像头配置不对或不在线,登录失败");
            window.opener=null;
            window.open('','_self');
            window.close();
          },
        }
      );
    },
    // 退出
    onLogout() {
      this.videoData.forEach((element) => {
        var szDeviceIdentify = element.ip + "_" + element.port;
        var iRet = WebVideoCtrl.I_Logout(szDeviceIdentify);
        if (0 == iRet) {
          //   this.$message({
          //     showClose: true,
          //     message: "退出成功",
          //     type: "success",
          //   });
        } else {
          // this.$message({
          //   showClose: true,
          //   message: "退出失败",
          //   type: "error",
          // });
        }
      });
    },
    clickStartRealPlay() {
      console.log("开始预览", this.index);
      // 开始预览
      var that = this;
      that.startPlayLoading = true;
      var szDeviceIdentify = that.hkvInfo.ip + "_" + that.hkvInfo.port;
      debugger
      that.startRealPlay(szDeviceIdentify, this.index, that.hkvInfo.nvrPrechannel);
      that.startPlayLoading = false;
    },
    startRealPlay(szDeviceIdentify, iWndIndex, iChannelID) {
      var that = this;
      WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {
        iRtspPort: that.iRtspPort,
        iWndIndex: iWndIndex,
        iChannelID: iChannelID,
        bZeroChannel: that.bZeroChannel,
        iStreamType: 2,//码流类型,2为子码流
        success: function () {
          //   that.$notify({
          //     title: "成功",
          //     message: "开始预览通道" + iChannelID + "成功",
          //     type: "success",
          //   });
        },
        error(status, xmlDoc2) {
          console.log(xmlDoc2); //不能删除
          // that.$notify({
          //   title: "失败",
          //   message: "开始预览通道" + iChannelID + "失败",
          //   type: "error",
          // });
          if (status === 403) {
            console.log("szInfo 设备不支持Websocket取流!");
          } else {
            console.log("开始预览失败 ", status, xmlDoc2);
          }
        },
      });
    },
    videoInitPlugin() {
      this.$nextTick(() => {
        var iRet = WebVideoCtrl.I_CheckPluginInstall();
        if (iRet === -1) {
          // alert("您还未安装过插件,双击开发包目录里的WebComponentsKit.exe安装");
          this.myFunction();
          return;
        }else{
           if (this.ua.match(/msie/) != null || this.ua.match(/trident/) != null) {
              this.browserType = "IE";
              this.initPlugin();
            } else {
              this.$notify({
                title: "失败",
                message: "请在ie模式下查看摄像头",
                type: "error",
              });
            }
        }
       
      });
    },
    myFunction() {
      var r = confirm("您还未安装过插件,请下载后查看摄像!");
      if (r == true) {
        window.location.href = "/WebComponentsKit.exe";
      } else {
      }
    },
    initPlugin() {
      WebVideoCtrl.I_InitPlugin("100%", "100%", {
        bWndFull: true, //是否支持单窗口双击全屏,默I_CheckPluginInstall
        iWndowType: this.iWndowType, //默认展示几个摄像头1x1 2x2
        cbInitPluginComplete: function () {
          WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin");
          // 检查插件是否最新
          if (WebVideoCtrl.I_CheckPluginVersion() === -1) {
            return;
          }
        },
      });
      for (var i = 0; i < this.videoData.length; i++) {
       
        this.hkvInfo = this.videoData[i];
        debugger
        this.index = i;
        this.onLogin();
      }
    },
    getDevicePort(szDeviceIdentify) {
      var oPort = WebVideoCtrl.I_GetDevicePort(szDeviceIdentify);
      this.iRtspPort = oPort.iRtspPort;
    },

    clickStopRealPlay: function () {
      for (var i = 0; i <= this.index; i++) {
        setTimeout(this.stopRealPlay(i), 1000);
      }
    },
    stopRealPlay: function (iWndIndex) {
      var that = this;
      WebVideoCtrl.I_Stop({
        iWndIndex: iWndIndex,
        success: function () {
          //   that.$notify({
          //     title: "成功",
          //     message: "停止预览窗口" + iWndIndex + "成功",
          //     type: "success",
          //   });
        },
        error: function () {
          // that.$notify({
          //   title: "失败",
          //   message: "停止预览窗口" + iWndIndex + "失败",
          //   type: "error",
          // });
        },
      });
    },
    // 获取通道,实际上可以根据自己的项目,获取数字通道,模拟通道,零通道中的一个或多个,不用全部获取(提高效率)
    getChannelInfo: function () {
      var that = this;
      var szDeviceIdentify = this.hkvInfo.ip + ":" + this.hkvInfo.port;
      // 数字通道
      that.hkvInfo.channels = [];
      WebVideoCtrl.I_GetDigitalChannelInfo(szDeviceIdentify, {
        async: false,
        mysuccess: function (xmlStr) {
          console.log("mysuccess I_GetDigitalChannelInfo: ", xmlStr);
          var jsonObj = that.$x2js.xml2js(xmlStr);
          var list = jsonObj.InputProxyChannelStatusList.InputProxyChannelStatus;
          for (var x = 0; x < list.length; x++) {
            that.hkvInfo.channels.push(list[x].id);
          }
        },
        success: function (xmlDoc) {},
        error: function (status, xmlDoc) {
          console.log("获取数字通道失败");
        },
      });
      // 模拟通道
      WebVideoCtrl.I_GetAnalogChannelInfo(szDeviceIdentify, {
        async: false,
        mysuccess: function (xmlStr) {
          var jsonObj = that.$x2js.xml2js(xmlStr);
          console.log("模拟通道mysuccess", xmlStr);
          var id = jsonObj.VideoInputChannelList.VideoInputChannel.id;
          that.hkvInfo.channels.push(id);
        },
        success: function (xmlStr) {
          console.log("模拟通道success", xmlStr);
        },
        error: function (status, xmlDoc) {
          console.log("模拟通道error", xmlDoc);
        },
      });
      // TODO 零通道
    },
  },
};
</script>
<style scoped>
.video_box {
  width: 100%;
  height: 100%;
}

.plugin {
  width: 100%;
  height: 100%;
}

.my-tag {
  margin-left: 3px;
}

.my-group-btn {
  margin-top: 5px;
}
</style>

 

posted on 2022-04-13 19:03  霸道流氓  阅读(1838)  评论(0编辑  收藏  举报