Vue3 中集成海康 H5 监控视频播放功能

🌈个人主页:前端青山
🔥系列专栏:Vue篇
🔖人终将被年少不可得之物困其一生
依旧青山,本期给大家带来Vuet篇专栏内容:Vue-集成海康 H5 监控视频播放功能
目录
一、引言
二、环境搭建
三、代码解析
子组件部分
1. 导入模块和组件
2. 定义组件属性和事件
3. 初始化变量
4. 初始化视频插件
5. 控制分屏数量
6. 视频线路弹框按钮
7. 生命周期钩子
8. 初始化视频播放
9. 处理事件
10.调用插件播放
父组件调用
一、引言
随着视频监控技术的发展,许多应用场景需要集成实时视频监控功能。本文将详细介绍如何在 Vue 3 应用中集成海康 H5 监控视频播放功能,实现视频的实时播放、分屏显示以及全屏切换等功能。


二、环境搭建
为了确保代码能够正常运行,我们需要准备以下开发环境:
-
Vue 3:用于构建前端应用。
-
Element Plus:用于 UI 组件库。
-
海康 H5 SDK:用于播放视频流。
三、代码解析
子组件部分
<template><div class="play_windows" v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.8)"><div class="tree-form"><el-treeref="tree":data="dataTree":props="defaultProps":highlight-current="true"@node-click="pitchOns"><template #default="{ node, data }"><span class="custom-tree-node">{{ data.name }}</span></template></el-tree></div><div class="video"><div class="dialog-slot-video-header-right"><el-button class="myButton" :class="{ 'active': videoIndex == 4 }" @click="videoTabClick(4)">1×1</el-button><el-button class="myButton" :class="{ 'active': videoIndex == 1 }" @click="videoTabClick(1)">3×3</el-button><el-button class="myButton" :class="{ 'active': videoIndex == 2 }" @click="videoTabClick(2)">4×4</el-button><el-button class="myButton" :class="{ 'active': videoIndex == 3 }" @click="videoTabClick(3)">整体全屏</el-button></div><div id='corpvideo'></div></div></div>
</template>
-
功能说明
-
play_windows容器:包含两个主要部分,左侧为树形结构,右侧为视频播放区域。 -
el-tree组件:展示监控设备树形结构,点击节点触发pitchOns方法。 -
视频播放区域:通过按钮控制不同的分屏模式(1×1、3×3、4×4)及全屏模式。
-
id='corpvideo':指定视频播放容器的 ID,供 H5 SDK 使用。
-
1. 导入模块和组件
import { ref, onMounted, nextTick, defineProps, defineExpose, defineEmits, watch, onBeforeUnmount } from 'vue';
import { ElMessage } from 'element-plus';
import { videoallList } from '@/api/screenVideo/index';
import { getGetByCode } from '@/api/videoSurveillance/index';
-
功能说明:导入了 Vue 的一些核心函数,如
ref、onMounted、nextTick等,以及 Element Plus 的消息提示组件ElMessage和相关 API。
2. 定义组件属性和事件
const emit = defineEmits(["handleSpjkPOIClick"]);
const props = defineProps({playURL: String, // 视频 URLsplitNum: Number, // 分屏播放,默认最大分屏 4*4dataTree: Object, // 树形数据defaultProps: Object
});
-
功能说明:定义了组件的属性
props和自定义事件emit,用于接收父组件传递的数据和触发事件。
3. 初始化变量
let dataTree = ref<any>(props.dataTree);
let defaultProps = ref<any>(props.defaultProps);
let loading = ref<Boolean>(false);
let myPlugin = ref<any>(null);
let index = ref<any>(1); // 多屏播放显示第几个
let mode = ref<any>(1); // 0 为低级播放,1 为高级播放
const urlList = ref<any>([]);
let playURLs = ref<any>("");
const jsPlugin = (window as any).JSPlugin;
-
功能说明:定义了一些响应式变量,用于存储数据和状态,如
loading用于控制加载状态,myPlugin用于存储视频插件实例。
4. 初始化视频插件
const myPlugins = () => {myPlugin.value = new jsPlugin({szId: 'corpvideo', // 需要英文字母开头,唯一性,必填szBasePath: '/h5player', // 必填,与 h5player.min.js 的引用目录一致bSupporDoubleClickFull: true, // 是否支持双击全屏,默认 trueiMaxSplit: 4, // 分屏播放,默认最大分屏 4*4iCurrentSplit: splitNum.value,oStyle: {borderSelect: '#FFCC00',},openDebug: true,});
};
-
功能说明:定义了一个方法
myPlugins,用于初始化视频插件实例,并配置相关参数。
5. 控制分屏数量
const tabPosition = ref<any>(1);
const playBackNum = (num: any) => {if (num == "3") {myPlugin.value.JS_FullScreenDisplay(true).then(() => { console.log(`wholeFullScreen success`) },(e: any) => { console.error(e) });return;}if (num == splitNum.value) {return;}splitNum.value = num;
};
-
功能说明:定义了一个方法
playBackNum,用于控制分屏数量,并支持全屏显示。
6. 视频线路弹框按钮
const splitNum = ref<any>(1);
const videoIndex = ref<number>(4); // 视频信息弹框默认值 index
const videoTabClick = (type: number) => {videoIndex.value = Number(type);if (type == 1) {splitNum.value = 3;const totalWindows = splitNum.value * splitNum.value;for (let i = 0; i < totalWindows; i++) {const url = urlList.value[i] || urlList.value[0];myPlugin.value.JS_Play(url, { playURL: url, mode: mode.value }, i).then(() => console.log(`Playing in window ${i}`),(e: any) => console.error('Error playing video', e));}} else if (type == 2) {splitNum.value = 4;const totalWindows = splitNum.value * splitNum.value;for (let i = 0; i < totalWindows; i++) {const url = urlList.value[i] || urlList.value[0];myPlugin.value.JS_Play(url, { playURL: url, mode: mode.value }, i).then(() => console.log(`Playing in window ${i}`),(e: any) => console.error('Error playing video', e));}} else if (type == 3) {myPlugin.value.JS_FullScreenDisplay(true).then(() => { console.log(`wholeFullScreen success`) },(e: any) => { console.error(e) });return;} else if (type == 4) {splitNum.value = 1;}myPlugin.value.JS_ArrangeWindow(splitNum.value).then(() => { console.log(`arrangeWindow to ${splitNum.value}x${splitNum.value} success`) },(e: any) => { console.error(e) });console.log(splitNum.value, '监控视频的值');
};
-
功能说明:定义了一个方法
videoTabClick,用于控制视频线路弹框按钮,并根据不同的类型调整分屏数量和播放视频。
7. 生命周期钩子
onMounted(() => {nextTick(() => {myPlugins();// 事件回调绑定myPlugin.value.JS_SetWindowControlCallback({windowEventSelect: function (iWndIndex: any) { // 插件选中窗口回调console.log('windowSelect callback: ', iWndIndex);},pluginErrorHandler: function (iWndIndex: any, iErrorCode: any, oError: any) { // 插件错误回调console.log('pluginError callback: ', iWndIndex, iErrorCode, oError);},windowEventOver: function (iWndIndex: any) { // 鼠标移过回调// console.log(iWndIndex);},windowEventOut: function (iWndIndex: any) { // 鼠标移出回调// console.log(iWndIndex);},windowEventUp: function (iWndIndex: any) { // 鼠标mouseup事件回调// console.log(iWndIndex);},windowFullCreenChange: function (bFull: any) { // 全屏切换回调console.log('fullScreen callback: ', bFull);},firstFrameDisplay: function (iWndIndex: any, iWidth: any, iHeight: any) { // 首帧显示回调console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);},performanceLack: function () { // 性能不足回调console.log('performanceLack callback: ');}});});
});
onBeforeUnmount(() => {console.log('切换了');
});
-
功能说明:在组件挂载时初始化视频插件,并绑定事件回调。在组件卸载前执行清理操作。
8. 初始化视频播放
const initialize = (playURL: any, urls?: any[]) => {urlList.value = urls;playURLs.value = playURL;loading.value = true;index.value = myPlugin.value.currentWindowIndex;myPlugin.value.JS_Play(playURL, { playURL, mode: mode.value }, index.value).then(() => { loading.value = false }, // 成功操作(e: any) => { loading.value = false;ElMessage.error('监控视频异常'); // 失败操作});
};
-
功能说明:定义了一个方法
initialize,用于初始化视频播放,并处理加载状态和错误提示。
9. 处理事件
const pitchOns = (e: any) => {if (!e || !e.self) {if (e.equipmentCoding) {handleAddChild(e);}return;}if (e.children) {emit("handleSpjkPOIClick", e.self.indexCode, '');return;} else {handleAddChild(e);}
};const handleAddChild = (e: any) => {if (!e || !e.self) {if (e.equipmentCoding) {videoUrl(e.equipmentCoding);}return;}if (e.self.indexCode) {let params = {UnitIndexCode: e.self.indexCode,};videoallList(params).then((res: any) => {if (res.data.rows.length == 0) {emit("handleSpjkPOIClick", e.self.indexCode, '');} else {e.children = e.children || [];// 修改 res.data.rows 中所有数据对象的字段 equipmentName 变成 nameres.data.rows = res.data.rows.map((child: any) => ({...child,name: child.equipmentName, // 将 equipmentName 字段复制到 name 字段// 删除原 equipmentName 字段}));res.data.rows.forEach((child: any) => {e.children.push(child);});// 展开当前节点(e as any).expanded = true;}})}
}
10.调用插件播放
const videoUrl =(e:any)=>{let params = {equipmentCoding: e,};getGetByCode(params).then(res => {setTimeout(() => {initialize(res.data.url);}, 1);});
}// 使用 watch 监听 splitNum 的变化watch(splitNum, (newValue, oldValue) => {if (newValue !== oldValue) {myPlugins();myPlugin.value.JS_ArrangeWindow(splitNum.value).then(() => { console.log(`arrangeWindow to ${splitNum.value}x${splitNum.value} success`) },(e: any) => { console.error(e) })}
});
//最后暴露方法defineExpose({initialize,myPlugins})
父组件调用
<template><div><ScreenMonitoring ref="screenmonitoring" :dataTree="dataTree" :defaultProps="defaultProps" @handleSpjkPOIClick="handleSpjkPOIClick" /></div>
</template><script setup>
import { ref, onMounted, nextTick } from 'vue';const dataTree = ref<any>([]);
const dataTree1 = ref<any>([]);
let screenmonitoring = ref();
const defaultProps = {children: 'children',label: 'name',
};onMounted(() => {nextTick(() => {let params = {};getTreeJson(params).then((res: any) => {let list = res.rows[0].children[9].children;list.forEach((item: any) => {extractNameAndRebuildTree(item); // 对每个根节点执行递归提取});dataTree.value = list; // 将处理后的列表赋值给 dataTree});});
});const extractNameAndRebuildTree = (node: any) => {// 如果节点有 self,提取 name 并放在最外层if (node.self && node.self.name) {node.name = node.self.name;}// 如果节点有 children,递归处理每个子节点if (node.children && node.children.length > 0) {node.children.forEach((child: any) => {extractNameAndRebuildTree(child);});}
};
const handleSpjkPOIClick = (poiId: string, coord: string) => {let params = {UnitIndexCode: poiId,};getGetByCodes(params).then((res: any) => {setTimeout(() => {screenmonitoring.value.initialize(res.data.urls[0], res.data.urls);}, 1);});
};
</script>
-
初始化数据树:
-
dataTree和dataTree1是两个响应式数组,用于存储处理后的数据。 -
screenmonitoring是一个引用,用于指向ScreenMonitoring子组件的实例。 -
defaultProps是传递给子组件的默认属性配置。
-
-
组件挂载时:
-
nextTick():等待 DOM 更新完成后再执行后续操作。 -
getTreeJson(params):从服务器获取数据,并处理返回的数据。 -
extractNameAndRebuildTree(item):递归处理每个节点,提取name并放在最外层。
-
-
处理点击事件:
-
handleSpjkPOIClick(poiId, coord):当点击某个 时,获取对应的视频 URL 并初始化视频播放。 -
getGetByCodes(params):从服务器获取视频 URL 数据。 -
setTimeout(() => { ... }, 1):延迟 1 毫秒后初始化视频播放。
-
通过这种方式,父组件能够有效地初始化数据树,并在点击 树状 时触发视频播放。
本文旨在详细介绍如何在 Vue 3 应用中集成海康 H5 监控视频播放功能,实现视频的实时播放、分屏显示以及全屏切换等功能。
相关文章:
Vue3 中集成海康 H5 监控视频播放功能
🌈个人主页:前端青山 🔥系列专栏:Vue篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Vuet篇专栏内容:Vue-集成海康 H5 监控视频播放功能 目录 一、引言 二、环境搭建 三、代码解析 子组件部分 1.…...
Linux: eBPF: libbpf-bootstrap-master 编译
文章目录 简介编译运行展示输出展示:简介 这个是使用libbpf的一个例子; 编译 如果是一个可以联网的机器,这个libbpf-bootstrap的编译就方便了,完全是自动化的下载依赖文件;如果没有,就只能自己准备这些个软件。 需要:libbpf-static; [root@RH8-LCP c]# makeLIB …...
1.1.4 计算机网络的分类
按分布范围分类: 广域网(wan) 城域网(man) 局域网(lan) 个域网(pan) 注意:如今局域网几乎采用“以太网技术实现”,因此“以太网”几乎成了“局域…...
周家庄智慧旅游小程序
项目概述 周家庄智慧旅游小程序将通过数字化手段提升游客的旅游体验,依托周家庄的自然与文化资源,打造智慧旅游新模式。该小程序将结合虚拟现实(VR)、增强现实(AR)和人工智能等技术,提供丰富的…...
【在Linux世界中追寻伟大的One Piece】命名管道
目录 1 -> 命名管道 1.1 -> 创建一个命名管道 1.2 -> 匿名管道与命名管道的区别 1.3 -> 命名管道的打开规则 1.4 -> 例子 1 -> 命名管道 管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。如果我们想在不相关的进程之间交换数据&…...
如意控物联网项目-ML307R模组软件及硬件调试环境搭建
软件及硬件调试环境搭建 1、 软件环境搭建及编译 a) 打开官方SDK,内涵APP-DEMO,通过vscode打开程序, 软件程序编写及编译参考下边说明文档链接 OneMO线上服务平台 编译需预安装python3.7以上版本,安装完python后,打开…...
大模型分布式训练并行技术(九)-总结
近年来,随着Transformer、MOE架构的提出,使得深度学习模型轻松突破上万亿规模参数,传统的单机单卡模式已经无法满足超大模型进行训练的要求。因此,我们需要基于单机多卡、甚至是多机多卡进行分布式大模型的训练。 而利用AI集群&a…...
uniapp view设置当前view之外的点击事件
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...
【Mybatis篇】动态SQL的详细带练
🧸安清h:个人主页 🎥个人专栏:【计算机网络】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 文章目录 🎯一.动态SQL简单介绍 🚦动态S…...
【MyBatis-Plus】 学习记录 常用功能及代码生成器使用
文章目录 1. 环境准备2. 创建基础实体类3. 编写 Mapper 接口4. Service 层5. 控制器层6. 分页功能7. 条件构造器8. 配置乐观锁9. 常见问题10. 代码生成器1. 创建数据库表2. 引入依赖3. 配置数据库连接4. 编写代码生成器5. 运行代码生成器6. 查看生成的代码 MyBatis-Plus 是一个…...
HalconDotNet实现OCR详解
文章目录 一、基于字符分割的 OCR二、基于模板匹配的 OCR三、基于深度学习的 OCR四、基于特征提取的 OCR五、基于区域建议的 OCR 一、基于字符分割的 OCR 字符分割是 OCR 中的一个重要步骤。首先,对包含文本的图像进行预处理,如去噪、二值化等操作&#…...
手搓一个Agent#Datawhale 组队学习Task3
书接上回,首先回顾一下Task2的一些补充: Task2主要任务是从零预训练一个tiny-llama模型,熟悉一下Llama的模型架构和流程。然后测试一下模型的效果。总的来说,因为某些未知的原因,loss一直没有降下去,导致最…...
基于SpringBoot+Vue+MySQL的在线酷听音乐系统
系统展示 用户前台界面 管理员后台界面 系统背景 随着互联网技术的飞速发展,网络已成为人们日常生活中不可或缺的一部分。在线音乐服务因其便捷性和丰富性,逐渐成为用户获取音乐内容的主要渠道。然而,传统的音乐播放平台往往存在歌曲资源有限…...
大数据实时数仓Hologres(一):Hologres 简单介绍
文章目录 Hologres 简单介绍 一、什么是实时数仓 Hologres 二、产品优势 1、专注实时场景 2、亚秒级交互式分析 3、统一数据服务出口 4、开放生态 5、MaxCompute查询加速 6、计算存储分离架构 三、应用场景 搭建实时数仓 四、产品架构 1、Shared Disk/Storage &am…...
【鸿蒙HarmonyOS NEXT】数据存储之分布式键值数据库
【鸿蒙HarmonyOS NEXT】数据存储之分布式键值数据库 一、环境说明二、分布式键值数据库介绍三、示例代码加以说明四、小结 一、环境说明 DevEco Studio 版本: API版本:以12为主 二、分布式键值数据库介绍 KVStore简介: 分布式键值数据库…...
基于springboot+小程序的儿童预防接种预约管理系统(疫苗1)(源码+sql脚本+视频导入教程+文档)
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 本儿童预防接种预约微信小程序可以实现管理员和用户。 1、管理员功能有个人中心,用户管理,儿童信息管理,疫苗信息管理,儿童接种管理&#x…...
计算物理精解【8】-计算原理精解【5】
文章目录 logistic模型多元回归分析多元回归分析概览1. 多元回归的概念与重要性2. 多元回归在实际应用中的例子3. 多元回归在预测和解释数据中的优势和局限性4. 多元回归的优缺点及改进建议 多元线性回归分析详解一、原理二、性质三、计算四、例子与例题五、应用场景六、优缺点…...
【Linux】 tcp | 解除服务器对tcp连接的限制 | 物联网项目配置
一、修改tcp连接限制 1、编辑 vi /etc/sysctl.conf 2、内容 net.ipv4.tcp_keepalive_intvl 75 net.ipv4.tcp_keepalive_probes 9 net.ipv4.tcp_keepalive_time 7200 net.ipv4.ip_local_port_range 1024 65535 net.ipv4.ip_conntrack_max 20000 net.ipv4.tcp_max_tw_bucket…...
如何隐藏Windows10「安全删除硬件」里的USB无线网卡
本方法参照了原文《如何隐藏Windows10「安全删除硬件」里的USB无线网卡》里面的方法,但是文章中的描述我的实际情况不太一样,于是我针对自己的实际情况进行了调整,经过测试可以成功隐藏Windows10「安全删除硬件」里的USB无线网卡。 先说一下…...
【QT Quick】基础语法:导入外部JS文件及调试
在 QML 中,可以使用 JavaScript 来实现业务逻辑的灵活性和简化开发。接下来我们会学习如何导入 JavaScript 文件,并在 QML 中使用它,同时也会介绍如何调试这些 JavaScript 代码。 导入 JavaScript 文件 在 QML 中导入 JavaScript 文件的方式…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...
