Улучшить управление видеоплеером и громкостью

- Автоматическая установка громкости на 100% при запуске плеера
- Постоянный мониторинг громкости каждые 2 секунды во время воспроизведения
- Усиление надежности команд Play/Pause/Seek (тройная отправка с задержками)
- Улучшенная перемотка ±10 секунд для всех типов плееров
- Поддержка громкости для нативного HTML5 видео (AniLibria)
- Агрессивная установка громкости в первые 15 секунд после загрузки iframe

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Nikita 2026-10-29 15:48:39 +05:00
parent 2ab0457568
commit 7da9ab00b1

View file

@ -697,6 +697,9 @@ export default function Cinema({
const isPlay = command === "play"; const isPlay = command === "play";
const isToggle = command === "toggle"; const isToggle = command === "toggle";
// Отправляем команды многократно для надежности (разные плееры реагируют в разное время)
for (let i = 0; i < 3; i++) {
setTimeout(() => {
// 1. Kodik Player API (Supports both object and stringified commands) // 1. Kodik Player API (Supports both object and stringified commands)
broadcastToWindowTree({ key: "kodik_player_api", value: { method: isToggle ? "toggle" : (isPlay ? "play" : "pause") } }); broadcastToWindowTree({ key: "kodik_player_api", value: { method: isToggle ? "toggle" : (isPlay ? "play" : "pause") } });
if (!isToggle) { if (!isToggle) {
@ -725,6 +728,8 @@ export default function Cinema({
// 6. Generic HTML5 postMessage // 6. Generic HTML5 postMessage
broadcastToWindowTree({ method: isPlay ? "play" : "pause" }); broadcastToWindowTree({ method: isPlay ? "play" : "pause" });
broadcastToWindowTree({ command: isPlay ? "play" : "pause" }); broadcastToWindowTree({ command: isPlay ? "play" : "pause" });
}, i * 100);
}
}, [broadcastToWindowTree]); }, [broadcastToWindowTree]);
const setPlayerVolumeMax = useCallback((showToast: boolean = false) => { const setPlayerVolumeMax = useCallback((showToast: boolean = false) => {
@ -802,7 +807,10 @@ export default function Cinema({
}, 120); }, 120);
} }
} }
// Установка громкости 100% каждый раз при воспроизведении
setPlayerVolumeMax(false); setPlayerVolumeMax(false);
setTimeout(() => setPlayerVolumeMax(false), 500);
setTimeout(() => setPlayerVolumeMax(false), 1500);
setIsPlayingState(true); setIsPlayingState(true);
showTvToast("Воспроизведение", "▶", 1200); showTvToast("Воспроизведение", "▶", 1200);
}, [sendIframePlaybackCommand, setPlayerVolumeMax, showTvToast]); }, [sendIframePlaybackCommand, setPlayerVolumeMax, showTvToast]);
@ -846,6 +854,9 @@ export default function Cinema({
const targetTime = Math.max(0, curTime + secondsDelta); const targetTime = Math.max(0, curTime + secondsDelta);
currentPlaybackRef.current.currentTime = targetTime; currentPlaybackRef.current.currentTime = targetTime;
// Отправляем команды перемотки несколько раз для надежности
for (let i = 0; i < 3; i++) {
setTimeout(() => {
// 1. Kodik API (Seek to absolute seconds & relative seek delta) // 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", time: targetTime } });
broadcastToWindowTree({ key: "kodik_player_api", value: { method: "seek_delta", time: secondsDelta } }); broadcastToWindowTree({ key: "kodik_player_api", value: { method: "seek_delta", time: secondsDelta } });
@ -879,6 +890,8 @@ export default function Cinema({
// 6. Generic HTML5 postMessage // 6. Generic HTML5 postMessage
broadcastToWindowTree({ method: "seek", time: targetTime }); broadcastToWindowTree({ method: "seek", time: targetTime });
broadcastToWindowTree({ command: "seek", time: targetTime }); broadcastToWindowTree({ command: "seek", time: targetTime });
}, i * 100);
}
} }
showTvToast(secondsDelta > 0 ? `+${secondsDelta} сек` : `${secondsDelta} сек`, secondsDelta > 0 ? "⏩" : "⏪", 1000); showTvToast(secondsDelta > 0 ? `+${secondsDelta} сек` : `${secondsDelta} сек`, secondsDelta > 0 ? "⏩" : "⏪", 1000);
}, [broadcastToWindowTree, showTvToast]); }, [broadcastToWindowTree, showTvToast]);
@ -1684,6 +1697,11 @@ export default function Cinema({
setTimeout(() => { setTimeout(() => {
setPlayerVolumeMax(false); setPlayerVolumeMax(false);
}, 4500); }, 4500);
// Агрессивная установка громкости каждые 3 секунды (первые 15 секунд)
const volumeInterval = setInterval(() => {
setPlayerVolumeMax(false);
}, 3000);
setTimeout(() => clearInterval(volumeInterval), 15000);
}, [sendIframePlaybackCommand, setPlayerVolumeMax]); }, [sendIframePlaybackCommand, setPlayerVolumeMax]);
// Start playback for a media item (movie or specific series episode) // Start playback for a media item (movie or specific series episode)
@ -1976,6 +1994,16 @@ export default function Cinema({
const activeMedia = playingMedia || selectedMedia; const activeMedia = playingMedia || selectedMedia;
currentPlaybackRef.current = { currentTime, duration }; 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) { if (duration > 0 && isTauri) {
const payload: CinemaPlayback = { const payload: CinemaPlayback = {
title_id: activeMedia.id, title_id: activeMedia.id,
@ -2119,6 +2147,18 @@ export default function Cinema({
return () => clearInterval(interval); return () => clearInterval(interval);
}, [playingEpisode, playerMode, allMirrorsFailed, playingMedia, selectedMedia, playingSeasonNumber, isTauri, currentUser?.email]); }, [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) // Listen to postMessage from embedded players (VidLink, Kodik, Alloha)
useEffect(() => { useEffect(() => {
const handleWindowMessage = (e: MessageEvent) => { const handleWindowMessage = (e: MessageEvent) => {