Files
Visualize-electronic-fences/src/utils/video.ts
2026-07-20 10:22:52 +08:00

106 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Hls from 'hls.js';
import { log } from 'node:console';
let hlsInstance: Hls | null = null;
// let hlsRetryCount = 0;
export const initHls = (monitorVideoUrl, monitorVideoRef, isDialogVisible?: () => boolean) => {
console.log('isDialogVisible', isDialogVisible);
const url = monitorVideoUrl.value;
const video = monitorVideoRef.value;
if (!url || !video) return;
// 销毁已有实例
if (hlsInstance) {
try {
hlsInstance.destroy();
} catch (e) {
// ignore
}
hlsInstance = null;
}
if (Hls.isSupported()) {
const hls = new Hls({
// ★ ZLM 注册流需要时间,配置自动重试
manifestLoadingMaxRetry: 5, // m3u8 加载最多重试20次
manifestLoadingRetryDelay: 500, // 每次重试间隔500ms
manifestLoadingTimeOut: 5000, // m3u8 请求超时5秒
levelLoadingMaxRetry: 2, // ts 分片加载最多重试20次
levelLoadingRetryDelay: 500,
lowLatencyMode: false, // 关掉低延迟模式,更稳定
startLevel: -1 // 自动选择码率
});
hls.loadSource(url);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
// 自动播放(若浏览器允许)
try {
video.play().catch(() => {});
} catch (e) {}
// 加载成功,重置重试计数
// hlsRetryCount = 0;
});
// ★ 错误自动恢复hls.js 拿到空 m3u8 或 ts 加载失败时自动重试
hls.on(Hls.Events.ERROR, (event, data) => {
if (data.fatal && (!isDialogVisible || isDialogVisible())) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
hls.startLoad();
hls.once(Hls.Events.FRAG_LOADED, () => {
//分片加载成功后播放
try {
video.play().catch(() => {});
} catch (e) {}
});
ElMessage.error('网络错误, 请检查网络或重试');
break;
case Hls.ErrorTypes.MEDIA_ERROR:
// 媒体解码错误 → 尝试恢复
hls.recoverMediaError();
break;
default:
// 其他致命错误 → 销毁,让下一次 initHls 重建
hls.destroy();
hlsInstance = null;
break;
}
}
});
hlsInstance = hls;
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// Safari/原生支持 HLS
video.src = url;
video.addEventListener('loadedmetadata', () => {
try {
video.play().catch(() => {});
} catch (e) {}
});
} else {
//proxy?.$modal.msgWarning('当前浏览器不支持 HLS 播放');
ElMessage.error('当前浏览器不支持 HLS 播放');
}
};
export const destroyHls = (monitorVideoRef) => {
try {
if (hlsInstance) {
hlsInstance.destroy();
hlsInstance = null;
}
} catch (e) {}
const video = monitorVideoRef.value;
if (video) {
// 清理原生 src避免残留
try {
video.pause();
video.removeAttribute('src');
// 对某些浏览器,需要调用 load() 来重置 media element
if (typeof video.load === 'function') video.load();
} catch (e) {
console.log('Error in destroyHls:', e);
}
}
};
export default { initHls, destroyHls };