首页 教程 Web前端 海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

海康威视

WEB3.3控件开发包 V3.3

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

下载得到海康威视的demo。按照说明文档启动项目。

如果是公司内部,一般都是配置好了对应的WiFi,不需要启动NGINX,直接启动.html文件即可

海康威视视频教程 注意:很多需要海康平台支持,需要付费

参考:

  • 在vue3 中使用海康威视WEB3.3控件开发包 V3.3 抓图

    • 如果你使用vue+vite对接遇到问题,可以参考Giteedemo

    • 有可能是路径问题。参考vite静态资源处理

      const getPath = () => { let path = new URL(`../../../plugin.html`, import.meta.url).href; console.log(path, "path"); return path; };

  • web端对接海康视频3.2开发包以及遇到的坑

Electron+vite+vue3+海康威视SDK开发过程踩坑

海康插件

  • 海康威视通过 HCWebSDKPlugin.exe 绘制出摄像头的播放画面。注意他找这个层级非常非常的高,并且是脱离文档流的,只要它被绘制出来,就是你把页面所有dom都删除,他依然纯在。
  • 它是单页面的。如果使用div去初始化多个插件是可以的,但是登录的时候,每次选择的插件是相同的
  • 海康威视对接有多种方式,通过网上查阅和观看源码发现,每种方式的最底层用的都是一套代码,对于不同的开发,进行了不同的封装

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

同一页面预览多个摄像头

使用nvr设备

使用nvr设备,一个账号配置多个摄像头。使用海康威视的demo可以实现分屏预览。如果只有一个摄像机是没有办法实现分屏预览的。500元就搞定。页面渲染直接使用div就行。代码放最下面了

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

使用nvr后,每个摄像头都是一个数字通道,参照编程指南传参

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

使用iframe 不推荐使用

上面说了海康威视插件是单页面的,不能使用div,那就要使用iframe

但是效果很不好。问题如下:

  • 图层会出现闪烁以至于消失。比如切屏、点击任务栏、点击Electron的窗口栏

  • 图层渲染位置不正确。海康插件是根据网页的左上角做渲染的,但是<div class="plugin" id="divplugin"></div>的位置是会影响最终结果的。比如使用绝对定位,设置top、left会使图层向右下移动。虽然说iframe是打开了一个新网页,但是它这个插架还是会根据最外层的网页为基准点,内部逻辑没办法探究。当渲染多个iframe的时候或者进行一些布局的时候,就会出现图层渲染位置不正确的问题

  • iframe中每个摄像头的登录顺序不固定。正确顺序为:1,2, 3, 4。实际为:2, 4, 1, 3

  • 对于登录操作,也不按照顺序渲染(好像是)

  • 如果要重新更换摄像头,需要全部退出再登录。上面说了,图层一旦出现,就不会改变,所以必须这样的。采用的是给每个组件添加一个key,每次选择摄像头的时候刷新key实现组件的刷新

  • 图层的层级太大了,该页面不能打开modalelectron中使用打开新标签页实现

  • 实现麻烦

    • 海康的源码是common.jsvitees moudle,所以html和js必须如下放置

    • 路径处理 const getPath = () => { let path = new URL(`../../../../public/html/plugin.html`, import.meta.url) .href; return path; };

    • 页面渲染顺序:父组件onMounted=>iframe,所以需要判断iframe加载完成,然后通知父组件才能进行通信。父组件将摄像头信息传入进行初始化、登录等操作

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

使用nvr预览踩坑

停止播放

查看源码后,很明显停止播放还做了其他操作。它会把当前窗口关闭,不能再继续使用。改用”全部停止播放“—— I_StopAllPlay ()。这个编程指南并没有写清楚(糟称冯 😊)

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

插件销毁

在离开页面后,图层依旧存在,即使退出登录也不好使。

bing 海康销毁插件找到了JS_DestroyPlugin,然后源码中搜一下找到了可以使用的api。这个api编程指南中也是没有的(糟称冯 😆)

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

组件初始化失败

插件已经安装并启动,demo中可以,另个一vue中也可以,之前iframe也可以,但是换成div就不行了。莫名过了一段时间自己好了。我换成iframe,iframe有g了,很奇怪

海康威视WEBSDK3.3控件开发-分屏预览多个摄像头

代码

webVideoCtrl.jsjquery放置在public/js文件夹中,如上图

camera.vue

<template> <div ref="playerRef" id="divPlugin" style="width: 100%; height: 100%"></div> </template> <script setup> const props = defineProps({ camera: { type: Object, }, }); const playerRef = ref(); const { camera } = toRefs(props); const cameraAll = ref([1, 2, 3, 4]); // 数字通道 const cameraView = ref([1, 2, 3, 4]); const closeNum = ref([]); let g_iWndIndex = 0; /** * 初始化相机 */ const init = () => { WebVideoCtrl.I_InitPlugin({ bWndFull: true, //是否支持单窗口双击全屏,默认支持 true:支持 false:不支持 iWndowType: 1, cbSelWnd: function (xmlDoc) { g_iWndIndex = parseInt($(xmlDoc).find("SelectWnd").eq(0).text(), 10); }, cbDoubleClickWnd: function () {}, cbEvent: (iEventType, iParam1) => { if (2 == iEventType) { // 回放正常结束 console.log("窗口" + iParam1 + "回放结束!"); } else if (-1 == iEventType) { console.log("设备" + iParam1 + "网络错误!"); } }, cbInitPluginComplete: function () { WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin").then( () => { // 检查插件是否最新 WebVideoCtrl.I_CheckPluginVersion().then((bFlag) => { if (bFlag) { alert("检测到新的插件版本,请升级HCWebSDKPlugin.exe!"); } else { console.log("初始化成功"); login(); } }); }, () => { alert("插件初始化失败,请确认是否已安装插件"); } ); }, }); }; /** * 登录 */ const login = () => { WebVideoCtrl.I_Login( camera.value.ip, 1, camera.value.port, camera.value.username, camera.value.pwd, { timeout: 60000, success: function (xmlDoc) { console.log("登录成功"); setTimeout(function () { getChannelInfo(`${camera.value.ip}_${camera.value.port}`); }, 1000); getDevicePort(`${camera.value.ip}_${camera.value.port}`); //获取端口 }, error: function (error) { console.log(error, "登录失败"); }, } ); }; // 数字通道 const getChannelInfo = (szDeviceIdentify) => { WebVideoCtrl.I_GetDigitalChannelInfo(szDeviceIdentify, { success: function (xmlDoc) { var oChannels = $(xmlDoc).find("InputProxyChannelStatus"); cameraAll.value = []; $.each(oChannels, function (i) { var id = $(this).find("id").eq(0).text(), name = $(this).find("name").eq(0).text(), online = $(this).find("online").eq(0).text(); if ("false" == online) { // 过滤禁用的数字通道 return true; } cameraAll.value[i] = id; if (i < 4) { cameraView.value[i] = id; } else { closeNum.value[i - 4] = id; } }); }, error: function (oError) {}, }); }; // 获取端口 const getDevicePort = (szDeviceIdentify) => { if (!szDeviceIdentify) { return; } WebVideoCtrl.I_GetDevicePort(szDeviceIdentify).then( (oPort) => { WebVideoCtrl.I_ChangeWndNum(2).then( () => { // console.log("分屏成功"); startRealPlay(); }, (oError) => {} ); }, (oError) => { console.log(oError.errorMsg, "获取端口失败"); } ); }; const logout = () => { let ip_port = `${camera.value.ip}_${camera.value.port}`; WebVideoCtrl.I_Logout(ip_port).then( () => { console.log("退出成功"); }, () => { console.log("退出失败!"); } ); }; const destroy = (item) => { WebVideoCtrl.I_HidPlugin().then( () => { console.log("销毁组件成功"); }, (error) => { console.log(error); } ); }; const play = (iWndIndex, iChannelID) => { // console.log("窗口:", iWndIndex, "----数字通道:", iChannelID, "预览"); WebVideoCtrl.I_StartRealPlay(`${camera.value.ip}_${camera.value.port}`, { iStreamType: 1, iChannelID: iChannelID, //播放通道 bZeroChannel: false, iWndIndex: iWndIndex, success: function () { // console.log( // "窗口:", // iWndIndex, // "----数字通道:", // iChannelID, // "开始预览成功!" // ); }, error: function (oError) { console.log( "窗口:", iWndIndex, "----数字通道:", iChannelID, "开始预览失败!", oError.errorMsg ); }, }); }; // 预览 const startRealPlay = () => { for (let i = 0; i < 4; i++) { let iChannelID = cameraView.value[i]; if (iChannelID) play(i, iChannelID); } }; const rePlay = () => { WebVideoCtrl.I_StopAllPlay().then((item) => { startRealPlay(); }); }; // 停止预览 const clickStopRealPlay = () => { WebVideoCtrl.I_StopAllPlay().then(() => { console.log("停止播放成功"); }); }; const changeIndex = (num) => { // num 为通道号 let isClose = closeNum.value.findIndex((item) => item == num); if (isClose > -1) { // 重新打开 closeNum.value.splice(isClose, 1); } else { // 关闭 closeNum.value.push(num); } cameraView.value = cameraAll.value.filter( (item) => !closeNum.value.includes(item) ); rePlay(); }; onMounted(() => { init(); }); onBeforeUnmount(() => { clickStopRealPlay(); logout(); destroy(); }); defineExpose({ changeIndex, }); </script>

index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>摄像头预览</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.js"></script> <script id="videonode" src="/js/webVideoCtrl.js"></script> <script src="/js/jquery-1.7.1.min.js"></script> <!-- 好像不需要。。。 --> <!-- <script id="videonode" src="/js/jsVideoPlugin-1.0.0.min.js"></script> --> </body> </html>

评论(0)条

提示:请勿发布广告垃圾评论,否则封号处理!!

    猜你喜欢
    【MySQL】用户管理

    【MySQL】用户管理

     服务器/数据库  4个月前  4.14k

    我们推荐使用普通用户对数据的访问。而root作为管理员可以对普通用户对应的权限进行设置和管理。如给张三和李四这样的普通用户权限设定后。就只能操作给你权限的库了。

    Cursor Rules 让开发效率变成10倍速

    Cursor Rules 让开发效率变成10倍速

     服务器/数据库  4个月前  2.39k

    在AI与编程的交汇点上,awesome-cursorrules项目犹如一座灯塔,指引着开发者们驶向更高效、更智能的编程未来。无论你是经验丰富的老手,还是刚入行的新人,这个项目都能为你的编程之旅增添一抹亮色。这些规则文件就像是你私人定制的AI助手,能够根据你的项目需求和个人偏好,精确地调教AI的行为。突然间,你会发现AI不仅能理解Next.js的最佳实践,还能自动应用TypeScript的类型检查,甚至主动提供Tailwind CSS的类名建议。探索新的应用场景,推动AI辅助编程的边界。

    探索Django 5: 从零开始,打造你的第一个Web应用

    探索Django 5: 从零开始,打造你的第一个Web应用

     服务器/数据库  4个月前  2.2k

    Django 是一个开放源代码的 Web 应用程序框架,由 Python 写成。它遵循 MVT(Model-View-Template)的设计模式,旨在帮助开发者高效地构建复杂且功能丰富的 Web 应用程序。随着每个版本的升级,Django 不断演变,提供更多功能和改进,让开发变得更加便捷。《Django 5 Web应用开发实战》集Django架站基础、项目实践、开发经验于一体,是一本从零基础到精通Django Web企业级开发技术的实战指南《Django 5 Web应用开发实战》内容以。

    MySQL 的mysql_secure_installation安全脚本执行过程介绍

    MySQL 的mysql_secure_installation安全脚本执行过程介绍

     服务器/数据库  4个月前  2.15k

    mysql_secure_installation 是 MySQL 提供的一个安全脚本,用于提高数据库服务器的安全性

    【MySQL基础篇】概述及SQL指令:DDL及DML

    【MySQL基础篇】概述及SQL指令:DDL及DML

     服务器/数据库  4个月前  895

    数据库是长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。数据库不仅仅是数据的简单堆积,而是遵循一定的规则和模式进行组织和管理的。数据库中的数据可以包括文本、数字、图像、音频等各种类型的信息。

    Redis中的哨兵(Sentinel)

    Redis中的哨兵(Sentinel)

     服务器/数据库  4个月前  716

    ​ 上篇文章我们讲述了Redis中的主从复制(Redis分布式系统中的主从复制-CSDN博客),本篇文章针对主从复制中的问题引出Redis中的哨兵,希望本篇文章会对你有所帮助。