refactor: Remove custom HLS preloading and segment downloading utilities, and relax HLS.js buffer settings for improved stability.

This commit is contained in:
kuekhaoyang
2025-12-24 15:39:43 +08:00
parent 01cbf10674
commit f847342cb5
7 changed files with 5 additions and 388 deletions
-5
View File
@@ -2,7 +2,6 @@
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';
@@ -25,10 +24,6 @@ export function DesktopVideoPlayer({
shouldAutoPlay = false
}: DesktopVideoPlayerProps) {
const { refs, state } = useDesktopPlayerState();
const { currentTime } = state;
// Preload HLS segments
useHLSPreloader({ src, currentTime, videoRef: refs.videoRef, isLoading: state.isLoading });
// Initialize HLS Player
useHlsPlayer({
-5
View File
@@ -4,7 +4,6 @@ import { useEffect } from 'react';
import { useScreenOrientation } from '@/lib/hooks/useMobilePlayer';
import { useMobilePlayerState } from './hooks/useMobilePlayerState';
import { useMobilePlayerLogic } from './hooks/useMobilePlayerLogic';
import { useHLSPreloader } from './hooks/useHLSPreloader';
import { useMobileGestures } from './hooks/useMobileGestures';
import { MobileControlsWrapper } from './mobile/MobileControlsWrapper';
import { MobileOverlay } from './mobile/MobileOverlay';
@@ -28,10 +27,6 @@ export function MobileVideoPlayer({
shouldAutoPlay = false
}: MobileVideoPlayerProps) {
const { refs, state } = useMobilePlayerState();
const { currentTime } = state;
// Preload HLS segments
useHLSPreloader({ src, currentTime, videoRef: refs.videoRef, isLoading: state.isLoading });
const {
videoRef,
@@ -1,88 +0,0 @@
import { useEffect, useRef, useState } from 'react';
import { parseHLSManifest, type Segment } from '@/lib/utils/hlsManifestParser';
import { preloadSegments } from '@/lib/utils/hls-downloader';
interface UseHLSPreloaderProps {
src: string;
currentTime: number;
videoRef: React.RefObject<HTMLVideoElement | null>;
isLoading: boolean;
}
export function useHLSPreloader({ src, currentTime, videoRef, isLoading }: UseHLSPreloaderProps) {
const abortControllerRef = useRef<AbortController | null>(null);
const segmentsRef = useRef<Segment[]>([]);
const [isManifestLoaded, setIsManifestLoaded] = useState(false);
const lastStartIndexRef = useRef<number>(-1);
const isInitializedRef = useRef(false);
const downloadTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const lastCurrentTimeRef = useRef<number>(0);
// Fetch and parse manifest when src changes
useEffect(() => {
if (!src || !src.endsWith('.m3u8')) return;
isInitializedRef.current = false;
lastStartIndexRef.current = -1;
const fetchManifest = async () => {
try {
// Fetch manifest
const segments = await parseHLSManifest(src);
segmentsRef.current = segments;
setIsManifestLoaded(true);
const totalDuration = segments[segments.length - 1]?.startTime + segments[segments.length - 1]?.duration || 0;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('503') || errorMessage.includes('Network unavailable')) {
console.warn('[Preloader] Network unavailable, skipping preload:', errorMessage);
} else {
console.error('[Preloader] Error fetching manifest:', error);
}
}
};
fetchManifest();
}, [src]);
// Manage downloads based on currentTime with debounce
useEffect(() => {
if (!isManifestLoaded || segmentsRef.current.length === 0) return;
if (isLoading) {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
abortControllerRef.current = null;
}
return;
}
if (downloadTimeoutRef.current) {
clearTimeout(downloadTimeoutRef.current);
}
downloadTimeoutRef.current = setTimeout(() => {
preloadSegments({
currentTime,
segments: segmentsRef.current,
videoRef,
lastStartIndexRef,
isInitializedRef,
abortControllerRef,
videoUrl: src
});
}, !isInitializedRef.current ? 100 : (Math.abs(currentTime - lastCurrentTimeRef.current) > 2 ? 2000 : 500));
lastCurrentTimeRef.current = currentTime;
}, [isManifestLoaded, currentTime, isLoading, videoRef, src]);
// Cleanup on unmount
useEffect(() => {
return () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
};
}, []);
}
+5 -6
View File
@@ -44,12 +44,11 @@ export function useHlsPlayer({
if (!isNativeHlsSupported) {
hls = new Hls({
enableWorker: true,
lowLatencyMode: true,
startFragPrefetch: true, // Fetch first segment immediately while parsing manifest
// Aggressively reduce buffering requirement for startup
maxBufferLength: 10,
maxMaxBufferLength: 20,
// Try to start playing as soon as we have enough data
lowLatencyMode: false, // Disable low latency for more stable playback
startFragPrefetch: false, // Don't prefetch - let browser handle buffering
// Use relaxed buffer settings
maxBufferLength: 30,
maxMaxBufferLength: 60,
fragLoadingMaxRetry: 3,
manifestLoadingMaxRetry: 3,
levelLoadingMaxRetry: 3,