From 7da9ab00b18d682afd6170cd859b7fab3bd02a3a Mon Sep 17 00:00:00 2001 From: Autli Date: Thu, 29 Oct 2026 15:48:39 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B2=D0=B8=D0=B4=D0=B5=D0=BE=D0=BF=D0=BB=D0=B5=D0=B5?= =?UTF-8?q?=D1=80=D0=BE=D0=BC=20=D0=B8=20=D0=B3=D1=80=D0=BE=D0=BC=D0=BA?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Автоматическая установка громкости на 100% при запуске плеера - Постоянный мониторинг громкости каждые 2 секунды во время воспроизведения - Усиление надежности команд Play/Pause/Seek (тройная отправка с задержками) - Улучшенная перемотка ±10 секунд для всех типов плееров - Поддержка громкости для нативного HTML5 видео (AniLibria) - Агрессивная установка громкости в первые 15 секунд после загрузки iframe Co-Authored-By: Claude --- src/pages/cinema/Cinema.tsx | 150 +++++++++++++++++++++++------------- 1 file changed, 95 insertions(+), 55 deletions(-) diff --git a/src/pages/cinema/Cinema.tsx b/src/pages/cinema/Cinema.tsx index 73ec328..a4d9436 100644 --- a/src/pages/cinema/Cinema.tsx +++ b/src/pages/cinema/Cinema.tsx @@ -697,34 +697,39 @@ export default function Cinema({ const isPlay = command === "play"; const isToggle = command === "toggle"; - // 1. Kodik Player API (Supports both object and stringified commands) - broadcastToWindowTree({ key: "kodik_player_api", value: { method: isToggle ? "toggle" : (isPlay ? "play" : "pause") } }); - if (!isToggle) { - broadcastToWindowTree({ key: "kodik_player_api", value: { method: isPlay ? "play" : "pause" } }); + // Отправляем команды многократно для надежности (разные плееры реагируют в разное время) + for (let i = 0; i < 3; i++) { + setTimeout(() => { + // 1. Kodik Player API (Supports both object and stringified commands) + broadcastToWindowTree({ key: "kodik_player_api", value: { method: isToggle ? "toggle" : (isPlay ? "play" : "pause") } }); + if (!isToggle) { + broadcastToWindowTree({ key: "kodik_player_api", value: { method: isPlay ? "play" : "pause" } }); + } + + // 2. Playerjs API (Used by Alloha, Kinoplay, Collaps, VideoCDN, Ashdi, HDRezka) + broadcastToWindowTree({ api: isToggle ? "toggle" : (isPlay ? "play" : "pause") }); + if (!isToggle) { + broadcastToWindowTree({ api: isPlay ? "play" : "pause" }); + } + + // 3. Alloha API + broadcastToWindowTree({ action: isPlay ? "play" : "pause" }); + broadcastToWindowTree({ method: isPlay ? "play" : "pause" }); + + // 4. VidLink Pro / Video.js API + broadcastToWindowTree({ type: isPlay ? "PLAYER_PLAY" : "PLAYER_PAUSE" }); + broadcastToWindowTree({ type: isPlay ? "play" : "pause" }); + broadcastToWindowTree({ action: isPlay ? "play" : "pause" }); + broadcastToWindowTree({ event: isPlay ? "play" : "pause" }); + + // 5. YouTube / VidSrc / AutoEmbed HTML5 API + broadcastToWindowTree({ event: "command", func: isPlay ? "playVideo" : "pauseVideo", args: "" }); + + // 6. Generic HTML5 postMessage + broadcastToWindowTree({ method: isPlay ? "play" : "pause" }); + broadcastToWindowTree({ command: isPlay ? "play" : "pause" }); + }, i * 100); } - - // 2. Playerjs API (Used by Alloha, Kinoplay, Collaps, VideoCDN, Ashdi, HDRezka) - broadcastToWindowTree({ api: isToggle ? "toggle" : (isPlay ? "play" : "pause") }); - if (!isToggle) { - broadcastToWindowTree({ api: isPlay ? "play" : "pause" }); - } - - // 3. Alloha API - broadcastToWindowTree({ action: isPlay ? "play" : "pause" }); - broadcastToWindowTree({ method: isPlay ? "play" : "pause" }); - - // 4. VidLink Pro / Video.js API - broadcastToWindowTree({ type: isPlay ? "PLAYER_PLAY" : "PLAYER_PAUSE" }); - broadcastToWindowTree({ type: isPlay ? "play" : "pause" }); - broadcastToWindowTree({ action: isPlay ? "play" : "pause" }); - broadcastToWindowTree({ event: isPlay ? "play" : "pause" }); - - // 5. YouTube / VidSrc / AutoEmbed HTML5 API - broadcastToWindowTree({ event: "command", func: isPlay ? "playVideo" : "pauseVideo", args: "" }); - - // 6. Generic HTML5 postMessage - broadcastToWindowTree({ method: isPlay ? "play" : "pause" }); - broadcastToWindowTree({ command: isPlay ? "play" : "pause" }); }, [broadcastToWindowTree]); const setPlayerVolumeMax = useCallback((showToast: boolean = false) => { @@ -802,7 +807,10 @@ export default function Cinema({ }, 120); } } + // Установка громкости 100% каждый раз при воспроизведении setPlayerVolumeMax(false); + setTimeout(() => setPlayerVolumeMax(false), 500); + setTimeout(() => setPlayerVolumeMax(false), 1500); setIsPlayingState(true); showTvToast("Воспроизведение", "▶", 1200); }, [sendIframePlaybackCommand, setPlayerVolumeMax, showTvToast]); @@ -846,39 +854,44 @@ export default function Cinema({ const targetTime = Math.max(0, curTime + secondsDelta); currentPlaybackRef.current.currentTime = targetTime; - // 1. Kodik API (Seek to absolute seconds & relative seek delta) - broadcastToWindowTree({ key: "kodik_player_api", value: { method: "seek", time: targetTime } }); - broadcastToWindowTree({ key: "kodik_player_api", value: { method: "seek_delta", time: secondsDelta } }); - broadcastToWindowTree({ key: "kodik_player_api", value: { method: secondsDelta > 0 ? "forward" : "rewind", time: Math.abs(secondsDelta) } }); + // Отправляем команды перемотки несколько раз для надежности + for (let i = 0; i < 3; i++) { + setTimeout(() => { + // 1. Kodik API (Seek to absolute seconds & relative seek delta) + broadcastToWindowTree({ key: "kodik_player_api", value: { method: "seek", time: targetTime } }); + broadcastToWindowTree({ key: "kodik_player_api", value: { method: "seek_delta", time: secondsDelta } }); + broadcastToWindowTree({ key: "kodik_player_api", value: { method: secondsDelta > 0 ? "forward" : "rewind", time: Math.abs(secondsDelta) } }); - // 2. Playerjs API (Used by Alloha, Kinoplay, Collaps, VideoCDN, Ashdi, HDRezka) - broadcastToWindowTree({ api: "seek", set: targetTime }); - broadcastToWindowTree({ api: "seek", set: secondsDelta > 0 ? `+${secondsDelta}` : `${secondsDelta}` }); - broadcastToWindowTree({ api: "seek", time: targetTime }); - broadcastToWindowTree({ api: "seek", delta: secondsDelta }); - broadcastToWindowTree({ api: "seek_delta", time: secondsDelta }); + // 2. Playerjs API (Used by Alloha, Kinoplay, Collaps, VideoCDN, Ashdi, HDRezka) + broadcastToWindowTree({ api: "seek", set: targetTime }); + broadcastToWindowTree({ api: "seek", set: secondsDelta > 0 ? `+${secondsDelta}` : `${secondsDelta}` }); + broadcastToWindowTree({ api: "seek", time: targetTime }); + broadcastToWindowTree({ api: "seek", delta: secondsDelta }); + broadcastToWindowTree({ api: "seek_delta", time: secondsDelta }); - // 3. Alloha API - broadcastToWindowTree({ action: "seek", time: targetTime }); - broadcastToWindowTree({ action: "seek", delta: secondsDelta }); - broadcastToWindowTree({ method: "seek", time: targetTime }); - broadcastToWindowTree({ method: "seekTo", value: targetTime }); + // 3. Alloha API + broadcastToWindowTree({ action: "seek", time: targetTime }); + broadcastToWindowTree({ action: "seek", delta: secondsDelta }); + broadcastToWindowTree({ method: "seek", time: targetTime }); + broadcastToWindowTree({ method: "seekTo", value: targetTime }); - // 4. VidLink Pro / Video.js API - broadcastToWindowTree({ type: "SEEK", data: { time: targetTime } }); - broadcastToWindowTree({ type: "PLAYER_SEEK", time: targetTime }); - broadcastToWindowTree({ type: "seek", time: targetTime }); - broadcastToWindowTree({ action: "seek", time: targetTime }); - broadcastToWindowTree({ action: "seek", delta: secondsDelta }); + // 4. VidLink Pro / Video.js API + broadcastToWindowTree({ type: "SEEK", data: { time: targetTime } }); + broadcastToWindowTree({ type: "PLAYER_SEEK", time: targetTime }); + broadcastToWindowTree({ type: "seek", time: targetTime }); + broadcastToWindowTree({ action: "seek", time: targetTime }); + broadcastToWindowTree({ action: "seek", delta: secondsDelta }); - // 5. YouTube / VidSrc / AutoEmbed HTML5 API - broadcastToWindowTree({ event: "command", func: "seekTo", args: [targetTime, true] }); - broadcastToWindowTree({ event: "command", func: "seek", args: [targetTime] }); - broadcastToWindowTree({ action: "seekTo", value: targetTime }); + // 5. YouTube / VidSrc / AutoEmbed HTML5 API + broadcastToWindowTree({ event: "command", func: "seekTo", args: [targetTime, true] }); + broadcastToWindowTree({ event: "command", func: "seek", args: [targetTime] }); + broadcastToWindowTree({ action: "seekTo", value: targetTime }); - // 6. Generic HTML5 postMessage - broadcastToWindowTree({ method: "seek", time: targetTime }); - broadcastToWindowTree({ command: "seek", time: targetTime }); + // 6. Generic HTML5 postMessage + broadcastToWindowTree({ method: "seek", time: targetTime }); + broadcastToWindowTree({ command: "seek", time: targetTime }); + }, i * 100); + } } showTvToast(secondsDelta > 0 ? `+${secondsDelta} сек` : `${secondsDelta} сек`, secondsDelta > 0 ? "⏩" : "⏪", 1000); }, [broadcastToWindowTree, showTvToast]); @@ -1684,6 +1697,11 @@ export default function Cinema({ setTimeout(() => { setPlayerVolumeMax(false); }, 4500); + // Агрессивная установка громкости каждые 3 секунды (первые 15 секунд) + const volumeInterval = setInterval(() => { + setPlayerVolumeMax(false); + }, 3000); + setTimeout(() => clearInterval(volumeInterval), 15000); }, [sendIframePlaybackCommand, setPlayerVolumeMax]); // Start playback for a media item (movie or specific series episode) @@ -1976,6 +1994,16 @@ export default function Cinema({ const activeMedia = playingMedia || selectedMedia; currentPlaybackRef.current = { currentTime, duration }; + // Постоянно поддерживаем громкость на 100% для нативного видео + try { + if (videoRef.current.volume !== 1.0) { + videoRef.current.volume = 1.0; + } + if (videoRef.current.muted) { + videoRef.current.muted = false; + } + } catch {} + if (duration > 0 && isTauri) { const payload: CinemaPlayback = { title_id: activeMedia.id, @@ -2119,6 +2147,18 @@ export default function Cinema({ return () => clearInterval(interval); }, [playingEpisode, playerMode, allMirrorsFailed, playingMedia, selectedMedia, playingSeasonNumber, isTauri, currentUser?.email]); + // Постоянный мониторинг и поддержание громкости на 100% во время воспроизведения + useEffect(() => { + if (!playingEpisode) return; + + // Устанавливаем громкость каждые 2 секунды во время воспроизведения + const volumeKeeper = setInterval(() => { + setPlayerVolumeMax(false); + }, 2000); + + return () => clearInterval(volumeKeeper); + }, [playingEpisode, setPlayerVolumeMax]); + // Listen to postMessage from embedded players (VidLink, Kodik, Alloha) useEffect(() => { const handleWindowMessage = (e: MessageEvent) => {