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

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定