vue页面集成海康威视web视频播放插件
参考大神链接:https://www.jianshu.com/p/71d97362fdd8
1、进入海康威视官网下载web视频插件
下载插件开发包:https://open.hikvision.com/download/5c67f1e2f05948198c909700?type=10
官方教程:https://open.hikvision.com/docs/docId?productId=612781c8ec4acb28e0e1c0c3&version=%2Fff026cfc47a14e79a6c9acf21d9d8769
2、将下载的3个js文件放入public路径下
3、public/index.html中增加引用
4、创建组件页面
<template><!--海康web插件--> <div> <el-row style="margin-bottom: 8px;margin-top: -25px;"> <el-col :span="5"> <el-radio-group v-model="type" size="medium" @input="changeType"> <el-radio-button label="live" >实时预览</el-radio-button> <el-radio-button label="rec">回放</el-radio-button> </el-radio-group> <!-- <el-button type="primary" icon="el-icon-video-pause" size="mini" @click="requestInterface">test</el-button>--> </el-col> <el-col :span="16"> <div v-show="playMode==1"> <span style="margin-right: 5px">回放时间:</span> <el-date-picker v-model="daterangeMonitorTime" size="small" style="width: 360px" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" ></el-date-picker> <el-button type="primary" icon="el-icon-video-play" size="mini" @click="startPlayback" style="margin-left: 3px;">回放 </el-button> <el-button type="primary" icon="el-icon-video-pause" size="mini" @click="stopPlayback">停止回放</el-button> </div> </el-col> <el-col :span="3"> <div style='color:#4194fc;text-decoration:underline;margin-top: 7px;' title="首次使用,请下载插件并安装"> <i class="el-icon-info"></i> <a href="http://localhost:7345/feature/cameraconfig/downloadVideoWebPlugin" download="VideoWebPlugin.exe">下载插件</a> </div> </el-col> </el-row> <div id="hikvision-grid" class="wrapper" ref="wrapper" style="width: 100%; height: 100%; clear: both" > <div v-show="oWebControl" :id="setting.id" :class="[oWebControl === null ? 'videoNull' : '']" style="width: 800px; height: 500px;" ></div> <br /> <div v-show="!oWebControl"> <div v-html="playText"></div> <br /> <div v-show="playText.includes('插件启动失败')"> 下载完成? <el-button type="primary" @click="destroyedAndCreate"> 点击此处 </el-button> 启动插件 </div> </div> </div> </div> </template> <script> import axios from 'axios'; export default { // 从父组件传递过来的 props: { setting: { // 设置项,带id type: Object, default: () => ({ id: 1, }), }, sysParams: { // 系统参数 type: Object, default: () => ({ appkey: "", // API 网关提供的 appkey secret: "", // API 网关提供的 secret ip: "", // API 网关 IP 地址 port:0 ,// API 网关端口 }), }, list: { // cameraCode列表 type: Array, default: () => [], }, layout: { // 布局 type: String, default: "1x1", }, }, data() { return { videoWidth: 0, videoHeight: 0, left: "", top: "", initCount: 0, // 启动次数 playMode: 0, // 0 预览 1回放 playText: "加载中...", cameraIndexCode: "", // 监控点编号 oWebControl: null, href: "http://localhost:7345/feature/cameraconfig/downloadVideoWebPlugin", selfEle: null, // 自身原始 //设置窗口遮挡 根据浏览器大小变化视频插件的大小 iLastCoverLeft: 0, iLastCoverTop: 0, iLastCoverRight: 0, iLastCoverBottom: 0, type:'live',//live实时rec回放 daterangeMonitorTime: [this.parseTime(new Date(new Date().setHours(0, 0, 0, 0))),this.parseTime(new Date())], initCount:0, //字符叠加 drawOSDParam:{ "argument": { "alignType": 1, "bold": 0, "color": 255, "fontSize": 32, "text": "噪声值:30.5", "wndId": 0, "x": 10, "y": 20 }, "funcName": "drawOSD" } }; }, mounted() { // 当前组件 this.selfEle = this.$refs.wrapper; this.observeWrapper(); // 首次加载时的到父容器的高度 this.playWndHeight = this.$refs.wrapper.clientHeight; // // 首次加载时的到父容器的宽度 this.playWndWidth = this.$refs.wrapper.clientWidth; // 初始化摄像头 // this.$nextTick(() => { // this.initPlugin(); // }); // 监听resize事件,使插件窗口尺寸跟随DIV窗口变化 window.addEventListener("resize", () => { if (this.oWebControl != null) { this.oWebControl.JS_Resize( this.$refs.wrapper.clientWidth, this.$refs.wrapper.clientHeight ); } }); // 监听滚动条scroll事件,使插件窗口跟随浏览器滚动而移动 window.addEventListener("scroll", () => { if (this.oWebControl != null) { this.oWebControl.JS_Resize( this.$refs.wrapper.clientWidth, this.$refs.wrapper.clientHeight ); } }); }, methods: { // 监听自身容器大小变化 observeWrapper() { // 监听 自身容器 元素宽度的变化 const ro = new ResizeObserver((entries) => { for (const entry of entries) { const cr = entry.contentRect; this.videoWidth = cr.width; this.videoHeight = cr.height; this.oWebControl && this.oWebControl.JS_Resize(this.videoWidth, this.videoHeight); this.oWebControl && this.setWndCover(); } }); ro.observe(document.querySelector("#hikvision-grid")); }, // 初始化+预览 createdVideo() { this.playText = "启动中..."; this.initPlugin(this.setting.id, () => { //this.multiPreviewVideo(); if (this.playMode == 0) { this.previewVideo();//预览 } }); }, // 销毁插件 destroyWnd(cb) { if (this.oWebControl) { this.oWebControl.JS_HideWnd(); this.oWebControl .JS_DestroyWnd({ funcName: "destroyeWnd", }) .then(function (oData) { }); } else { console.log("没有实例"); } cb && cb(); }, // 销毁并重启 destroyedAndCreate() { this.destroyWnd(() => { this.createdVideo(); }); }, // 初始化 init(callback) { this.getPubKey(() => { ////////////////////////////////// 请自行修改以下变量值 //////////////////////////////////// let appkey = this.sysParams.appkey; //综合安防管理平台提供的appkey,必填 let secret = this.setEncrypt(this.sysParams.secret); //综合安防管理平台提供的secret,必填 let ip = this.sysParams.ip; //综合安防管理平台IP地址,必填 let playMode = this.playMode; //初始播放模式:0-预览,1-回放 let port = this.sysParams.port; //综合安防管理平台端口,若启用HTTPS协议,默认443 let snapDir = "H:\\SnapDir"; //抓图存储路径 let videoDir = "H:\\VideoDir"; //紧急录像或录像剪辑存储路径 let layout = this.layout; //playMode指定模式的布局 let enableHTTPS = 1; //是否启用HTTPS协议与综合安防管理平台交互,是为1,否为0 let encryptedFields = "secret"; //加密字段,默认加密领域为secret let showToolbar = 1; //是否显示工具栏,0-不显示,非0-显示 let showSmart = 0; //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示 let buttonIDs = "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769"; //自定义工具条按钮 ////////////////////////////////// 请自行修改以上变量值 //////////////////////////////////// this.oWebControl .JS_RequestInterface({ funcName: "init", argument: JSON.stringify({ appkey: appkey, //API网关提供的appkey secret: secret, //API网关提供的secret ip: ip, //API网关IP地址 playMode: playMode, //播放模式(决定显示预览还是回放界面) port: port, //端口 snapDir: snapDir, //抓图存储路径 videoDir: videoDir, //紧急录像或录像剪辑存储路径 layout: layout, //布局 enableHTTPS: enableHTTPS, //是否启用HTTPS协议 encryptedFields: encryptedFields, //加密字段 showToolbar: showToolbar, //是否显示工具栏 showSmart: showSmart, //是否显示智能信息 buttonIDs: buttonIDs, //自定义工具条按钮 }), }) .then((oData) => { // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题 this.oWebControl.JS_Resize(this.videoWidth, this.videoHeight); callback && callback(); }); }); }, // 创建播放实例 initPlugin(id, callback) { let that = this; that.oWebControl = new WebControl({ szPluginContainer: id, // 指定容器id iServicePortStart: 15900, // 指定起止端口号,建议使用该值 iServicePortEnd: 15900, szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid cbConnectSuccess: function () { // 创建WebControl实例成功 that.oWebControl .JS_StartService("window", { // WebControl实例创建成功后需要启动服务 dllPath: "./VideoPluginConnect.dll", // 值"./VideoPluginConnect.dll"写死 }) .then( function () { // 启动插件服务成功 that.oWebControl.JS_SetWindowControlCallback({ // 设置消息回调 cbIntegrationCallBack: that.cbIntegrationCallBack, }); that.oWebControl .JS_CreateWnd(id, that.videoWidth, that.videoHeight) .then(() => { //JS_CreateWnd创建视频播放窗口,宽高可设定 that.init(callback); // 创建播放实例成功后初始化 }); }, function () { // 启动插件服务失败 } ); }, cbConnectError: () => { // 创建WebControl实例失败 that.oWebControl = null; that.playText = "插件未启动,正在尝试启动,请稍候..."; WebControl.JS_WakeUp("VideoWebPlugin://"); // 程序未启动时执行error函数,采用wakeup来启动程序 that.initCount++; if (that.initCount < 3) { setTimeout(() => { that.initPlugin(); }, 3000); } else { that.playText = `插件启动失败,请检查插件是否安装。请下载安装!<a href=\""+that.href+"\"; type="primary" download="VideoWebPlugin.exe" style='color:#4194fc'>下载插件</a>`; } }, cbConnectClose: (bNormalClose) => { // 异常断开:bNormalClose = false // JS_Disconnect正常断开:bNormalClose = true that.oWebControl = null; that.playText ="插件未启动,正在尝试启动,请稍候..."; WebControl.JS_WakeUp("VideoWebPlugin://"); that.initCount ++; if (that.initCount < 2) { setTimeout(function () { that.initPlugin(id, () => { if (that.playMode == 0) { that.previewVideo();//预览 } }); }, 3000) } else { that.playText ="插件启动失败,请检查插件是否安装。请下载安装!<a href=\""+that.href+"\"; type=\"primary\" download=\"VideoWebPlugin.exe\" style='color:#4194fc;text-decoration:underline;'>下载插件</a>"; } }, }); }, // 关闭 handleClose() { if (this.oWebControl) { this.oWebControl.JS_RequestInterface({ funcName: "stopAllPreview", }); this.oWebControl.JS_HideWnd(); // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题 this.oWebControl.JS_Disconnect().then( () => { // 断开与插件服务连接成功 }, () => { // 断开与插件服务连接失败 } ); this.oWebControl = null; } }, // 消息回调 cbIntegrationCallBack(oData) { // console.log(oData); }, // 预览 previewVideo() { let cameraIndexCode = this.list[0]; // 获取输入的监控点编号值,必填 let streamMode = 1; // 主子码流标识:0-主码流,1-子码流 let transMode = 1; // 传输协议:0-UDP,1-TCP let gpuMode = 0; // 是否启用GPU硬解,0-不启用,1-启用 let wndId = -1; // 播放窗口序号(在2x2以上布局下可指定播放窗口) this.oWebControl.JS_RequestInterface({ funcName: "startPreview", argument: JSON.stringify({ cameraIndexCode: cameraIndexCode.trim(), // 监控点编号 streamMode: streamMode, // 主子码流标识 transMode: transMode, // 传输协议 gpuMode: gpuMode, // 是否开启GPU硬解 wndId: wndId, // 可指定播放窗口 }), }); }, // 批量预览 multiPreviewVideo() { let streamMode = 1; // 主子码流标识:0-主码流,1-子码流 let transMode = 1; // 传输协议:0-UDP,1-TCP let gpuMode = 0; // 是否启用GPU硬解,0-不启用,1-启用 this.oWebControl .JS_RequestInterface({ funcName: "startMultiPreviewByCameraIndexCode", argument: JSON.stringify({ list: this.list.map((camera, idx) => { return { cameraIndexCode: camera, //监控点编号 streamMode, //主子码流标识 transMode, //传输协议 gpuMode, //是否开启GPU硬解 wndId: idx + 1, // 播放窗口序号(在2x2以上布局下可指定播放窗口) }; }), // 监控点编号集合 }), }) .then((res) => { if (res.errorCode === 0) { console.log("预览成功"); } }); }, //获取公钥 getPubKey(callback) { this.oWebControl .JS_RequestInterface({ funcName: "getRSAPubKey", argument: JSON.stringify({ keyLength: 1024, }), }) .then((oData) => { if (oData.responseMsg.data) { this.pubKey = oData.responseMsg.data; callback(); } }); }, //RSA加密 setEncrypt(value) { let encrypt = new JSEncrypt(); encrypt.setPublicKey(this.pubKey); return encrypt.encrypt(value); }, //设置窗口遮挡 // setWndCover() { // let iWidth = document.body.clientWidth; // let iHeight = document.body.clientHeight; // let oDivRect = document.getElementById("divPlugin").getBoundingClientRect(); // let iCoverLeft = (oDivRect.left < 0) ? Math.abs(oDivRect.left): 0; // let iCoverTop = (oDivRect.top < 0) ? Math.abs(oDivRect.top): 0; // let iCoverRight = (oDivRect.right - iWidth > 0) ? Math.round(oDivRect.right - iWidth) : 0; // let iCoverBottom = (oDivRect.bottom - iHeight > 0) ? Math.round(oDivRect.bottom - iHeight) : 0; // iCoverLeft = (iCoverLeft > 700) ? 700 : iCoverLeft; // iCoverTop = (iCoverTop > 400) ? 400 : iCoverTop; // iCoverRight = (iCoverRight > 700) ? 700 : iCoverRight; // iCoverBottom = (iCoverBottom > 400) ? 400 : iCoverBottom; // if (this.iLastCoverLeft != iCoverLeft) { // console.log("iCoverLeft: " + iCoverLeft); // this.iLastCoverLeft = iCoverLeft; // this.oWebControl.JS_SetWndCover("left", iCoverLeft); // } // if (this.iLastCoverTop != iCoverTop) { // console.log("iCoverTop: " + iCoverTop); // this.iLastCoverTop = iCoverTop; // this.oWebControl.JS_SetWndCover("top", iCoverTop); // } // if (this.iLastCoverRight != iCoverRight) { // console.log("iCoverRight: " + iCoverRight); // this.iLastCoverRight = iCoverRight; // this.oWebControl.JS_SetWndCover("right", iCoverRight); // } // if (this.iLastCoverBottom != iCoverBottom) { // console.log("iCoverBottom: " + iCoverBottom); // this.iLastCoverBottom = iCoverBottom; // this.oWebControl.JS_SetWndCover("bottom", iCoverBottom); // } // }, // 设置窗口裁剪,当因滚动条滚动导致窗口需要被遮住的情况下需要JS_CuttingPartWindow部分窗口 setWndCover() { let iWidth = $(window).width(); // 获取浏览器宽度 不含滚动条 let iHeight = $(window).height(); let oDivRect = $("#" + this.setting.id) .get(0) .getBoundingClientRect(); let iCoverLeft = oDivRect.left < 0 ? Math.abs(oDivRect.left) : 0; let iCoverTop = oDivRect.top < 0 ? Math.abs(oDivRect.top) : 0; let iCoverRight = oDivRect.right - iWidth > 0 ? Math.round(oDivRect.right - iWidth) : 0; let iCoverBottom = oDivRect.bottom - iHeight > 0 ? Math.round(oDivRect.bottom - iHeight) : 0; iCoverLeft = iCoverLeft > this.videoWidth ? this.videoWidth : iCoverLeft; iCoverTop = iCoverTop > this.videoHeight ? this.videoHeight : iCoverTop; iCoverRight = iCoverRight > this.videoWidth ? this.videoWidth : iCoverRight; iCoverBottom = iCoverBottom > this.videoHeight ? this.videoHeight : iCoverBottom; // 多1个像素点防止还原后边界缺失一个像素条 this.oWebControl.JS_RepairPartWindow( 0, 0, this.videoWidth + 1, this.videoHeight ); if (iCoverLeft != 0) { this.oWebControl.JS_CuttingPartWindow( 0, 0, iCoverLeft, this.videoHeight ); } if (iCoverTop != 0) { // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条 this.oWebControl.JS_CuttingPartWindow( 0, 0, this.videoWidth + 1, iCoverTop ); } if (iCoverRight != 0) { this.oWebControl.JS_CuttingPartWindow( this.videoWidth - iCoverRight, 0, iCoverRight, this.videoHeight ); } if (iCoverBottom != 0) { this.oWebControl.JS_CuttingPartWindow( 0, this.videoHeight - iCoverBottom, this.videoWidth, iCoverBottom ); } }, //改变播放类型 changeType() { if (this.type == 'live') {//0预览 this.playMode = 0; } else {//1回放 this.playMode = 1; } this.destroyedAndCreate(); }, //录像回放功能 startPlayback() { if (null == this.daterangeMonitorTime || '' == this.daterangeMonitorTime) { this.$modal.msgError("请选择时间"); return; } let cameraIndexCode = this.list[0]; // 获取输入的监控点编号值,必填 var startTimeStamp = new Date(this.daterangeMonitorTime[0]).getTime(); //回放开始时间戳,必填 var endTimeStamp = new Date(this.daterangeMonitorTime[1]).getTime(); //回放结束时间戳,必填 var recordLocation = 1; //录像存储位置:0-中心存储,1-设备存储 var transMode = 0; //传输协议:0-UDP,1-TCP var gpuMode = 0; //是否启用GPU硬解,0-不启用,1-启用 var wndId = -1; //播放窗口序号(在2x2以上布局下可指定播放窗口) this.oWebControl.JS_RequestInterface({ funcName: "startPlayback", argument: JSON.stringify({ cameraIndexCode: cameraIndexCode, //监控点编号 startTimeStamp: Math.floor(startTimeStamp / 1000).toString(), //录像查询开始时间戳,单位:秒 endTimeStamp: Math.floor(endTimeStamp / 1000).toString(), //录像结束开始时间戳,单位:秒 recordLocation: recordLocation, //录像存储类型:0-中心存储,1-设备存储 transMode: transMode, //传输协议:0-UDP,1-TCP gpuMode: gpuMode, //是否启用GPU硬解,0-不启用,1-启用 wndId: wndId //可指定播放窗口 }) }) }, // 停止回放 stopPlayback() { this.oWebControl.JS_RequestInterface({ funcName: "stopAllPlayback" }) }, // value为字符串,JS_RequestInterface仅接收json格式的变量,且需要先解析出argument,并且将argument字段的内容转为字符串 requestInterface() { var JsonParam = this.drawOSDParam; var JsonArgument = JsonParam.argument; JsonParam.argument = JSON.stringify(JsonArgument); this.oWebControl.JS_RequestInterface(JsonParam).then(function (oData) { console.log(oData) }); }, // 判断字符串是否为json isJSON(str) { if (typeof str == 'string') { try { var obj = JSON.parse(str); if (typeof obj == 'object' && obj) { return true; } else { console.log("param is not the correct JSON message"); return false; } } catch (e) { console.log("param is not the correct JSON message"); return false; } } console.log('It is not a string!') } }, destroyed() { this.destroyWnd(); }, watch: { list: { immediate: true, deep: true, handler(value) { if (value.length > 0) { console.log("watch海康威视组件的列表list:", value); this.destroyedAndCreate(); } else { this.destroyWnd(() => { this.oWebControl = null; }); if (value.length === 0) { this.playText = "<span style='color:#fff;font-size:27px;'>暂无现场监控视频!!</span>"; } else { this.playText = "<span style='color:#fff;font-size:27px;'>现场监控暂不可用,请刷新后再试!!</span>"; } } }, }, "$store.state.videohide"(n, o) { if (n) { this.oWebControl.JS_HideWnd(); } else if (!n) { this.oWebControl.JS_ShowWnd(); } }, }, }; </script> <style lang="less" scoped> .playWnd { // margin: 30px 0 0 400px; width: 1000px; /*播放容器的宽和高设定*/ height: 600px; border: 1px solid red; } .operate { margin-top: 24px; } .operate::after { content: ""; display: block; clear: both; } .module { float: left; width: 340px; /*min-height: 320px;*/ margin-left: 16px; padding: 16px 8px; box-sizing: border-box; border: 1px solid #e5e5e5; } .module .item { margin-bottom: 4px; } .module input[type="text"] { box-sizing: border-box; display: inline-block; vertical-align: middle; margin-left: 0; width: 150px; min-height: 20px; } .module .btn { min-width: 80px; min-height: 24px; margin-top: 100px; margin-left: 80px; } </style>
5、页面引用组件,显示视频
<monitorVideoVue :sys-params="sysParams" :list="curShowList"></monitorVideoVue>
import monitorVideoVue from '../monitorVideo';
data中放入
//海康平台参数
sysParams:{
appkey:"",
secret:"",
ip:"",
port:443
},
curShowList: [], // 当前能显示的摄像头
6、我只使用了一个窗口显示,默认进入显示实时预览,可通过按钮切换回放。