mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-15 00:33:44 +08:00
feat: Add useHlsPlayer hook to manage HLS video playback and integrate it into DesktopVideoPlayer.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useDesktopPlayerState } from './hooks/useDesktopPlayerState';
|
||||
import { useDesktopPlayerLogic } from './hooks/useDesktopPlayerLogic';
|
||||
import { useHLSPreloader } from './hooks/useHLSPreloader';
|
||||
import { useHlsPlayer } from './hooks/useHlsPlayer';
|
||||
import { DesktopControlsWrapper } from './desktop/DesktopControlsWrapper';
|
||||
import { DesktopOverlayWrapper } from './desktop/DesktopOverlayWrapper';
|
||||
|
||||
@@ -29,6 +30,13 @@ export function DesktopVideoPlayer({
|
||||
// Preload HLS segments
|
||||
useHLSPreloader({ src, currentTime, videoRef: refs.videoRef, isLoading: state.isLoading });
|
||||
|
||||
// Initialize HLS Player
|
||||
useHlsPlayer({
|
||||
videoRef: refs.videoRef,
|
||||
src,
|
||||
autoPlay: shouldAutoPlay
|
||||
});
|
||||
|
||||
const {
|
||||
videoRef,
|
||||
containerRef,
|
||||
@@ -71,7 +79,6 @@ export function DesktopVideoPlayer({
|
||||
<video
|
||||
ref={videoRef}
|
||||
className="w-full h-full object-contain"
|
||||
src={src}
|
||||
poster={poster}
|
||||
x-webkit-airplay="allow"
|
||||
onPlay={handlePlay}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import Hls from 'hls.js';
|
||||
|
||||
interface UseHlsPlayerProps {
|
||||
videoRef: React.RefObject<HTMLVideoElement | null>;
|
||||
src: string;
|
||||
autoPlay?: boolean;
|
||||
onAutoPlayPrevented?: (error: Error) => void;
|
||||
}
|
||||
|
||||
export function useHlsPlayer({
|
||||
videoRef,
|
||||
src,
|
||||
autoPlay = false,
|
||||
onAutoPlayPrevented
|
||||
}: UseHlsPlayerProps) {
|
||||
const hlsRef = useRef<Hls | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const video = videoRef.current;
|
||||
if (!video || !src) return;
|
||||
|
||||
// Cleanup previous HLS instance
|
||||
if (hlsRef.current) {
|
||||
hlsRef.current.destroy();
|
||||
hlsRef.current = null;
|
||||
}
|
||||
|
||||
let hls: Hls | null = null;
|
||||
|
||||
// Check if HLS is supported natively (Safari, Mobile Chrome)
|
||||
// We prefer native playback if available as it's usually more battery efficient
|
||||
const isNativeHlsSupported = video.canPlayType('application/vnd.apple.mpegurl');
|
||||
|
||||
if (Hls.isSupported()) {
|
||||
// Use hls.js for browsers without native support (Desktop Chrome, Firefox, Edge)
|
||||
// OR if we want to force hls.js for better control (optional, but sticking to native first is safer)
|
||||
|
||||
// Note: Some desktop browsers (like Safari) support native HLS.
|
||||
// We usually prefer native, BUT sometimes native implementation is buggy or lacks features.
|
||||
// For now, we follow the standard pattern: Native first, then HLS.js.
|
||||
// EXCEPT for Chrome on Desktop which reports canPlayType as '' (false).
|
||||
|
||||
if (!isNativeHlsSupported) {
|
||||
console.log('[HLS] Initializing hls.js');
|
||||
hls = new Hls({
|
||||
enableWorker: true,
|
||||
lowLatencyMode: true,
|
||||
});
|
||||
hlsRef.current = hls;
|
||||
|
||||
hls.loadSource(src);
|
||||
hls.attachMedia(video);
|
||||
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||
console.log('[HLS] Manifest parsed');
|
||||
if (autoPlay) {
|
||||
video.play().catch((err) => {
|
||||
console.warn('[HLS] Autoplay prevented:', err);
|
||||
onAutoPlayPrevented?.(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
hls.on(Hls.Events.ERROR, (event, data) => {
|
||||
if (data.fatal) {
|
||||
switch (data.type) {
|
||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||
console.error('[HLS] Network error, trying to recover...');
|
||||
hls?.startLoad();
|
||||
break;
|
||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||
console.error('[HLS] Media error, trying to recover...');
|
||||
hls?.recoverMediaError();
|
||||
break;
|
||||
default:
|
||||
console.error('[HLS] Fatal error, cannot recover:', data);
|
||||
hls?.destroy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('[HLS] Using native HLS support');
|
||||
// Native HLS support
|
||||
video.src = src;
|
||||
}
|
||||
} else if (isNativeHlsSupported) {
|
||||
// Fallback for environments where Hls.js is not supported but native is (e.g. iOS without MSE?)
|
||||
console.log('[HLS] Using native HLS support (Hls.js not supported)');
|
||||
video.src = src;
|
||||
} else {
|
||||
console.error('[HLS] HLS not supported in this browser');
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (hls) {
|
||||
hls.destroy();
|
||||
}
|
||||
};
|
||||
}, [src, videoRef, autoPlay, onAutoPlayPrevented]);
|
||||
}
|
||||
Reference in New Issue
Block a user