1. 程式人生 > 其它 >Vue中預覽HIKVSION海康威視的NVR(網路硬碟錄影機)中多個通道(攝像機)的視訊

Vue中預覽HIKVSION海康威視的NVR(網路硬碟錄影機)中多個通道(攝像機)的視訊

場景

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>