海康摄像头技术在现代化项目管理中的实际应用
前言
最近做项目的过程中遇到了在页面中播放摄像机拍摄的实时视频的需求,于是开始各种收集资料,本来想使用rtsp形式来播放视频流,无奈该方式有些延迟只能再寻找其他方式。因为现场的摄像机设备就是使用的海康,所以在海康的官网中找到了对应的视频播放插件 海康官网
下载插件
进入官网后需要把第一个插件包下载下来,然后会得到一个压缩包,我们只需要安装一下bin
目录下的VideoWebPlugin.exe
安装包就可以了。
使用插件
引入插件
以vue2项目为例,首先要将插件包中的demo
文件夹下的jquery-1.12.4.min.js jsencrypt.min.js web-control_1.2.5.min.js
文件放入public文件夹并在index.html文件中进行引入。
<script type="text/javascript" src="./static/haikang/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="./static/haikang/jsencrypt.min.js"></script>
<script type="text/javascript" src="./static/haikang/web-control_1.2.5.min.js"></script>
初始化插件
完成插件的引入后在window
对象上会有一个WebControl
的函数,然后通过使用new
生成实例对象。
data() {
return {
oWebControl: null,
objData: {
//海康初始化数据
appkey: "26076135",
ip: "223.99.211.253",
secret: "YQ4AZpQ1BcOFahnEx07h",
port: 1443,
playMode: 0, // 0 预览 1回放
layout: "1x1", //页面展示的模块数【16】
},
list: ['118623de0848450aaf557e0be2ce9069', '388252741a9d4c73b3c0cddfea650359', '2095dd7a4e1f45c999592f77a05467de', '72849719cb4348d5975fdc21ee782b40', '25145a1c83a04d239f54f3cd74aa4524', '567a5e40a5464e8cb2ebc2ead14ec568', '3d5c276ca387403296fa605412f2e394', 'ab86f052ea2b41a3b8c863ba21037847', '22e997ff2e184381a6b419d0018e2e1b'],
}
},
mounted() {
this.initPlugin("playVideo", 250, 250);
},
methods: {
initPlugin(box, width, height) {
this.oWebControl = new WebControl({
szPluginContainer: box, // 指定容器id
iServicePortStart: 15900, // 指定起止端口号,建议使用该值
iServicePortEnd: 15909,
szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
cbConnectSuccess: () => {
// 创建WebControl实例成功
this.oWebControl
.JS_StartService("window", {
// WebControl实例创建成功后需要启动服务
// 值"./VideoPluginConnect.dll"写死
dllPath: "./VideoPluginConnect.dll",
})
.then(
()=> {
// 设置消息回调
this.oWebControl.JS_SetWindowControlCallback({
cbIntegrationCallBack: this.cbIntegrationCallBack,
});
//JS_CreateWnd创建视频播放窗口,宽高可设定
this.oWebControl
.JS_CreateWnd(box, width, height, { bEmbed: true })
.then( ()=> {
// 创建播放实例成功后初始化
this.init(width, height);
});
},
()=> {
// 启动插件服务失败
}
);
},
// 创建WebControl实例失败
cbConnectError: () =>{
this.oWebControl = null;
// this.$message.warning("插件未启动,正在尝试启动,请稍候...");
},
cbConnectClose: () => {
// 异常断开:bNormalClose = false
// JS_Disconnect正常断开:bNormalClose = true
this.oWebControl = null;
},
});
},
}
list
中存放的是摄像机的编号,这里先固定写了几个。在initPlugin
函数中共接收三个参数,分别是视频容器的id、宽度和高度,以上大部分都是一些固定的钩子函数和写法,我们着重关注初始化成功时的回调函数,实例初始化成功后会调用init
方法。
async init(width, height) {
await this.getPubKey(() => {
let appkey = this.objData.appkey; //综合安防管理平台提供的appkey,必填
let secret = this.setEncrypt(this.objData.secret); //综合安防管理平台提供的secret,必填
let ip = this.objData.ip; //综合安防管理平台IP地址,必填
let playMode = this.objData.playMode; //初始播放模式:0-预览,1-回放
let port = this.objData.port; //综合安防管理平台端口,若启用HTTPS协议,默认443
let snapDir = "D:\\SnapDir"; //抓图存储路径
let videoDir = "D:\\VideoDir"; //紧急录像或录像剪辑存储路径
let layout = this.objData.layout; //playMode指定模式的布局
let enableHTTPS = 1; //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
let encryptedFields = "secret"; //加密字段,默认加密领域为secret
let showToolbar = 1; //是否显示工具栏,0-不显示,非0-显示
let showSmart = 1; //是否显示智能信息(如配置移动侦测后画面上的线框),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, //自定义工具条按钮
}),
})
.then(function (oData) {
this.oWebControl.JS_Resize(width, height); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
});
});
setTimeout(() => {
this.selecttype()
}, 200)
},
// RSA 加密
setEncrypt(value) {
let encrypt = new window.JSEncrypt();
encrypt.setPublicKey(this.pubKey);
return encrypt.encrypt(value);
},
在init
方法中分别调用了getPubKey
和setEncrypt
来获取公钥和进行加密操作,然后开始进入到selecttype
方法中。
async selecttype() {
await this.preview()
},
preview() {
this.list.forEach(item => {
this.previewVideo(item)
})
},
previewVideo(data) {
let cameraIndexCode = data; // 获取输入的监控点编号值,必填
let streamMode = 0; // 主子码流标识:0-主码流,1-子码流
let transMode = 0; // 传输协议: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, // 可指定播放窗口
}),
});
},
这时就可以在页面中看到视频加载的效果。
最终效果
视频流畅度相对来说还是比较稳定的,而且这个视频控件中自带了很多功能,比如放大缩小、多个视频布局展示设置、全屏、截图、画中画、录音等功能,如果需要用到这些的话可以在此基础上进行定制开发。
存在的问题
唯一存在的问题就是样式上的问题,视频加载完毕后它的层级会很高,这时候如果有弹窗要显示的话会被其覆盖,并且切换页面或者路由也不会隐藏,因为它并不存在于DOM结构中,针对这一问题通过查阅开发手册发现有相关方法可以解决这一问题。(开发手册也在下载的插件包中~)
router.beforeEach((to, from, next) => {
// 销毁视频控件
if (Vue.prototype.oWebControl) {
// 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
Vue.prototype.oWebControl.JS_HideWnd();
// 销毁当前播放的视频
Vue.prototype.oWebControl.JS_RequestInterface({ funcName: "destroyWnd" });
// 断开与插件服务连接
Vue.prototype.oWebControl.JS_Disconnect();
Vue.prototype.oWebControl = null;
}
next()
})
这里我写到了路由全局守卫中来做一个全局的控制,在初始化完毕后使用Vue.prototype.oWebControl = this.oWebControl;
收集其实例对象,这样一来跳转页面的时候就会命中上面的代码。
转载自:https://juejin.cn/post/7366264344393334810