uniapp开发app使用海康威视播放监控视频流如何使用以及遇到了什么问题

uniapp开发的app中需要使用海康威视播放视频流

第一步:

去官网https://open.hikvision.com/download/5c67f1e2f05948198c909700?type=20下载相关的SD

因为我是使用uniapp开发的app,选择下载了H5视频播放器开发包V2.5.1,同时它会有相关的demo下载,功能还是比较全的

第二步:

运行demo

第三步:将相关的js文件SDK放在项目中

在项目中引入:

javascript 复制代码
<script module="vedio" lang="renderjs">
	export default {
		data() {
			return {
				playData: [],
				player: null,
				accessToken: null,
				playerSdkLoaded: false, // SDK是否加载完成
				isPlayerReady: false, // 标记播放器是否初始化完成(新增)
				JSPlugin: null // 缓存SDK实例,避免重复加载(新增)
			}
		},
		mounted() {
			const that = this;
			// 先修复removeEventListener空指针问题(关键)
			this.fixRemoveEventListener();
			// 只加载一次SDK,缓存到JSPlugin
			import('@/static/js/h5player.min.js').then(res => {
				console.log(res, 'SDK加载完成');
				that.JSPlugin = res.JSPlugin;
				that.playerSdkLoaded = true;
				// 初始化播放器(首次加载)
				that.initPlayer();
			}).catch(err => {
				console.error('SDK加载失败:', err);
			})
		},
		beforeDestroy() {
			// 页面销毁时彻底销毁播放器
			this.destroyPlayer().then(() => {
				this.player = null;
				this.isPlayerReady = false;
				this.JSPlugin = null;
			});
		},
		methods: {
			// 修复removeEventListener空指针(核心)
			fixRemoveEventListener() {
				const originalRemove = EventTarget.prototype.removeEventListener;
				EventTarget.prototype.removeEventListener = function(type, listener, options) {
					if (this) { // 仅当当前对象存在时执行
						try {
							originalRemove.call(this, type, listener, options);
						} catch (err) {
							if (err.message.includes('removeEventListener')) {
								console.warn('解绑事件忽略:', type);
							} else {
								throw err;
							}
						}
					}
				};
			},
			// 切换播放地址(核心改造)
			async changePlayUrl(newUrl, oldUrl, instance) {
				if (!newUrl || newUrl === oldUrl) return; // 空地址/相同地址不处理
				console.log('切换流地址:', newUrl);
				// 1. 先彻底销毁旧播放器
				await this.destroyPlayer();
				// 2. 确保SDK已加载,重新初始化播放器
				if (!this.JSPlugin) {
					console.error('SDK未加载完成');
					return;
				}
				await this.initPlayer();
				// 3. 播放器初始化完成后立即播放(取消setTimeout,改用实例就绪判断)
				if (this.player && this.isPlayerReady) {
					this.player.JS_Play(newUrl, {
						playURL: newUrl,
						mode: 0,
						PlayBackMode: 1,
						keepDecoder: 0
					}, 0).then(res => {
						console.log('播放成功:', res);
					}).catch(err => {
						console.error('播放失败:', err);
						// H.265解码失败时降级处理(可选)
						if (err.message.includes('h265')) {
							uni.showToast({
								title: 'H.265解码失败,请切换H.264流',
								icon: 'none'
							});
						}
					});
				}
			},
			// 销毁播放器(Promise封装,确保彻底)
			destroyPlayer() {
				return new Promise(resolve => {
					if (this.player && this.isPlayerReady) {
						try {
							this.player.JS_Stop(); // 先停止播放(海康标准方法)
							this.player.off(); // 解绑事件
							this.player.destroy(); // 销毁实例
							// 清空容器DOM,避免残留
							const container = document.getElementById('video-container');
							if (container) container.innerHTML = '';
						} catch (err) {
							console.warn('销毁播放器错误:', err);
						} finally {
							this.player = null;
							this.isPlayerReady = false;
							resolve();
						}
					} else {
						resolve();
					}
				});
			},
			// 全屏播放
			wholeFullScreen() {
				if (!this.player) return;
				this.player.JS_FullScreenDisplay(true).then(() => {
					console.log('全屏成功');
				}).catch(e => {
					console.error('全屏失败:', e);
				})
			},
			// 初始化播放器(锁定软解,稳化解码)
			initPlayer() {
				return new Promise((resolve) => {
					if (!this.JSPlugin) {
						resolve(false);
						return;
					}
					try {
						const my_player = new this.JSPlugin({
							szId: 'video-container', // 容器ID
							szBasePath: "/static/js/", // SDK路径
							iMaxSplit: 1, // 移动端只需要1路播放,减少性能消耗
							openDebug: false, // 关闭debug,减少日志干扰
							mseWorkerEnable: true, // 开启多线程解码,提升软解性能
							bSupporDoubleClickFull: true,
							// ========== 核心:锁定软解,避免H.265硬解不稳定 ==========
							decodeType: 'soft', // 强制软解(关键!放弃auto硬解)
							enableSoftDecode: true, // 显式开启软解
							supportH265: true,
							isFlushURI: true, // 切换流清空URI缓存
							reconnectTimes: 3, // 解码失败重连
							reconnectInterval: 2000,
							// ========== 移动端适配 ==========
							renderType: 'canvas', // canvas渲染更兼容
							lowLatency: false, // 关闭低延迟,换稳定性
							maxBufferLength: 5, // 降低缓冲,减少内存占用
						});
						// 绑定错误回调,捕获解码异常
						my_player.JS_SetWindowControlCallback({
							pluginErrorHandler: (iWndIndex, iErrorCode, oError) => {
								console.error('播放器错误:', iWndIndex, iErrorCode, oError);
								if (oError && oError.message.includes('h265')) {
									this.isPlayerReady = false;
								}
							},
							firstFrameDisplay: (iWndIndex, iWidth, iHeight) => {
								console.log('首帧显示:', iWndIndex, iWidth, iHeight);
								this.isPlayerReady = true; // 首帧显示标记就绪
							},
							performanceLack: (iWndIndex) => {
								console.warn('性能不足:', iWndIndex);
							}
						});
						this.player = my_player;
						this.isPlayerReady = true; // 标记初始化完成
						resolve(true);
					} catch (err) {
						console.error('初始化播放器失败:', err);
						this.isPlayerReady = false;
						resolve(false);
					}
				});
			},
			// 截取设备序号和通道号(保留)
			getHashParts(str) {
				const parts = str.split("#");
				return {
					before: parts[0],
					after: parts.length > 1 ? parts[1] : "",
				};
			}
		},
	}
</script>

在项目中也遇到了很多问题,也都一一解决了:

1:因为开发的app,在浏览器的手机模拟器能够播放,但是在真机运行的时候提示JSPlugin没有定义

后来经过调整,查资料是因为js文件引入没有加载成功,后来就改变了引入方式,变成这样

2:因为是多个视频流进行切换,在切换的时候会出现这样的问题,原因是实例未销毁

3:在切换的时候会出现[H5player]-%c2025-12-08 10:57:44.823%c-Error: color: blue color: black VideoDecoder not support h265: at app-view.js:45399,导致播放不出来,以下是解决办法

UniApp 中使用海康威视 H5 播放器切换视频流时出现 [H5player] VideoDecoder not support h265 错误,核心原因是移动端浏览器 / 设备不支持 H.265(HEVC)解码 ,且海康威视 H5 播放器默认未启用兼容降级策略。以下是分维度的解决方案,从「解码兼容」「流格式转换」「播放器配置」三个层面彻底解决:

一、核心问题定位

H.265(HEVC)是高效视频编码格式,但移动端存在两大兼容问题:

  1. 硬件层面:中低端安卓 /iOS 设备的视频解码芯片不支持 H.265 硬解;
  2. 浏览器层面 :移动端 Chrome/Safari 等浏览器的VideoDecoder API(WebCodecs)对 H.265 支持极差,仅部分高版本安卓设备兼容;
  3. 播放器层面:海康 H5 播放器默认优先使用硬解,未检测到 H.265 支持时直接报错,未自动降级为软解 / 转码。

以上就是我使用海康威视的经验分享,大家如果有相同的问题或者其它好的经验,可以评论区讨论哦

相关推荐
羊羊小栈1 小时前
基于「YOLO姿态识别 + AI大模型分析」的智能健身辅助系统(vue+flask+AI算法)
vue.js·人工智能·yolo·毕业设计·创业创新·大作业
一只一只妖1 小时前
Taro+Vue3+TS+Vite 小程序开发底座搭建流程
vue.js·小程序·taro
羽沢312 小时前
vue3 + element-plus 表单校验
前端·javascript·vue.js
Dgua2 小时前
一文吃透Vue Diff原理:从核心逻辑到实战避坑
前端·vue.js
小飞侠在吗2 小时前
vue Hooks
前端·javascript·vue.js
小茴香3532 小时前
vue3的传参方式总结
javascript·vue.js·typescript
梵得儿SHI2 小时前
Vue 核心语法深度解析:生命周期与响应式之计算属性(computed)与侦听器(watch/watchEffect)
前端·javascript·vue.js·计算属性·侦听器·缓存机制·数据派生
游戏开发爱好者82 小时前
以 uni-app 为核心的 iOS 上架流程实践, 从构建到最终提交的完整路径
android·ios·小程序·https·uni-app·iphone·webview
秋天的一阵风2 小时前
翻掘金看到停更的前辈们,突然想聊两句 🤔
前端·vue.js·程序员