面向需要在网页里接入海康设备实时预览 / 回放的前端同学。本文只讲 插件版(OCX / WebComponents) 的接入方式与注意事项,不绑定具体业务页面。
常见配套包名:HCWebSDKPluginsUserSetup.exe(Windows)。前端通过全局对象 WebVideoCtrl 调用 I_* 系列 API。
一、插件版是什么
插件版本质是:浏览器装一个本地播放组件,页面用 ActiveX(旧 IE)或 WebComponents/NPAPI 式桥接,把解码、渲染交给本地进程。
| 项 | 说明 |
|---|---|
| 核心对象 | window.WebVideoCtrl |
| 安装包 | 常见为 HCWebSDKPluginsUserSetup.exe |
| 检测 API | I_CheckPluginInstall(),返回 -1 表示未安装 |
| 销毁 API | I_DestroyPlugin() |
| 典型环境 | Windows + 特定浏览器(历史方案多依赖 IE / 企业定制 Chromium) |
和后文将写的「无插件版」对比:
| 插件版 | 无插件版 | |
|---|---|---|
| 客户端 | 必须安装本地插件 | 不用装插件,靠 WASM/JS |
| 检测 | I_CheckPluginInstall |
I_SupportNoPlugin |
| 销毁 | I_DestroyPlugin |
I_DestroyWorker |
| 浏览器 | 对内核、位数敏感 | 通常要求较新的 Chromium |
二、脚本与静态资源
页面通常需要提前注入(顺序因官方 demo 而异,常见组合):
- jQuery(部分接口仍用
$解析 XML) - 加密相关脚本(登录 / 会话)
webVideoCtrl.js(暴露WebVideoCtrl)
示例(示意):
xml
<script src="/static/hcWebSdk/encryption/aes.js"></script>
<script src="/static/hcWebSdk/webVideoCtrl.js"></script>
业务代码启动前先轮询确认全局对象:
javascript
function waitForWebVideoCtrl(timeoutMs = 10000): Promise<boolean> {
const start = Date.now()
return new Promise((resolve) => {
const tick = () => {
if (window.WebVideoCtrl) return resolve(true)
if (Date.now() - start > timeoutMs) return resolve(false)
setTimeout(tick, 500)
}
tick()
})
}
三、标准流程:检测 → 初始化 → 插入 → 登录 → 预览
scss
脚本加载成功
↓
I_CheckPluginInstall() !== -1
↓
I_InitPlugin({ ... cbInitPluginComplete })
↓
I_InsertOBJECTPlugin(容器 DOM id)
↓
I_Login(ip, protocol, port, user, pass, { success, error })
↓
I_GetDevicePort / 通道信息(可选)
↓
I_StartRealPlay / I_StartPlayback
↓
离开页面:I_Stop → I_Logout → I_DestroyPlugin
1. 检测是否安装
javascript
const status = WebVideoCtrl.I_CheckPluginInstall()
if (status === -1) {
// 引导用户下载 HCWebSDKPluginsUserSetup.exe,安装后刷新页面
throw new Error('海康插件未安装')
}
可按系统提供安装包:
- Windows:
/plugin/HCWebSDKPluginsUserSetup.exe - Mac:官方若提供对应包,再单独配置(很多项目从未落地 Mac 包)
2. 初始化并插入容器
插件版初始化常见是 对象参数(不传宽高字符串):
typescript
await new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('插件初始化超时')), 15000)
WebVideoCtrl.I_InitPlugin({
bWndFull: true,
iWndowType: 1, // 1=1×1,2=2×2,3=3×3 ...
cbSelWnd() {},
cbDoubleClickWnd() {},
cbEvent() {},
cbInitPluginComplete() {
clearTimeout(timer)
// 往指定空容器插入插件对象
WebVideoCtrl.I_InsertOBJECTPlugin('hikPluginBox')
.then(() => resolve(true))
.catch(reject)
},
})
})
容器要求:
- 页面里有一个 空的
<div id="hikPluginBox"></div> - 不要在里面再塞 Vue/React 子节点;插入时会改写 DOM
- 容器需要有明确宽高,否则容易黑屏
3. 登录设备
javascript
const protocol = location.protocol === 'https:' ? 2 : 1 // 1=http,2=https
const ret = WebVideoCtrl.I_Login(ip, protocol, port, username, password, {
timeout: 3000,
success() {
// deviceIdentify 常用约定:`${ip}_${port}`
},
error(err) {
// errorCode === 2001:设备已在插件会话中登录,可按成功处理
},
})
// 同步返回 -1:表示已登录
if (ret === -1) {
// 视为已登录
}
4. 实时预览
javascript
const deviceIdentify = `${ip}_${port}`
const wnd = WebVideoCtrl.I_GetWindowStatus(0)
if (wnd) {
WebVideoCtrl.I_Stop({ iWndIndex: 0 })
}
WebVideoCtrl.I_StartRealPlay(deviceIdentify, {
iWndIndex: 0,
iStreamType: 1, // 主码流
iChannelID: 1,
bZeroChannel: false,
success() {},
error(status) {},
})
5. 回放
javascript
WebVideoCtrl.I_RecordSearch(deviceIdentify, channelId, startTime, endTime, {
iStreamType: 1,
iSearchPos: 0,
success(xmlDoc) {
// 响应里常见:OK / MORE / NO MATCHES
// MORE 时递增 iSearchPos 继续查
},
})
WebVideoCtrl.I_StartPlayback(deviceIdentify, {
iStreamType: 1,
iChannelID: channelId,
szStartTime: '2026-07-15 10:00:00',
szEndTime: '2026-07-15 11:00:00',
success() {},
error() {},
})
6. 云台
php
// cmd:1上 2下 3左 4右;10/11 变倍;12/13 聚焦;14/15 光圈
WebVideoCtrl.I_PTZControl(cmd, false, { iWndIndex: 0, iPTZSpeed: 4 })
// 动作后延时发送 stop
setTimeout(() => {
WebVideoCtrl.I_PTZControl(cmd, true, { iWndIndex: 0, iPTZSpeed: 4 })
}, 300)
7. 销毁
scss
WebVideoCtrl.I_Stop() // 或按窗口停
WebVideoCtrl.I_Logout(deviceIdentify)
WebVideoCtrl.I_DestroyPlugin()
切记: 插件版用 I_DestroyPlugin,不要和无插件的 I_DestroyWorker 混用。
四、注意事项(踩坑清单)
1. 必须先装插件,且安装后刷新
未安装时 I_CheckPluginInstall() === -1。用户装完若页面不刷新,WebVideoCtrl / 检测结果可能仍是旧状态。产品文案建议明确:安装完成后请刷新页面。
2. 浏览器与系统限制很硬
- 多数插件包面向 Windows
- Mac / Linux 往往无包或不可用,别在 UI 上假装「全平台可装」
- 现代 Chrome 已弱化/移除传统插件能力,插件版越来越难在默认浏览器跑通
→ 长期更宜迁到无插件版
3. 容器 DOM 只能是「空壳」
I_InsertOBJECTPlugin 会接管节点。若用前端框架在同一个节点下 v-if 子组件、或反复销毁重建父节点,容易出现:
parentNode为空- 插入返回
-1 - 黑屏、焦点异常
实践:视频容器单独一个永远存在的空 div,上层 UI 不要嵌进它内部。
4. 视频画面上叠不了普通网页布局
插件版画面不是普通的 <video> / Canvas,而是由本地插件以原生窗口层绘制。它往往压在 HTML 之上,不参与常规文档流的层叠:
- 在播放区域上用 CSS/
z-index盖遮罩、水印、Loading、Tooltip、弹层,均无效 - 整页 Modal、抽屉若盖住视频区,会出现「对话框在下面、画面仍戳在最前」的穿帮
opacity、圆角裁剪、滤镜、混合模式对插件窗口也不生效
交互与信息建议放到播放区外侧(侧栏、底栏、工具条)。若必须暂时压住画面(切页、弹确认框),优先:
- 先停播 / 隐藏或销毁插件窗口,再弹页面层
- 或把确认类 UI 设计到不与视频矩形相交的区域
产品评审时尽早约定:画面内不做复杂 HTML 叠加;有强叠加诉求时,优先评估无插件版(Canvas 渲染,才能正常叠 DOM)。
5. 登录态别重复造混乱
I_Login 同步 -1 或回调 errorCode === 2001,通常表示 已经登录过 。切页若不 I_Logout,再进页面很容易撞上 2001。建议:
- 页面离开:停播 → 登出 →
I_DestroyPlugin - 2001 可按成功容错,但要自己维护「本地是否已记录该设备」
6. 窗口占用要先停再播
同一窗口再次 I_StartRealPlay / I_StartPlayback 前,先 I_GetWindowStatus + I_Stop,否则容易失败或卡死上一路画面。
7. 协议要跟页面一致
I_Login 的 iProtocol:1 = http,2 = https。页面是 HTTPS、却按 HTTP 登录设备,常见证书/混合内容问题。
8. 分屏与尺寸
iWndowType:1/2/3/4 对应 1×1 / 2×2 / 3×3 / 4×4- 布局变化后如有
I_Resize,等容器真正有宽高再调(侧栏动画结束后再调更稳)
9. 安装包分发与安全策略
企业内网常要把安装包挂在静态资源目录(如 /plugin/)。注意:
- HTTPS 站点下载 exe 可能被浏览器拦截
- 权限策略、杀毒软件误报
- 版本升级后旧插件与新
webVideoCtrl.js不匹配
10. 全局单例思维
插件往往在浏览器进程里是单实例倾向:多个页面/多个容器同时 I_InitPlugin 很容易打架。常见做法:
- 全局只保留一个插件宿主
- 或切页前完整 destroy,再在新容器 init
五、推荐目录结构(示意)
csharp
public/
plugin/
HCWebSDKPluginsUserSetup.exe # Windows 安装包
static/
hcWebSdk/
webVideoCtrl.js
encryption/
六、何时还该用插件版
适合这些情况:
- 客户机可控、允许统一装包(如机房专用电脑)
- 设备固件/取流方式不支持无插件 WebSocket
- 已有成熟插件运维链路,短期无法迁 WASM
否则,更建议直接做无插件版(Chromium + WASM),减少安装、兼容与客服成本。下一篇会专门写 无插件版 的用法与注意事项。
小结
插件版接入骨架很固定:检测安装 → Init/Insert → Login → RealPlay/Playback → DestroyPlugin 。真正拖垮交付的通常是环境与交互边界:浏览器砍插件、容器 DOM 被框架改坏、画面是原生窗口叠不上网页样式、登录态/窗口态未清理、安装包分发不完整。
把它当成「本地播放器 + JS 桥」来管生命周期,会比当成普通 <video> 稳得多。