场景
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>