原创不易,如果觉得对你有所帮助,拜托点赞哦~~ ^_^
最近在做一个Vue项目,其中一个需求,就是在页面中展示出海康威视的监控图像,并进行云台控制。
研究的过程还是有点儿痛苦的,这类技术文章数量不多,即便找到了一些,也是看起来有点儿不知所云(也许是我自身能力的问题吧)。
经过一段时间的研究,最终比较成功的实现了需求,在这里分享给大家,我尽可能把本文写成傻瓜式的风格,因为我感觉接触一个新事物时,哪怕其中一个小步骤没搞明白,都会极大的影响你对新事物的理解,希望本文能使你绕开我之前的痛苦历程。
首先要感谢博主“大前端技术沙龙”的文章《海康威视web控件开发的正确姿势》,该文章末尾提供了开发包下载链接,亲测可用,而且我的Vue项目中最终移植的也是该开发包中的相关文件。
该文章提供的开发包有两个:32位的和64位的,我试了一下,两个demo程序都能用,先安装开发包中的“WebComponentsKit.exe”,然后用IE(必须是IE)来打开demo.html,demo程序就算运行起来了,如下图,点击“允许阻止的内容”按钮
虽然控件的说明文档中说支持chrome,但我试了,无法正常调出监控画面,我估计是控件加载的问题,正好客户也是用IE,所以我还没去研究怎么在chrome中使用。有研究出来的小伙伴麻烦告诉我一下,我也很想知道,谢谢!
接着如下图,在红色块的位置输入IP、端口号(一般为80)、用户名、密码后,点击“登录”按钮,蓝色块中就会显示出已登录上的监控设备的信息,此时再点击“开始预览”按钮,即可看到监控画面(因保密需求,画面进行了遮挡)
demo.html的成功运行,给了我非常大的信心(之前也下载过一些海康的demo,但未能正常运行),既然它能正常工作,那我只要吃透它的源码,就肯定能实现我要的功能。
接下来,打开demo.html的源码,看到里面引入了demo.js文件,事实上,你在demo程序中点击各种按钮,都是去调用的demo.js中的响应方法。
再打开demo.js,就会发现,它又去调用了如“WebVideoCtrl.I_InitPlugin”、“WebVideoCtrl.I_InsertOBJECTPlugin”等一系列的以“WebVideoCtrl.I_”开头的函数,这些函数就是海康提供的API。这些API都来自开发包中的“webVideoCtrl.js”文件。
这样就大概搞明白了demo程序的逻辑,正式开始移植开发包到自己的Vue项目中:
第一步、见下图,将开发包中的“jquery-1.7.1.min.js”和“webVideoCtrl.js”这两个文件拷贝过来并放入hikvision文件夹,图中的demo.js和demo.css其实是用不到的,不需要拷贝到Vue项目中。
demo.js是我刚开始没吃透代码时,用来直接调里面的方法,以避免出bug。后期熟悉代码后,直接调用webVideoCtrl.js的API即可,demo.js也就没用了。
demo.css也没啥用处,项目中并未引用该文件。
另外,hikvision文件夹似乎必须放在public文件夹中,我试着放入src文件夹后,就无法正常工作了,原因未知,有懂的小伙伴希望不吝赐教。
第二步、见下图,在index.html的底部,即</body>标签后引入“jquery-1.7.1.min.js”和“webVideoCtrl.js”(看到别的文章说要在底部引入文件,我照葫芦画瓢,没去试在其他位置引入是否可行)。
</body><script src="./hikvision/jquery-1.7.1.min.js"></script><script id="videonode" src="./hikvision/webVideoCtrl.js"></script>
</html>
第三步、要想显示出监控画面,主要有三个步骤
- 初始化视频插件、并将插件嵌入id为“divPlugin”的<div>中
- 登录监控设备
- 播放画面
接下来我们来依次实现这三个步骤。
首先,新建一个vue组件,比如camera.vue,<template>代码如下:
<template><div class="container">//此div用于视频插件嵌入<div id="divPlugin" class="plug">haha</div><button @click="InitCamera">Init</button><button @click="cameraLogin">login</button><button @click="cameraPlay">play</button><button @click="cameraDirectPlay">一键播放</button><button @click="cameraLogout">登出</button></div>
</template>
为了保证三个步骤都正确执行,我用了个笨方法,使用三个按钮,每个按钮的@click绑定一个方法,分别对应初始化插件、登录监控设备、播放画面。在methods里写对应的方法,见下图:
注:上图中的IP、用户名、密码都是假的,填写你自己设备的信息。另外你们看到的“119.119.119.119_80”的写法是API要求的格式,是将IP和端口号用下划线连接,即“IP_port”。
然后随便你是把camera组件放入父组件中调用,还是用路由单独调用,总之找个地方调用它,接着npm run serve后,老规矩用IE打开。
按顺序依次点击init、login、play按钮,就能看到监控播放啦!!撒花~~~
然而你乐早了。。。
第四步、进一步改进,很明显三个按钮依次按下才播放,太没有人性,需改为按一个按钮即可播放,即上图中那个“一键播放”按钮。
实现的思路也很简单,就是把三个按钮的响应代码全写进“一键播放”按钮的@click方法中,但单纯堆代码会有bug,下图是我最初写的“一键播放”按钮的响应代码。
//功能不正常的代码 cameraDirectPlay(){//第一步,初始化并嵌入插件WebVideoCtrl.I_InitPlugin("100%", "100%",{bWndFull: true,iPackageType: 2,iWndowType: 1,cbInitPluginComplete: function () {WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin");console.log("初始化成功")}})//第二步,登录设备WebVideoCtrl.I_Login('119.119.119.119', 1, '80', '用户名', '密码',{success:function (){WebVideoCtrl.I_GetAnalogChannelInfo('119.119.119.119_80',{async: false})console.log("登录成功")}})//第三步,播放画面WebVideoCtrl.I_StartRealPlay('119.119.119.119_80', {success: function () {console.log('预览成功')},error: function (status, xmlDoc) {console.log('预览失败')}})},
上面这段代码就是简单的把之前的三个按钮的响应方法的代码堆在一起,出现的bug是:第一次按下“一键播放”按钮后,无画面出现,再按一次才出现画面。
为何会这样?接下来利用console.log来查找原因,会发现是第二步登录监控设备尚未成功时,第三步播放画面已经执行了,从而导致了bug。于是机智的我立刻想到用setTimeout延迟执行第三步,待监控设备登录后再执行第三步即可,果然成功了!撒花~~~
然而你又乐早了,setTimeout的确可以解决问题,但设置多少秒合适?我设置了0.5秒,但万一在其他电脑上0.5秒不够又或者太长呢?这就太不灵活了。
后来我注意到第二步“登录设备”的API(即WebVideoCtrl.I_Login函数)可以在success和error两种情况下使用回调函数,这就解决了我的问题,只需把第三步“播放画面”的代码嵌入第二步“登录设备”的success中进行回调即可,也就是说当第二步“登录设备”成功后,才会去执行第三步“播放画面”。
最终正确代码如下:
//“一键播放”按钮的@click响应代码 cameraDirectPlay(){//第一步,初始化并嵌入插件WebVideoCtrl.I_InitPlugin("100%", "100%",{bWndFull: true,iPackageType: 2,iWndowType: 1,cbInitPluginComplete: function () {WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin");console.log("初始化成功")}})//第二步,登录设备WebVideoCtrl.I_Login('119.119.119.119', 1, '80', '用户名', '密码',{success:function (){WebVideoCtrl.I_GetAnalogChannelInfo('119.119.119.119_80',{async: false})console.log("登录成功")//第三步,播放画面// 可以看到第三步的代码放入了第二步的success中回调WebVideoCtrl.I_StartRealPlay('119.119.119.119_80', {success: function () {console.log('预览成功')},error: function (status, xmlDoc) {console.log('预览失败')}})}})},
运行效果如下:
按惯例遮挡画面,嘿嘿。
播放功能已实现,就是挺丑的,爱美的你可以祭出CSS了。
至于云台控制,其实跟播放画面的实现差不多流程,而且更简单,所以我偷懒就不写了,这样也能锻炼大家的自我学习能力,只需看看demo.html和demo.js,聪明的你就会明白怎么做云台控制了。