45 对接海康视频九宫格的实现

2024-03-27 09:44

本文主要是介绍45 对接海康视频九宫格的实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

这里主要是 来看一下 海康视频 的一个九宫格播放的需求

然后 在实际使用的过程中产生了一些问题, 比如 增加一个视频, 应该只增量请求这一个视频的服务, 而一些实现下是全量请求了 整个视频列表的服务

另外 就是全屏播放, 如果是 自己写样式来实现 全屏播放, 可能需要 重新创建 海康的player, 进而 需要重新请求 海康的视频服务

另外 还有 cpu, 内存占用过高的情况, 然后 还有一些疑似 内存泄露的情况

这里 调整一个版本 记录一下

以下有一些版本, 一个是自定义实现九宫格, 这样做的问题 还是挺多的, 以上的问题基本上都占了, 然后另外一个版本是 直接使用 海康自己提供的 api 来实现 九宫格, 会稍微好一些

 

 

整体来说, 一个比较良好的情况是, 否则的话 可能会出现一些 较高的资源占用的问题

  1. 新增一个视频的时候, 仅仅增量请求这一个视频的数据, 增量的和海康建立连接
  2. 全屏的时候 使用海康的 api, 它自己已经实现了 自适应, 否则 自己处理的话 自适应有可能需要重新和海康建立连接, 重新渲染
  3. 尽量避免 并发 和请求海康的接口, 经常会崩溃, 尽量避免 频繁的和海康断开视频连接, 重新创建视频连接

 

 

自己自定义九宫格

这个就相当于是 海康的视频播放器只播放一个视频

然后 这里是 循环 codeUrlList, 一个视频对应于一个 player, 虽然同时 播放了多个 player 但是 实际上核心占用资源的貌似是其中一个

key 需要指定, 否则 在一些需要重新渲染 海康player 的场景下面, 模型改变了 但是每一个 div 内部的 player 的 dom 不会重新渲染, 可能会导致 视频错位等问题

这个 问题就是需要自己实现全屏的样式, 以及全拼的时候需要全部重新渲染一次, 才能适应全屏之后的窗口

其他的 增量的获取海康服务, 避免并发的请求海康接口 就需要自己处理了

以下的测试代码 看 (!singlePlayer) 部分

 

业务组件如下

<template><div class="indexDiv"><div v-if="!singlePlayer" v-for="item in codeUrlList" :key="item.code" style="width:400px; display: inline; float:left;"><Player :palyer-code="item.code" :play-url="item.url"></Player></div><PlayerSplitByHk ref="playerHk" v-if="singlePlayer"></PlayerSplitByHk><button @click="handleFullScreen" >全屏</button></div>
</template><script>import Player from "./Player.vue"
import PlayerSplitByHk from "./PlayerSplitByHk.vue"export default {name: "Index",components: {Player,PlayerSplitByHk,},data() {return {singlePlayer: false,codeUrlList: [{"code":"61092100561310001001","url":"ws://112.110.110.109/openUrl/KG6aIkE"},{"code":"61102600581328004001","url":"ws://112.110.110.109:559/openUrl/KHubaKc"},{"code":"61092200561310001001","url":"ws://112.110.110.109:559/openUrl/KIs4xbO"},{"code":"61092200561310001002","url":"ws://112.110.110.109:559/openUrl/KJcCKwo"},{"code":"61092200561310002701","url":"ws://112.110.110.109/openUrl/KK6g812"},{"code":"61092200561310001901","url":"ws://112.110.110.109:559/openUrl/KL11U1W"},{"code":"61092800561310002101","url":"ws://112.110.110.109:559/openUrl/KLJjkk0"},{"code":"61092800561310002402","url":"ws://112.110.110.109:559/openUrl/KMu98ME"},{"code":"61092800561310002901","url":"ws://112.110.110.109/openUrl/KNaIYik"}]};},mounted() {// test for hk sudokuif(this.singlePlayer) {this.$refs.playerHk.updateCodeUrlList(this.codeUrlList)// call updateCodeUrlList if codeUrlList updatedlet _this = thissetTimeout(function() {let updatedCodeUrlList = []_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))updatedCodeUrlList.splice(5, 3)_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)console.log(" splice with idx 6, 7, 8 ")console.log(" ----------------------------- ")}, 5000)setTimeout(function() {let updatedCodeUrlList = []_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))updatedCodeUrlList.splice(5, 3)updatedCodeUrlList.push({code: "code1", url: "url1"})updatedCodeUrlList.push({code: "code2", url: "url2"})_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)console.log(" push url1, url2 ")console.log(" ----------------------------- ")}, 10000)}},methods: {handleFullScreen() {// test for hk sudokuif(this.singlePlayer) {this.$refs.playerHk.handleFullScreen()}}}
}</script><style scoped></style>

 

视频播放组件如下

<template><div clas="outerDiv" ><div class="main" :id="'playerDiv' + this.palyerCode"  ></div></div>
</template><script>export default {name: "Player",props: {palyerCode: {type: String,default: "",},playUrl: {type: String,default: "",},},data() {return {player: null};},mounted() {this.createPlayer()this.startPlay()},methods: {createPlayer() {this.player = new window.JSPlugin({szId: 'playerDiv' + this.palyerCode,szBasePath: "./",iMaxSplit: 4,iCurrentSplit: 1,openDebug: true,oStyle: {borderSelect: '#000',}})// 事件回调绑定let _this = thisthis.player.JS_SetWindowControlCallback({windowEventSelect: function (iWndIndex) {  //插件选中窗口回调console.log('windowSelect callback: ', iWndIndex);_this.player.JS_Stop(iWndIndex).then(() => { console.log('stop play ' + iWndIndex + ' success') },e => { console.error(e) })},pluginErrorHandler: function (iWndIndex, iErrorpalyerCode, oError) {  //插件错误回调console.log('pluginError callback: ', iWndIndex, iErrorpalyerCode, oError);},windowFullCcreenChange: function (bFull) {  //全屏切换回调console.log('fullScreen callback: ', bFull);},firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {  //首帧显示回调console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);},performanceLack: function () {  //性能不足回调console.log('performanceLack callback: ');}});},startPlay() {let playURL = this.playUrllet model = 1console.log(" start replay with url : " + playURL)// this.player.JS_Play(playURL, { playURL, model }, 0).then(//     () => { console.log('realplay success') },//     e => { console.error(e) }// )}}
}</script><style scoped></style>

 

 

使用 hik 提供的 api 实现九宫格

这里的九宫格的实现就是直接基于 hk 的 api 了, 比如这里的 this.player.JS_ArrangeWindow, this.player.JS_Play 

然后 全屏基于 this.player.JS_FullScreenDisplay, 然后 全拼的状态可以通过 windowFullCcreenChange 进行获取

一些 常见的回调函数, 也在 demo 中有体现

然后 降低客户端和海康服务器这边的开销的处理, 主要是如下的 更新前后的视频列表, 如果目标索引的视频变了, 才重新发起请求, 重新建立视频连接

 

这样的话 开始的时候点击九个视频, 资源占用大概是 cpu100%, 内存差不多是 500M 左右, 然后 随着时间的推移, 主项目的js引擎[不是海康player的js引擎] 占用内存逐渐升高, 这个具体就得看这个 player 的问题了, 然后刷新 Index.vue 的页面, 这个内存占用 依然存在

这里 就不深究了

 

业务组件如下

<template><div class="indexDiv"><div v-if="!singlePlayer" v-for="item in codeUrlList" :key="item.code" style="width:400px; display: inline; float:left;"><Player :palyer-code="item.code" :play-url="item.url"></Player></div><PlayerSplitByHk ref="playerHk" v-if="singlePlayer"></PlayerSplitByHk><button @click="handleFullScreen" >全屏</button></div>
</template><script>import Player from "./Player.vue"
import PlayerSplitByHk from "./PlayerSplitByHk.vue"export default {name: "Index",components: {Player,PlayerSplitByHk,},data() {return {singlePlayer: false,codeUrlList: [{"code":"61092100561310001001","url":"ws://112.110.110.109/openUrl/KG6aIkE"},{"code":"61102600581328004001","url":"ws://112.110.110.109:559/openUrl/KHubaKc"},{"code":"61092200561310001001","url":"ws://112.110.110.109:559/openUrl/KIs4xbO"},{"code":"61092200561310001002","url":"ws://112.110.110.109:559/openUrl/KJcCKwo"},{"code":"61092200561310002701","url":"ws://112.110.110.109/openUrl/KK6g812"},{"code":"61092200561310001901","url":"ws://112.110.110.109:559/openUrl/KL11U1W"},{"code":"61092800561310002101","url":"ws://112.110.110.109:559/openUrl/KLJjkk0"},{"code":"61092800561310002402","url":"ws://112.110.110.109:559/openUrl/KMu98ME"},{"code":"61092800561310002901","url":"ws://112.110.110.109/openUrl/KNaIYik"}]};},mounted() {// test for hk sudokuif(this.singlePlayer) {this.$refs.playerHk.updateCodeUrlList(this.codeUrlList)// call updateCodeUrlList if codeUrlList updatedlet _this = thissetTimeout(function() {let updatedCodeUrlList = []_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))updatedCodeUrlList.splice(5, 3)_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)console.log(" splice with idx 6, 7, 8 ")console.log(" ----------------------------- ")}, 5000)setTimeout(function() {let updatedCodeUrlList = []_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))updatedCodeUrlList.splice(5, 3)updatedCodeUrlList.push({code: "code1", url: "url1"})updatedCodeUrlList.push({code: "code2", url: "url2"})_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)console.log(" push url1, url2 ")console.log(" ----------------------------- ")}, 10000)}},methods: {handleFullScreen() {// test for hk sudokuif(this.singlePlayer) {this.$refs.playerHk.handleFullScreen()}}}
}</script><style scoped></style>

 

视频播放组件如下

<template><div class="outerDiv" ><div class="main" id="playerDiv" ></div></div>
</template><script>export default {name: "PlayerSplitByHk",props: {},data() {return {player: null,videoListMax: 0,isFirstClick: false,codeUrlList: null,};},mounted() {this.createPlayer()},methods: {updateCodeUrlList(newCodeUrlList) {let oldCodeUrlList = this.codeUrlListthis.codeUrlList = newCodeUrlListthis.videoListMax = Math.max(this.videoListMax, newCodeUrlList.length)let matrixLen = newCodeUrlList.length > 4 ? 3 : (newCodeUrlList.length > 1 ? 2 : 1)this.isFirstClick = truethis.player.JS_ArrangeWindow(matrixLen)for(let i=newCodeUrlList.length; i<this.videoListMax; i++) {console.log(" stop replay with idx : " + i)this.player.JS_Stop(i);}for(let i=0; i<newCodeUrlList.length; i++) {let newItem = newCodeUrlList[i]let oldItem = oldCodeUrlList && oldCodeUrlList[i]if((!oldItem) || (oldItem.code !== newItem.code)) {this.startPlay(i)}}},handleFullScreen() {this.player.JS_FullScreenDisplay(true).then(() => { console.log(`wholeFullScreen success`) },e => { console.error(e) })},createPlayer() {this.player = new window.JSPlugin({szId: 'playerDiv',szBasePath: "/static",iMaxSplit: 9,iCurrentSplit: 1,iWidth: 400,iHeight: 300,openDebug: true,oStyle: {// border: '#green',// borderSelect: '#ffcc00',}})// 事件回调绑定let _this = thisthis.player.JS_SetWindowControlCallback({windowEventSelect: function (iWndIndex) {  //插件选中窗口回调if(_this.isFirstClick) {_this.isFirstClick = falsereturn ;}console.log(" do what you want ")},pluginErrorHandler: function (iWndIndex, iErrorpalyerCode, oError) {console.log('pluginError callback: ', iWndIndex, iErrorpalyerCode, oError);},windowFullCcreenChange: function (bFull) {console.log('fullScreen callback: ', bFull);},firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);},performanceLack: function () {console.log('performanceLack callback: ');}});},startPlay(idx) {let playURL = this.codeUrlList[idx].urllet model = 1console.log(" start replay with idx : " + idx)// this.player.JS_Play(playURL, { playURL, model }, idx).then(//     () => { console.log('realplay success') },//     e => { console.error(e) }// )}}
}</script><style scoped></style>

 

 

完 

 

 

 

这篇关于45 对接海康视频九宫格的实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/851681

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、