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、我只使用了一个窗口显示,默认进入显示实时预览,可通过按钮切换回放。

浙公网安备 33010602011771号