45 对接海康视频九宫格的实现
前言
这里主要是 来看一下 海康视频 的一个九宫格播放的需求
然后 在实际使用的过程中产生了一些问题, 比如 增加一个视频, 应该只增量请求这一个视频的服务, 而一些实现下是全量请求了 整个视频列表的服务
另外 就是全屏播放, 如果是 自己写样式来实现 全屏播放, 可能需要 重新创建 海康的player, 进而 需要重新请求 海康的视频服务
另外 还有 cpu, 内存占用过高的情况, 然后 还有一些疑似 内存泄露的情况
这里 调整一个版本 记录一下
以下有一些版本, 一个是自定义实现九宫格, 这样做的问题 还是挺多的, 以上的问题基本上都占了, 然后另外一个版本是 直接使用 海康自己提供的 api 来实现 九宫格, 会稍微好一些
整体来说, 一个比较良好的情况是, 否则的话 可能会出现一些 较高的资源占用的问题
- 新增一个视频的时候, 仅仅增量请求这一个视频的数据, 增量的和海康建立连接
- 全屏的时候 使用海康的 api, 它自己已经实现了 自适应, 否则 自己处理的话 自适应有可能需要重新和海康建立连接, 重新渲染
- 尽量避免 并发 和请求海康的接口, 经常会崩溃, 尽量避免 频繁的和海康断开视频连接, 重新创建视频连接
自己自定义九宫格
这个就相当于是 海康的视频播放器只播放一个视频
然后 这里是 循环 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 对接海康视频九宫格的实现
前言 这里主要是 来看一下 海康视频 的一个九宫格播放的需求 然后 在实际使用的过程中产生了一些问题, 比如 增加一个视频, 应该只增量请求这一个视频的服务, 而一些实现下是全量请求了 整个视频列表的服务 另外 就是全屏播放, 如果是 自己写样式来实现 全屏播放, 可能需要 …...
二-容量管理之容量水位
容量水位概念 容量水位(Capacity Level)是指一个系统或服务所使用资源的程度、范围和可承受能力,通常以百分比表示。在容量管理中,容量水位是非常重要的指标,用于衡量系统或服务的健康状况、资源利用率以及未来容量需求。 容量水位通常是根据一些关键指标进行计算,例如…...
计算机网络——数据链路层(差错控制)
计算机网络——数据链路层(差错控制) 差错从何而来数据链路层的差错控制检错编码奇偶校验码循环冗余校验(CRC)FCS 纠错编码海明码海明距离纠错流程确定校验码的位数r确定校验码和数据位置 求出校验码的值检错并纠错 我们今年天来继…...
【搜索引擎1】Ubuntu通过deb方式安装ElasticSearch和Kibana、ik中文分词插件
1、官网下载文件 版本为官网最新版本,ElasticSearch与Kibana版本必须保持一致 ElasticSearch下载地址:Download Elasticsearch | Elastic Kibana下载地址:Past Releases of Elastic Stack Software | Elastic 下载选择DEB文件 ik插件下载…...
1.0 html(1)
html 一、基本介绍 1、定义:html是一种超文本标记语言,也是一种标识性语言(不是编程语言) 标记:记号(绰号) 超文本:就是页面内容可以包含图片、链接,音乐,…...
基于SpringBoot和Leaflet的行政区划地图掩膜效果实战
目录 前言 一、掩膜小知识 1、GIS掩膜的实现原理 2、图层掩膜流程 二、使用插件 1、leaflet-mask介绍 2、核心代码解释 三、完整实例实现 1、后台逻辑实现 2、省级行政区划查询实现 3、行政区划定位及掩膜实现 4、成果展示 总结 前言 在之前的博客提过按空间矢量…...
【机器学习之---数学】马尔科夫链
every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 马尔科夫 1. 概念 1.1 引言 马尔可夫链在许多领域都有应用,包括物理学、生物学、工程学、经济学和计算机科学等。在计算机科学中࿰…...
教程3_图像的轮廓
目录 目标 1. 特征矩 2、轮廓质心 3. 轮廓面积 4. 轮廓周长 5. 轮廓近似 6. 轮廓凸包 7. 边界矩形 7.1.直角矩形 7.2. 旋转矩形 8. 最小闭合圈 9. 拟合一个椭圆 10. 拟合直线 目标 在本文中,我们将学习 - 如何找到轮廓的不同特征,例如面积&…...
【Linux】-Linux下的编辑器Vim的模式命令大全及其自主配置方法
目录 1.简单了解vim 2.vim的模式 2.1命令模式 2.2插入模式 2.3底行模式 3.vim各模式下的命令集 3.1正常(命令模式下) 3.1.1光标定位命令 3.1.2 复制粘贴 3.1.3 删除 3.1.4 撤销 3.1.5大小写转换 3.1.6替换 「R」:替换光标所到之处的字符&…...
基于SpringBoot和Vue的车辆管理系统的设计与实现
今天要和大家聊的是一款基于SpringBoot和Vue的车辆管理系统的设计与实现 !!! 有需要的小伙伴可以通过文章末尾名片咨询我哦!!! 💕💕作者:李同学 💕…...
R折线图(自备)
目录 折线图基础 创建散点和折线图 复杂折现加图例 折线图柱状图 数据处理 进行差异检验 基础绘图折线 基础绘图箱线 进行合并 双轴柱状与折线图 数据 折线图基础 创建散点和折线图 rm(list ls()) opar <-par(no.readonlyTRUE)##自带orange数据集 par(mfrowc…...
web学习笔记(四十五)Node.js
目录 1. Node.js 1.1 什么是Node.js 1.2 为什么要学node.js 1.3 node.js的使用场景 1.4 Node.js 环境的安装 1.5 如何查看自己安装的node.js的版本 1.6 常用终端命令 2. fs 文件系统模块 2.1引入fs核心模块 2.2 读取指定文件的内容 2.3 向文件写入指定内容 2.4 创…...
基于Gabor滤波器的指纹图像识别,Matlab实现
博主简介: 专注、专一于Matlab图像处理学习、交流,matlab图像代码代做/项目合作可以联系(QQ:3249726188) 个人主页:Matlab_ImagePro-CSDN博客 原则:代码均由本人编写完成,非中介,提供…...
55、Qt/事件机制相关学习20240326
一、代码实现设置闹钟,到时间后语音提醒用户。示意图如下: 代码: #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), speecher(new QTextToSpeech(t…...
Clip Converter - 视频在线下载方法
Clip Converter - 视频在线下载方法 1. Video URL to Download2. Continue3. StartReferences YT to MP4 & MP3 Converter! https://www.clipconverter.cc/ Clip Converter is a free online media conversion application, which allows you to reocord, convert and do…...
【No.19】蓝桥杯简单数论上|模运算|快速幂|GCD|LCM|刷题统计|RSA解密|核桃的数量(C++)
简单数论 模运算 定义:模运算为 a 除以 m 的余数,记为 a mod m,有 a mod m a % m模运算是大数运算中的常用操作。如果一个数太大,无法直接输出,或者不需要直接输出,可以把它取模后,缩小数值再…...
区块链安全之DDoS防护的重要性及其实施策略
随着区块链技术的不断发展和广泛应用,其安全问题也日益凸显。其中,分布式拒绝服务(DDoS)攻击是对区块链网络稳定性和效率构成潜在威胁的重要因素之一。本文旨在深入探讨区块链为何需要采取DDoS高防措施,并提出相应的防护策略。 一、区块链面…...
使用Spark单机版环境
在Spark单机版环境中,可通过多种方式进行实战操作。首先,可使用特定算法或数学软件计算圆周率π,并通过SparkPi工具验证结果。其次,在交互式Scala版或Python版Spark Shell中,可以进行简单的计算、打印九九表等操作&…...
【分布式】——降级熔断限流
降级&熔断&限流 ⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记仓库👉https://github.com/A-BigTree/tree-learning-notes 个人主页👉https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点…...
代码随想录刷题笔记 Day 58 | 判断子序列 No.392 | 不同的子序列 No.115
文章目录 Day 5801. 判断子序列(No. 392)<1> 题目<2> 题解<3> 代码 02. 不同的子序列(No. 115)<1> 题目<2> 题解<3> 代码 Day 58 01. 判断子序列(No. 392) 题目链接…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
