前言
该h5属于硬件产品,websdk版不是默认显示的那个
硬件产品-websdk插件版
也可以直接下载
www.hikvision.com/en/support/…
优点:
1 不需要后台参与,指转wss流协议在网页播放,官网对照是h5视频播放器开发包 2 只要有超脑账号密码ip
缺点:
1 浏览器出现多窗口都有监控画面显示时,会快速切换时,重复启用海康插件窗口,出现多个画面叠加
2 关闭a页面打开b页面,可能虽然关闭了a但未及时释放监控画面导致b页上出现了a页的监控画面。
异常时任务管理器搜hc结束监控进程就行
本质是任务管理器开机自启了hc程序,网页调用,没启用也可以手动搜hc一般不用
注意是是HCWebSDKPluginsUserSetup别安装错成VideoWebPlugin.exe
addEventListener如果是vue可以beforeDestroy声明周期执行相同
来自本站另外一个来源:juejin.cn/post/744964…
<!DOCTYPE html>
<html>
<head>
<title>海康威视自动监控</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
body,
html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#divPlugin {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="divPlugin"></div>
<script src="../../../public/static/lib/jquery-3.3.1.min.js"></script>
<!-- 海康账号登录视频插件 -->
<script src="../../../public/static/js/webVideoCtrl.js"></script>
<script>
function getQueryStringParam(paramName) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(paramName);
}
// 1 单窗口;
// 2 4 宫格,即 2×2 布局;
// 3 6 宫格;
// 4 8 宫格;
// 5 9 宫格,即 3×3 布局;
// 6 16 宫格。
// 新
// 1 1×1 1
// 2 2×2 4
// 3 3×3 9
// 4 4×4 16
const CONFIG = {
IP: getQueryStringParam("ip"),
PORT: "80",
PROTOCOL: 1,
USER: getQueryStringParam("user"),
PASSWORD: getQueryStringParam("pwd"),
RTSP_PORT: "554",
iWndowType: getQueryStringParam("split") * 1, // 必须数字
// 1 单窗口;
// 2 4 宫格,即 2×2 布局;
// 3 6 宫格;
// 4 8 宫格;
// 5 9 宫格,即 3×3 布局;
// 6 16 宫格。
channels: getQueryStringParam("channel")
? getQueryStringParam("channel").split(",")
: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
STREAM_TYPE: 2, // 1主码流卡顿 2子码流不卡顿
};
let webVideoCtrl = null;
let isPreviewing = false;
let controller = null;
let initInProgress = false; // 跟踪初始化状态
class HikvisionController {
constructor() {
this.deviceId = `${CONFIG.IP}_${CONFIG.PORT}`;
this.isPreviewing = false;
console.log("[控制器] 初始化设备:", this.deviceId);
this.init();
}
// 参考Vue版本的简单回调流程
init() {
if (!window.WebVideoCtrl) {
showError("<strong>❌ 插件库未加载</strong><br>请检查webVideoCtrl.js路径", 0);
return;
}
console.log("[初始化] 开始...");
// 1. 初始化插件(回调方式)
WebVideoCtrl.I_InitPlugin({
bWndFull: true,
iWndowType: CONFIG.SPLIT,
cbInitPluginComplete: () => {
console.log("[初始化] 插件初始化完成,准备插入...");
// 2. 插入插件
WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin")
.then(() => {
console.log("[初始化] 插件插入成功");
// 3. 设置窗口数量
if (WebVideoCtrl.I_ChangeWndNum) {
WebVideoCtrl.I_ChangeWndNum(CONFIG.SPLIT);
}
// 4. 登录设备(回调方式)
this.loginAndPreview();
})
.catch(err => {
showError(`<strong>插件插入失败</strong><br>${err.message || JSON.stringify(err)}`, 0);
});
}
});
}
loginAndPreview() {
console.log(`[登录] 正在连接 ${CONFIG.IP}:${CONFIG.PORT}...`);
WebVideoCtrl.I_Login(
CONFIG.IP,
1, // 协议类型
CONFIG.PORT,
CONFIG.USER,
CONFIG.PASSWORD,
{
async: true,
success: (xmlDoc) => {
const status = $(xmlDoc).find("statusString").text();
if (status === "OK") {
console.log("[登录] ✓ 成功");
this.startPreview();
} else {
const statusCode = $(xmlDoc).find("statusCode").text();
showError(`<strong>登录异常</strong><br>状态: ${status} (${statusCode})`, 8000);
}
},
error: (err) => {
console.error("[登录] ✗ 失败:", err);
let errorMessage = `<strong>🚨 登录失败 (${err.errorCode})</strong><br>`;
switch(err.errorCode) {
case 21:
errorMessage += `用户名或密码错误<br><small>用户: ${CONFIG.USER}</small>`;
break;
case 403:
errorMessage += `IP被设备封锁<br><small>请检查安全策略</small>`;
break;
default:
errorMessage += `${err.errorMsg || '未知错误'}`;
}
showError(errorMessage, 10000);
}
}
);
}
startPreview() {
if (this.isPreviewing) return;
this.isPreviewing = true;
console.log("[预览] 启动所有通道...", CONFIG.CHANNELS);
// 先停止所有播放(忽略错误)
if (WebVideoCtrl.I_StopRealPlayAll) {
WebVideoCtrl.I_StopRealPlayAll(this.deviceId).catch(() => {});
}
// 逐个启动预览
CONFIG.CHANNELS.forEach((channel, index) => {
setTimeout(() => {
this.playChannel(channel, index);
}, index * 200); // 增加微小延迟,避免同时请求过载
});
}
playChannel(iChannelID, wndIndex) {
WebVideoCtrl.I_StartRealPlay(this.deviceId, {
iWndIndex: wndIndex,
iChannelID: iChannelID,
iStreamType: 2, // 1主 2子码流
bZeroChannel: false,
iPort: 554, // RTSP端口
success: () => {
console.log(`[预览] ✓ 通道 ${iChannelID} 启动成功`);
},
error: (err) => {
console.error(`[预览] ✗ 通道 ${iChannelID} 失败:`, err);
if (err.errorCode === 403) {
showError(`<strong>权限错误 (403)</strong><br>无法访问通道 ${iChannelID}`, 6000);
}
}
});
}
}
// ==========================================
// 页面加载
// ==========================================
document.addEventListener("DOMContentLoaded", () => {
console.log("[页面] DOM加载完成");
});
// 页面卸载清理
window.addEventListener("beforeunload", () => {
if (window.WebVideoCtrl) {
console.log("[页面] 执行清理...");
try {
WebVideoCtrl.I_StopAllPlay();
WebVideoCtrl.I_DestroyPlugin();
WebVideoCtrl.I_Logout(`${CONFIG.IP}_${CONFIG.PORT}`);
} catch (e) {
console.warn("清理警告:", e);
}
}
});
</script>
</body>
</html>
使用方式
https://xx.com/index.html?ip=192.168.0.2&user=admin&pwd=xx&split=2&channel=3,2,6,7
超脑的ip账号密码
注意下载官网插件后的js,要两个放入对应,js是动态加载的会自行加载另外一个虽然html未引入
vue版未验证: juejin.cn/post/733393…
推荐个另外的vue版,同样public下index.html需要引入jq和官方的webVideo.js
<template>
<div ref="divPlugin" id="divPlugin" class="plugin-container"></div>
</template>
<script>
export default {
name: 'HikvisionMonitor',
props: {
config: {
type: Object,
required: true,
default: () => ({})
}
},
data() {
return {
webVideoCtrl: null,
isPreviewing: false,
controller: null,
initInProgress: false,
deviceId: '',
channels: []
}
},
watch: {
config: {
handler(newVal) {
// this.handleConfigChange(newVal)
},
deep: true
}
},
mounted() {
// 初始化插件容器
this.initPlugin()
},
beforeDestroy() {
// 组件销毁前清理插件资源
console.log('组件销毁前清理插件资源')
this.closeHk()
},
methods: {
// 获取查询参数(此处可根据实际需求调整)
getQueryStringParam(paramName) {
const urlParams = new URLSearchParams(window.location.search)
return urlParams.get(paramName)
},
handleConfigChange(newConfig) {
// 当配置改变时,重新初始化或更新预览
this.closeHk() // 先关闭当前预览
this.initPlugin() // 重新初始化
},
initPlugin() {
if (this.initInProgress) return
this.initInProgress = true
this.deviceId = `${this.config.ip}_${this.config.port || 80}`
this.channels = this.config.channel || [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 根据传入配置解析通道
if (!window.WebVideoCtrl) {
console.error('WebVideoCtrl 插件未加载')
this.initInProgress = false
return
}
// 初始化插件
WebVideoCtrl.I_InitPlugin({
bWndFull: true,
cbInitPluginComplete: () => {
console.log('插件初始化完成')
this.$nextTick(() => {
if (this.$refs.divPlugin) {
// 插入插件到容器中
WebVideoCtrl.I_InsertOBJECTPlugin('divPlugin')
.then(() => {
this.loginDeviceAndSetupDisplay()
})
.catch(err => {
console.error(1, err)
})
} else {
console.error('未找到插件容器')
}
})
}
})
},
loginDeviceAndSetupDisplay() {
// 登录设备并设置显示
if (window.WebVideoCtrl && WebVideoCtrl.I_Login) {
WebVideoCtrl.I_Login(
this.config.ip,
1, // 假设协议为 1(可根据实际情况调整)
this.config.port || 80,
this.config.user,
this.config.pwd,
{
success: xmlDoc => {
if ($(xmlDoc).find('statusString').text() === 'OK') {
this.setupDisplay()
} else {
console.error('登录状态异常')
}
},
error: err => {
console.error('登录失败:', err)
}
}
)
} else {
console.error('WebVideoCtrl.I_Login 方法未定义')
}
},
setupDisplay() {
// 设置显示布局
if (window.WebVideoCtrl && WebVideoCtrl.I_ChangeWndNum) {
// 切割画面要求数字
WebVideoCtrl.I_ChangeWndNum(this.config.split || 2)
}
// window.addEventListener('resize', () => {
// if (window.WebVideoCtrl && WebVideoCtrl.I_Resize) {
// WebVideoCtrl.I_Resize(window.innerWidth, window.innerHeight)
// }
// })
this.startPreviewAllChannels() // 启动所有通道预览
},
startPreviewAllChannels() {
if (this.isPreviewing) return
this.isPreviewing = true
try {
if (window.WebVideoCtrl && WebVideoCtrl.I_StopRealPlayAll) {
WebVideoCtrl.I_StopRealPlayAll(this.deviceId)
}
this.channels.forEach((channel, index) => {
this.playChannel(channel, index)
})
} catch (error) {
console.error('预览启动失败:', error)
} finally {
this.isPreviewing = false
}
},
playChannel(iChannelID, wndIndex) {
if (!window.WebVideoCtrl || !WebVideoCtrl.I_StartRealPlay) {
console.error('WebVideoCtrl.I_StartRealPlay 方法未定义')
return
}
WebVideoCtrl.I_StartRealPlay(this.deviceId, {
iWndIndex: wndIndex,
iChannelID: parseInt(iChannelID), // 确保通道 ID 为数字类型
iStreamType: 2, // 假设流类型为 2(可根据实际情况调整)
bZeroChannel: false,
iPort: 554, // RTSP 端口(可根据实际情况调整)
success: () => {
console.log(`通道 ${iChannelID} 预览启动成功`)
},
error: err => {
console.error(`通道 ${iChannelID} 预览启动失败:`, err)
}
})
},
closeHk() {
if (window.WebVideoCtrl) {
console.log('关闭预览')
window.WebVideoCtrl.I_StopAllPlay()
console.log('销毁插件')
window.WebVideoCtrl.I_DestroyPlugin()
window.WebVideoCtrl.I_Logout(this.deviceId)
}
}
}
}
</script>
<style scoped>
.plugin-container {
width: 100%;
height: 100%;
}
</style>