import { useEffect, useRef } from "react"; import type { RefObject } from "react"; import { useRouter } from "next/navigation"; import type { LoopMode, Neighbors } from "../types"; interface UseVideoPlayerProps { awemeId: string; videoRef: RefObject; volume: number; rate: number; loopMode: LoopMode; neighbors: Neighbors; progressRestored: boolean; setIsPlaying: (playing: boolean) => void; setProgress: (progress: number) => void; setProgressRestored: (restored: boolean) => void; } export function useVideoPlayer({ awemeId, videoRef, volume, rate, loopMode, neighbors, progressRestored, setIsPlaying, setProgress, setProgressRestored, }: UseVideoPlayerProps) { const router = useRouter(); // 恢复播放进度 useEffect(() => { if (progressRestored) return; const v = videoRef.current; if (!v) return; const onLoadedMetadata = () => { if (progressRestored) return; try { const key = `aweme_progress_${awemeId}`; const saved = localStorage.getItem(key); if (!saved) { setProgressRestored(true); return; } const { time, timestamp } = JSON.parse(saved); const now = Date.now(); const fiveMinutes = 5 * 60 * 1000; if (now - timestamp < fiveMinutes && time > 1 && time < v.duration - 1) { v.currentTime = time; console.log(`恢复播放进度: ${Math.round(time)}s`); } else if (now - timestamp >= fiveMinutes) { localStorage.removeItem(key); } } catch (e) { console.error("恢复播放进度失败", e); } setProgressRestored(true); }; if (v.readyState >= 1) { onLoadedMetadata(); } else { v.addEventListener("loadedmetadata", onLoadedMetadata, { once: true }); return () => v.removeEventListener("loadedmetadata", onLoadedMetadata); } }, [awemeId, progressRestored, videoRef, setProgressRestored]); // 保存播放进度 useEffect(() => { const v = videoRef.current; if (!v) return; const saveProgress = () => { if (!v.duration || Number.isNaN(v.duration) || v.currentTime < 1) return; try { const key = `aweme_progress_${awemeId}`; const value = JSON.stringify({ time: v.currentTime, timestamp: Date.now(), }); localStorage.setItem(key, value); } catch (e) { console.error("保存播放进度失败", e); } }; const interval = setInterval(saveProgress, 2000); const onBeforeUnload = () => saveProgress(); window.addEventListener("beforeunload", onBeforeUnload); return () => { clearInterval(interval); window.removeEventListener("beforeunload", onBeforeUnload); saveProgress(); }; }, [awemeId, videoRef]); // 监听播放状态和进度 useEffect(() => { const v = videoRef.current; if (!v) return; const onTime = () => { if (!v.duration || Number.isNaN(v.duration)) return; setProgress(v.currentTime / v.duration); }; const onPlay = () => setIsPlaying(true); const onPause = () => setIsPlaying(false); const onEnded = () => { if (loopMode === "sequential" && neighbors?.next) { router.push(`/aweme/${neighbors.next.aweme_id}`); } }; v.addEventListener("timeupdate", onTime); v.addEventListener("loadedmetadata", onTime); v.addEventListener("play", onPlay); v.addEventListener("pause", onPause); v.addEventListener("ended", onEnded); return () => { v.removeEventListener("timeupdate", onTime); v.removeEventListener("loadedmetadata", onTime); v.removeEventListener("play", onPlay); v.removeEventListener("pause", onPause); v.removeEventListener("ended", onEnded); }; }, [loopMode, neighbors?.next, router, videoRef, setIsPlaying, setProgress]); // 自动播放检测 useEffect(() => { const v = videoRef.current; if (!v) return; const checkAutoplay = async () => { try { await v.play(); setIsPlaying(true); } catch (error) { console.log("自动播放被阻止,需要用户交互"); setIsPlaying(false); } }; if (v.readyState >= 1) { checkAutoplay(); } else { v.addEventListener("loadedmetadata", checkAutoplay, { once: true }); return () => v.removeEventListener("loadedmetadata", checkAutoplay); } }, [awemeId, videoRef, setIsPlaying]); // 更新音量和倍速 useEffect(() => { const v = videoRef.current; if (v) v.volume = volume; }, [volume, videoRef]); useEffect(() => { const v = videoRef.current; if (v) v.playbackRate = rate; }, [rate, videoRef]); }