From 31deeae53fa76445b4bf58bee5f02eac2468db5d Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Wed, 12 Feb 2025 18:32:31 +0900 Subject: [PATCH] [Update] Support ASS format file. and show actor combine with text. --- .../plugins_section/PluginsSection.jsx | 131 +++++++++++++----- 1 file changed, 96 insertions(+), 35 deletions(-) diff --git a/src-ui/app/main_page/plugins_section/PluginsSection.jsx b/src-ui/app/main_page/plugins_section/PluginsSection.jsx index 7925c4d5..84d966a2 100644 --- a/src-ui/app/main_page/plugins_section/PluginsSection.jsx +++ b/src-ui/app/main_page/plugins_section/PluginsSection.jsx @@ -14,8 +14,8 @@ export const PluginsSection = () => { const [targetHour, setTargetHour] = useState("19"); const [targetMinute, setTargetMinute] = useState("00"); - // カウントダウンの状態 - // initialCountdown: 開始ボタン押下時に計算される元の残り秒数 + // カウントダウン状態 + // initialCountdown: 再生開始ボタン押下時に算出される元の残り秒数 const [initialCountdown, setInitialCountdown] = useState(null); // countdownAdjustment: ユーザーが上下ボタンで調整する値(秒単位) const [countdownAdjustment, setCountdownAdjustment] = useState(0); @@ -24,12 +24,12 @@ export const PluginsSection = () => { // cuesScheduled: 字幕タイマーが一度スケジュールされたか const [cuesScheduled, setCuesScheduled] = useState(false); - // setTimeout/setInterval のタイマーID管理用 + // タイマー(setTimeout/setInterval)のID管理用 const timersRef = useRef([]); // ファイル入力リセット用の ref const fileInputRef = useRef(null); - // ファイルアップロード処理 + // ファイルアップロード時の処理 const handleFileUpload = (event) => { const file = event.target.files[0]; if (!file) return; @@ -37,9 +37,15 @@ export const PluginsSection = () => { reader.onload = (e) => { const content = e.target.result; setSrtContent(content); - const parsedCues = parseSRT(content); + let parsedCues = []; + // 拡張子により ASS と SRT を判定 + if (file.name.toLowerCase().endsWith(".ass")) { + parsedCues = parseASS(content); + } else { + parsedCues = parseSRT(content); + } setCues(parsedCues); - console.log("パース結果:", parsedCues); + console.log("Parsed cues:", parsedCues); if (fileInputRef.current) { fileInputRef.current.value = ""; } @@ -49,14 +55,20 @@ export const PluginsSection = () => { // 字幕開始時の処理 const startFunction = (cue) => { - console.log(`字幕開始 (index: ${cue.index}): ${cue.text}`); - sendTextToOverlay(cue.text); + let send_text = ""; + if (cue.actor !== "") { + send_text = `[${cue.actor}] ${cue.text}`; + } else { + send_text = `${cue.text}`; + } + console.log(`字幕開始 (index: ${cue.index}) send_text:${send_text}`); + sendTextToOverlay(send_text); }; // 字幕終了時の処理 const endFunction = (cue) => { console.log(`字幕終了 (index: ${cue.index}): ${cue.text}`); - // 必要に応じて終了処理(例:テキストクリア) + // 必要に応じた終了処理(例:テキストクリア)を実装可能 // sendTextToOverlay(""); }; @@ -75,7 +87,7 @@ export const PluginsSection = () => { setCuesScheduled(false); }; - // cues のスケジュールを行う(offset は countdownAdjustment * 1000) + // cues のスケジュールを行う(字幕開始時のオフセットは countdownAdjustment * 1000) const scheduleCues = (offset) => { cues.forEach((cue) => { const startDelay = cue.startTime * 1000 + offset; @@ -93,7 +105,6 @@ export const PluginsSection = () => { // カウントダウンタイマーの開始 const startCountdownInterval = (initialValue) => { - // 初期表示は (initialValue + countdownAdjustment) setEffectiveCountdown(initialValue + countdownAdjustment); const countdownInterval = setInterval(() => { setEffectiveCountdown((prev) => { @@ -150,7 +161,8 @@ export const PluginsSection = () => { ) { sendTextToOverlay("Start."); console.log("Start."); - scheduleCues(0); + // オフセットは countdownAdjustment × 1000 を字幕に反映 + scheduleCues(countdownAdjustment * 1000); setCuesScheduled(true); } }, [effectiveCountdown, isPlaying, cuesScheduled, countdownAdjustment]); @@ -190,11 +202,11 @@ export const PluginsSection = () => {

字幕プレイヤー

{playbackMode === "absolute" && (
- +