一、封装HLS播放组件
直接上代码:
请先导入 hls.js 依赖
封装的React组件,设置有错误捕捉无闪动继续加载画面
import React, { useEffect, useRef } from 'react';
import Hls from 'hls.js';
type HlsPlayerProps = {
url?: string; // HLS m3u8 地址
width?: number;
height?: number;
isLive?: boolean;
};
const HlsPlayer: React.FC<HlsPlayerProps> = ({ url }) => {
const videoRef = useRef<HTMLVideoElement>(null);
const hlsRef = useRef<Hls | null>(null);
const handleHlsError = (hls: Hls, data: any) => {
console.error('HLS 播放错误', data);
if (data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
console.warn('网络错误,尝试重新加载分片...');
hls.startLoad(); // 继续加载,不 destroy
break;
case Hls.ErrorTypes.MEDIA_ERROR:
console.warn('媒体错误,尝试恢复...');
hls.recoverMediaError(); // 恢复媒体解码
break;
default:
console.error('不可恢复错误,停止播放');
hls.destroy();
break;
}
} else if (data.details === Hls.ErrorDetails.BUFFER_STALLED_ERROR) {
console.warn('缓冲区无数据,尝试继续加载...');
hls.startLoad(); // 直接恢复加载,不 destroy
}
};
const initHls = () => {
if (!url || !videoRef.current) return;
if (hlsRef.current) {
hlsRef.current.destroy();
hlsRef.current = null;
}
if (Hls.isSupported()) {
const hls = new Hls({});
hls.loadSource(url);
hls.attachMedia(videoRef.current);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
videoRef.current?.play();
});
hls.on(Hls.Events.ERROR, (event, data) => handleHlsError(hls, data));
hlsRef.current = hls;
} else if (videoRef.current.canPlayType('application/vnd.apple.mpegurl')) {
videoRef.current.src = url;
videoRef.current.addEventListener('loadedmetadata', () => {
videoRef.current?.play();
});
} else {
console.error('当前环境不支持 HLS 播放');
}
};
useEffect(() => {
initHls();
return () => {
if (hlsRef.current) {
hlsRef.current.destroy();
hlsRef.current = null;
}
};
}, [url]);
// 如果没传 URL,显示加载占位
if (!url) {
return (
<div style={{
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
background: 'rgba(0,0,0,0.1)',
color: '#999',
fontSize: 14
}}>
正在加载视频...
</div>
);
}
return (
<div style={{ width: '100%', height: '100%' }}>
<video
ref={videoRef}
style={{ width: '100%', height: '100%', objectFit: 'cover', }}
autoPlay
muted
loop
playsInline
/>
</div>
);
};
export default HlsPlayer;
二、HLS组件播放使用
// 其中的videoUrl 就是HLS播放的视频流
<div style={{ width: '200ox', height: '200px' }}>
<HlsPlayer url={videoUrl}></HlsPlayer>
</div>
三、监控展示效果
直接播放画面