web前端在vue中通过海康插件嵌入视频,实现实时预览以及视频回放功能
首先第一步,在海康官网下海康视频插件下载到电脑中海康开放平台
然后新建一个组件,下面我直接把我封装好的组件代码拿出来,重要的地方我在代码中添加了注释
<template><div ref="iSecureCenter" style="height: 100%; width: 100%"></div>
</template><script>
import moment from 'moment'
export default {name: 'iSecureCenterContainer',props: {iSecureCenterConfig: {type: Object,default: () => {return {appkey: '',secret: '',ip: '',playMode: 0,snapDir: 'D:\\SnapDir',videoDir: 'D:\\VideoDir',layout: '1x1',//窗口样式cameraIndexCodeList: [''],previewCode: '',}},},},data() {return {id: '',oWebControl: null,pubKey: '',initCount: 0,divInfo: {width: 0,height: 0,},}},computed: {formatId() {return '#' + this.id},},watch: {iSecureCenterConfig: function (val, oldVal) {console.log(val)if (val.playMode !== oldVal.playMode) {console.log(val.playMode)this.oWebDestroyWnd()this.initPlugin()}if (val.previewCode && val.previewCode !== oldVal.previewCode) {this.startPreview(val.previewCode)}},},mounted() {// this.id = window.crypto.randomUUID()this.id = new Date().getTime().toString()console.log(this.id)this.$refs.iSecureCenter.id = this.id//获取id,绑定div,渲染没有插件的情况下,提示下载。let doc = document.getElementById(this.id)doc.style.color = '#fff'doc.style.fontSize = '20px'doc.style.fontWeight = '600'this.divInfo.width = $(this.formatId).width()this.divInfo.height = $(this.formatId).height()this.initPlugin()window.addEventListener('resize', this.listenerFunc)window.addEventListener('scroll', this.listenerFunc)// window.addEventListener('')// this.iSecureCenterConfig.cameraIndexCodeList?.forEach(item => {// this.startPreview(item)// })},beforeDestroy() {window.removeEventListener('resize', this.listenerFunc)window.removeEventListener('scroll', this.listenerFunc)if (this.oWebControl != null) {this.oWebControl.JS_HideWnd() // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题this.oWebControl.JS_Disconnect().then(function () {// 断开与插件服务连接成功},function () {// 断开与插件服务连接失败})}console.log('beforeDestroy')},methods: {initPlugin() {this.oWebControl = new WebControl({szPluginContainer: this.id, // 指定容器idiServicePortStart: 15900, // 指定起止端口号,建议使用该值iServicePortEnd: 15900,szClassId: '', // 用于IE10使用ActiveX的clsidcbConnectSuccess: () => {// 创建WebControl实例成功this.oWebControl.JS_StartService('window', {// WebControl实例创建成功后需要启动服务dllPath: './VideoPluginConnect.dll', // 值"./VideoPluginConnect.dll"写死}).then(() => {// 启动插件服务成功this.oWebControl.JS_SetWindowControlCallback({// 设置消息回调cbIntegrationCallBack: this.cbIntegrationCallBack,})const { width, height } = this.divInfothis.oWebControl.JS_CreateWnd(this.id, width, height).then(() => {//JS_CreateWnd创建视频播放窗口,宽高可设定this.init() // 创建播放实例成功后初始化})},function () {// 启动插件服务失败})},cbConnectError: () => {// 创建WebControl实例失败this.oWebControl = null$(this.formatId).html('插件未启动,正在尝试启动,请稍候...')WebControl.JS_WakeUp('VideoWebPlugin://') // 程序未启动时执行error函数,采用wakeup来启动程序this.initCount++if (this.initCount < 3) {setTimeout(() => {this.initPlugin()}, 3000)} else {$(this.formatId).html(`<div><div>插件启动失败,请检查插件是否安装!</div><div>插件下载地址:<a href='下载地址' target=_blank underline>点击下载</a></div></div>`)}},cbConnectClose: (bNormalClose) => {// 异常断开:bNormalClose = false// JS_Disconnect正常断开:bNormalClose = trueconsole.log('cbConnectClose')this.oWebControl = null$(this.formatId).html('插件未启动,正在尝试启动,请稍候...')WebControl.JS_WakeUp('VideoWebPlugin://')this.initCount++if (this.initCount < 3) {setTimeout(() => {this.initPlugin()}, 3000)} else {$(this.formatId).html(`<div><div>插件启动失败,请检查插件是否安装!</div><div>插件下载地址:<a href='下载地址' target=_blank underline>点击下载</a></div></div>`)}},})},// 设置窗口控制回调setCallbacks() {this.oWebControl.JS_SetWindowControlCallback({cbIntegrationCallBack: function (oData) {this.showCBInfo(JSON.stringify(oData.responseMsg))},})},// 推送消息// cbIntegrationCallBack(oData) {// showCBInfo(JSON.stringify(oData.responseMsg));// },//初始化init() {this.getPubKey(() => {// 请自行修改以下变量值 const appkey = this.iSecureCenterConfig.appkey //综合安防管理平台提供的appkey,必填const secret = this.setEncrypt(this.iSecureCenterConfig.secret) //综合安防管理平台提供的secret,必填const ip = this.iSecureCenterConfig.ip //综合安防管理平台IP地址,必填const playMode = this.iSecureCenterConfig.playMode //初始播放模式:0-预览,1-回放const port = 443 //综合安防管理平台端口,若启用HTTPS协议,默认443const snapDir = this.iSecureCenterConfig?.snapDir ?? 'D:\\SnapDir' //抓图存储路径const videoDir = this.iSecureCenterConfig?.videoDir ?? 'D:\\VideoDir' //紧急录像或录像剪辑存储路径const layout = this.iSecureCenterConfig?.layout ?? '1x1' //playMode指定模式的布局const enableHTTPS = 1 //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1const encryptedFields = 'secret' //加密字段,默认加密领域为secretconst showToolbar = 1 //是否显示工具栏,0-不显示,非0-显示const showSmart = 0 //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示const 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网关提供的appkeysecret: secret, //API网关提供的secretip: 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) => {console.log(oData)const { width, height } = this.divInfo// this.startPreview()this.initPreviewList()this.oWebControl.JS_Resize(width, height) // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题})})},//获取公钥getPubKey(callback) {this.oWebControl.JS_RequestInterface({funcName: 'getRSAPubKey',argument: JSON.stringify({keyLength: 1024,}),}).then((oData) => {console.log(oData)if (oData.responseMsg.data) {this.pubKey = oData.responseMsg.datacallback()}})},//RSA加密setEncrypt(value) {var encrypt = new JSEncrypt()encrypt.setPublicKey(this.pubKey)return encrypt.encrypt(value)},setWndCover() {const { width, height } = this.divInfoconst iWidth = $(window).width()const iHeight = $(window).height()const oDivRect = $(this.formatId).get(0).getBoundingClientRect()let iCoverLeft = oDivRect.left < 0 ? Math.abs(oDivRect.left) : 0let iCoverTop = oDivRect.top < 0 ? Math.abs(oDivRect.top) : 0let iCoverRight = oDivRect.right - iWidth > 0 ? Math.round(oDivRect.right - iWidth) : 0let iCoverBottom = oDivRect.bottom - iHeight > 0 ? Math.round(oDivRect.bottom - iHeight) : 0iCoverLeft = iCoverLeft > width ? width : iCoverLeftiCoverTop = iCoverTop > height ? height : iCoverTopiCoverRight = iCoverRight > width ? width : iCoverRightiCoverBottom = iCoverBottom > height ? height : iCoverBottomthis.oWebControl.JS_RepairPartWindow(0, 0, width + 1, height) // 多1个像素点防止还原后边界缺失一个像素条if (iCoverLeft != 0) {this.oWebControl.JS_CuttingPartWindow(0, 0, iCoverLeft, height)}if (iCoverTop != 0) {this.oWebControl.JS_CuttingPartWindow(0, 0, width + 1, iCoverTop) // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条}if (iCoverRight != 0) {this.oWebControl.JS_CuttingPartWindow(width - iCoverRight, 0, iCoverRight, height)}if (iCoverBottom != 0) {this.oWebControl.JS_CuttingPartWindow(0, height - iCoverBottom, width, iCoverBottom)}},listensFunc() {const { width, height } = this.divInfo// 监听resize事件,使插件窗口尺寸跟随DIV窗口变化$(window).resize(() => {if (this.oWebControl != null) {this.oWebControl.JS_Resize(width, height)this.setWndCover()}})// 监听滚动条scroll事件,使插件窗口跟随浏览器滚动而移动$(window).scroll(() => {if (this.oWebControl != null) {this.oWebControl.JS_Resize(width, height)this.setWndCover()}})// 标签关闭$(window).unload(function () {if (oWebControl != null) {this.oWebControl.JS_HideWnd() // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题this.oWebControl.JS_Disconnect().then(function () {// 断开与插件服务连接成功},function () {// 断开与插件服务连接失败})}})},initPreviewList() {this.iSecureCenterConfig.cameraIndexCodeList?.forEach((item) => {this.oWebControl.JS_RequestInterface({funcName: 'startPreview',argument: JSON.stringify({cameraIndexCode: item, //监控点编号streamMode: 0, //主子码流标识transMode: 1, //传输协议gpuMode: 0, //是否开启GPU硬解wndId: -1, //可指定播放窗口}),})})},startPreview(cameraIndexCode) {// this.iSecureCenterConfig.cameraIndexCodeList.forEach(item => {// this.oWebControl.JS_RequestInterface({// funcName: "startPreview",// argument: JSON.stringify({// cameraIndexCode: item, //监控点编号// streamMode: 0, //主子码流标识// transMode: 1, //传输协议// gpuMode: 0, //是否开启GPU硬解// wndId: -1 //可指定播放窗口// })// })// })this.oWebControl.JS_RequestInterface({funcName: 'startPreview',argument: JSON.stringify({cameraIndexCode: cameraIndexCode, //监控点编号streamMode: 0, //主子码流标识transMode: 1, //传输协议gpuMode: 0, //是否开启GPU硬解wndId: -1, //可指定播放窗口}),})},listenerFunc() {this.divInfo.width = $(this.formatId).width()this.divInfo.height = $(this.formatId).height()const { width, height } = this.divInfoif (this.oWebControl != null) {this.oWebControl.JS_Resize(width, height)this.setWndCover()}},// 设置插件显示隐藏setoWebControlVisible(bol = true) {if (bol) {this.oWebControl.JS_HideWnd()} else {this.oWebControl.ShowWnd()}},// 插件停止所有视频预览oWebAllVideoStop() {this.oWebControl.JS_RequestInterface({funcName: 'stopAllPreview',})},oWebDestroyWnd() {this.oWebControl.JS_DestroyWnd()},oWebStartPlayback(cameraIndexCode,// startTimeStamp = moment().startOf('week').unix(),startTimeStamp =moment().add(-7, 'd').unix(),//历史视频开始时间,目前维度7天endTimeStamp = moment().unix(),//历史视频截至时间playTimeStamp=moment().startOf('day').unix(),//视频回放开始播放时间recordLocation = 1,transMode = 0,wndId = -1) {console.log(cameraIndexCode, startTimeStamp, moment().startOf('week'))this.oWebControl.JS_RequestInterface({funcName: 'startPlayback',argument: { cameraIndexCode, startTimeStamp, endTimeStamp, recordLocation, transMode ,playTimeStamp},})},},
}
</script>
以上是封装的组件,下面是调用的方法
<iSecureCenterContainer :iSecureCenterConfig="iSecureCenterConfig" ref="iSecureCenterRef" />
//先引入组件在data中定义的 iSecureCenterConfig: {appkey: '',secret: '',ip: '',playMode: 0,snapDir: 'D:\\SnapDir',videoDir: 'D:\\VideoDir',layout: '3x3',cameraIndexCodeList: [],previewCode: '',},//点击视频的时候触发的方法 判断是历史视频还是实时预览handleNodeClick(data) {console.log(data)if (this.iSecureCenterConfig.playMode === 0) {this.iSecureCenterConfig = {...this.iSecureCenterConfig,previewCode: data.code,}} else {this.$refs.iSecureCenterRef.oWebStartPlayback(data.code)}},//实时,历史视频切换,videoChange(data) {if (data == 'shishi') {this.info = '实时视频'this.iSecureCenterConfig = {...this.iSecureCenterConfig,playMode: 0,layout: "3x3"}} else {this.info = '历史视频'this.iSecureCenterConfig = {...this.iSecureCenterConfig,playMode: 1, //1是回放layout: "1x1"}}},