"use client"; import React from "react"; import { useTranslations } from "next-intl"; import { toast } from "sonner"; import { Video, FileText } from "lucide-react"; import { useSrtPlayer } from "./hooks/useSrtPlayer"; import { useSubtitleSync } from "./hooks/useSubtitleSync"; import { useKeyboardShortcuts, createSrtPlayerShortcuts } from "./hooks/useKeyboardShortcuts"; import { useFileUpload } from "./hooks/useFileUpload"; import { loadSubtitle } from "./utils/subtitleParser"; import { VideoPlayer } from "./components/compounds/VideoPlayer"; import { SubtitleArea } from "./components/compounds/SubtitleArea"; import { ControlBar } from "./components/compounds/ControlBar"; import { UploadZone } from "./components/compounds/UploadZone"; import { SeekBar } from "./components/atoms/SeekBar"; import { LightButton } from "@/components/ui/buttons"; export default function SrtPlayerPage() { const t = useTranslations("home"); const srtT = useTranslations("srt_player"); const { uploadVideo, uploadSubtitle } = useFileUpload(); const { state, actions, videoRef, videoEventHandlers, subtitleActions } = useSrtPlayer(); // 字幕同步 useSubtitleSync( state.subtitle.data, state.video.currentTime, state.video.isPlaying, state.controls.autoPause, (subtitle) => { if (subtitle) { subtitleActions.setCurrentSubtitle(subtitle.text, subtitle.index); } else { subtitleActions.setCurrentSubtitle("", null); } }, (subtitle) => { // 自动暂停逻辑 actions.seek(subtitle.start); actions.pause(); } ); // 键盘快捷键 const shortcuts = React.useMemo(() => createSrtPlayerShortcuts( actions.togglePlayPause, actions.nextSubtitle, actions.previousSubtitle, actions.restartSubtitle, actions.toggleAutoPause ), [ actions.togglePlayPause, actions.nextSubtitle, actions.previousSubtitle, actions.restartSubtitle, actions.toggleAutoPause ] ); useKeyboardShortcuts(shortcuts); // 处理字幕文件加载 React.useEffect(() => { if (state.subtitle.url) { loadSubtitle(state.subtitle.url) .then(subtitleData => { subtitleActions.setSubtitleData(subtitleData); toast.success(srtT("subtitleLoadSuccess")); }) .catch(error => { toast.error(srtT("subtitleLoadFailed") + ": " + error.message); }); } }, [srtT, state.subtitle.url, subtitleActions]); // 处理进度条变化 const handleSeek = React.useCallback((index: number) => { if (state.subtitle.data[index]) { actions.seek(state.subtitle.data[index].start); } }, [state.subtitle.data, actions]); // 处理视频上传 const handleVideoUpload = React.useCallback(() => { uploadVideo(actions.setVideoUrl, (error) => { toast.error(srtT("videoUploadFailed") + ": " + error.message); }); }, [uploadVideo, actions.setVideoUrl, srtT]); // 处理字幕上传 const handleSubtitleUpload = React.useCallback(() => { uploadSubtitle(actions.setSubtitleUrl, (error) => { toast.error(srtT("subtitleUploadFailed") + ": " + error.message); }); }, [uploadSubtitle, actions.setSubtitleUrl, srtT]); // 检查是否可以播放 const canPlay = state.video.url && state.subtitle.url && state.subtitle.data.length > 0; return (
{/* 标题区域 */}

{t("srtPlayer.name")}

{t("srtPlayer.description")}

{/* 主要内容区域 */}
{/* 视频播放器区域 */}
{(!state.video.url || !state.subtitle.url || state.subtitle.data.length === 0) && (

{!state.video.url && !state.subtitle.url ? srtT("uploadVideoAndSubtitle") : !state.video.url ? srtT("uploadVideoFile") : !state.subtitle.url ? srtT("uploadSubtitleFile") : srtT("processingSubtitle") }

{(!state.video.url || !state.subtitle.url) && (

{srtT("needBothFiles")}

)}
)} {state.video.url && ( {state.subtitle.url && state.subtitle.data.length > 0 && ( )} )}
{/* 控制面板 */}
{/* 上传区域和状态指示器 */}
{state.video.url ? srtT("uploaded") : srtT("upload")}

{srtT("subtitleFile")}

{state.subtitle.url ? srtT("uploaded") : srtT("notUploaded")}

{state.subtitle.url ? srtT("uploaded") : srtT("upload")}
{/* 控制按钮和进度条 */}
{/* 控制按钮 */} {/* 进度条 */}
{/* 字幕进度显示 */}
{state.subtitle.currentIndex !== null ? `${state.subtitle.currentIndex + 1}/${state.subtitle.data.length}` : '0/0' }
{/* 播放速度显示 */} {state.video.playbackRate}x {/* 自动暂停状态 */} {srtT("autoPauseStatus", { enabled: state.controls.autoPause ? srtT("on") : srtT("off") })}
); }