zoukankan      html  css  js  c++  java
  • SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版)

    场景

    若依前后端分离版手把手教你本地搭建环境并运行项目:

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

    SpringBoot+Vue+Openlayers实现地图上新增和编辑坐标并保存提交:

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

    在上面实现的基础上,对接海康威视摄像头实现摄像头预览效果。

    该型号只支持IE模式取流。

    注:

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

    实现

    1、去官网-硬件产品-WEB开发包下载官方示例代码。

    由于这里的设备不支持websocket取流,所以下载下面的3.0的开发包。

    2、按照上面博客中建表与生成前后端代码,进而实现对摄像头参数的管理。

    实现预览的主要参数包括Ip、端口号、登录名、登录密码。其他的都是额外加的参数。

    3、勾选摄像头进行预览,限制最多选择四个,否则浏览器会卡顿。

        <el-table
          v-loading="loading"
          :data="videoList"
          @selection-change="handleSelectionChange"
        >

    多选事件处理

         // 多选框选中数据
        handleSelectionChange(selection) {
          this.openVideoData = [];
          this.openVideoData = selection;
          this.ids = selection.map((item) => item.id);
          this.single = selection.length !== 1;
          this.multiple = !selection.length;
        },

    需要提前声明变量

      data() {
        return {
          // 遮罩层
          loading: false,
          // 选中数组
          ids: [],
          // 非单个禁用
          single: true,
          // 非多个禁用
          multiple: true,

    4、点击预览按钮实现跳转到预览的新标签页

            <el-button
              type="success"
              plain
              icon="el-icon-setting"
              size="mini"
              :disabled="multiple"
              @click="videoChange"
              >预览</el-button
            >

    预览按钮的点击事件

       // 查看摄像
        videoChange() {
          let routeUrl = this.$router.resolve({
            path: "/carVideo",
            query: {
              videoData: JSON.stringify(this.openVideoData),
            },
          });
          if (this.openVideoData.length > 4) {
            this.$notify({
              title: "失败",
              message: "最多支持预览选择4个摄像头",
              type: "error",
            });
          } else {
            window.open(routeUrl.href, "_blank");
          }
        },

    首先校验最多选择四个,然后跳转到新的预览页面/carVideo。

    首先配置路由,打开src/router下的index.js,添加路由

      {
        path: '/carVideo',
        component: Layout,
        component: (resolve) => require(['@/views/system/cameramap/component/video'], resolve),
        meta: {title: '摄像头'},
        hidden: true,
      },

    然后跳转路由时携带了要进行预览的摄像头参数this.openVideoData

    5、预览页面video.vue引入官网的webVideoCtrl.js文件

    首先该页面中需要引入官网的webVideoCtrl.js文件,在根目录下新建static目录,将js文件放在该目录下

    引入

    import { WebVideoCtrl } from "/static/webVideoCtrl.js";

    6、video.vue判断当前是否为IE/兼容模式

    data中获取请求代理

    ua: navigator.userAgent.toLocaleLowerCase(),

    created方法中进行判断并提示

      created() {
        if (this.ua.match(/msie/) != null || this.ua.match(/trident/) != null) {
          this.browserType = "IE";
          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;
          }
        } else {
          this.$notify({
            title: "失败",
            message: "请在ie模式下查看摄像头",
            type: "error",
          });
        }
      },

    7、初始化预览页面

    在mounted中执行初始化界面的操作

      mounted() {
        this.videoChange();
      },

    在方法中

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

    调用videoInitPlugin中校验是否已经安装插件,插件位置为开发包中exe文件

    校验是否已经安装插件的方法

        videoInitPlugin() {
          this.$nextTick(() => {
            var iRet = WebVideoCtrl.I_CheckPluginInstall();
            if (iRet === -1) {
              // alert("您还未安装过插件,双击开发包目录里的WebComponentsKit.exe安装");
              this.myFunction();
              return;
            }
            this.initPlugin();
          });
        },
        myFunction() {
          var r = confirm("您还未安装过插件,请下载后查看摄像!");
          if (r == true) {
            window.location.href = "/WebComponentsKit.exe";
          } else {
          }
        },

    如果没有安装插件会进行提示并且确定后进行下载,所以将WebComponentsKit.exe

    放在代码中public目录下

    如果已经安装插件则执行官方js中初始化插件的方法

        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];
            this.index = i;
            this.onLogin();
          }
        },

    然后是遍历选择的所有摄像头进行登录操作。

    8、摄像头登录

        // 登录
        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;
                that.$message({
                  showClose: true,
                  message: "登录失败",
                  type: "error",
                });
              },
            }
          );
        },

    9、登录成功后调用预览

    在登录成功后直接调用预览方法

        clickStartRealPlay() {
          console.log("开始预览", this.index);
          // 开始预览
          var that = this;
          that.startPlayLoading = true;
          var szDeviceIdentify = that.hkvInfo.ip + "_" + that.hkvInfo.port;
          that.startRealPlay(szDeviceIdentify, this.index, that.hkvInfo.channels[0]);
          that.startPlayLoading = false;
        },
        startRealPlay(szDeviceIdentify, iWndIndex, iChannelID) {
          var that = this;
          WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {
            iRtspPort: that.iRtspPort,
            iWndIndex: iWndIndex,
            iChannelID: iChannelID,
            bZeroChannel: that.bZeroChannel,
            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);
              }
            },
          });
        },

    10、在页面销毁关闭时停止预览并退出登录

      destroyed() {
        this.clickStopRealPlay();
        this.onLogout();
      },

    停止预览

        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",
              // });
            },
          });
        },

    退出登录

        // 退出
        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",
              // });
            }
          });
        },

    11、完整video.vue示例代码

    <template>
      <div class="video_box">
        <!-- 摄像头 -->
        <div id="divPlugin" class="plugin"></div>
      </div>
    </template>
    
    <script>
    import { WebVideoCtrl } from "/static/webVideoCtrl.js";
    export default {
      name: "OpUser",
      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() {
        if (this.ua.match(/msie/) != null || this.ua.match(/trident/) != null) {
          this.browserType = "IE";
          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;
          }
        } else {
          this.$notify({
            title: "失败",
            message: "请在ie模式下查看摄像头",
            type: "error",
          });
        }
      },
      mounted() {
        this.videoChange();
      },
      destroyed() {
        this.clickStopRealPlay();
        this.onLogout();
      },
      methods: {
        getList() {},
        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;
                that.$message({
                  showClose: true,
                  message: "登录失败",
                  type: "error",
                });
              },
            }
          );
        },
        // 退出
        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;
          that.startRealPlay(szDeviceIdentify, this.index, that.hkvInfo.channels[0]);
          that.startPlayLoading = false;
        },
        startRealPlay(szDeviceIdentify, iWndIndex, iChannelID) {
          var that = this;
          WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {
            iRtspPort: that.iRtspPort,
            iWndIndex: iWndIndex,
            iChannelID: iChannelID,
            bZeroChannel: that.bZeroChannel,
            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;
            }
            this.initPlugin();
          });
        },
        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];
            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 {
       100%;
      height: 100%;
    }
    
    .plugin {
       100%;
      height: 100%;
    }
    
    .my-tag {
      margin-left: 3px;
    }
    
    .my-group-btn {
      margin-top: 5px;
    }
    </style>
  • 相关阅读:
    C++ 对象模型学习记录(2) 第3章 data语义学
    C++ 对象模型学习记录(1) 第2章 构造函数语义学
    C ++ 对象模型学习记录(4) function 语义学 (未完待续)
    C++ 对象模型学习记录(3) 第1章 关于对象(未完)
    设计模式复习 之 代理模式
    大数运算
    effective C ++ 学习笔记之 item 31 将文件间的编译依赖关系降至最低(未完成)
    Java 复习 之1 多线程
    SQL中char varchar nchar nvarchar ntext区别和使用(资料汇总)
    .Net中的加密解密
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/15517468.html
Copyright © 2011-2022 走看看