mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-05-21 21:57:28 +08:00
fix: destroy MediaPlayer when source changing on webkit
This commit is contained in:
@@ -130,6 +130,12 @@ function PlayPageClient() {
|
|||||||
const currentIdRef = useRef(currentId);
|
const currentIdRef = useRef(currentId);
|
||||||
const videoTitleRef = useRef(videoTitle);
|
const videoTitleRef = useRef(videoTitle);
|
||||||
|
|
||||||
|
// 标记是否已触发过一次 sourcechange(首次不重建播放器)
|
||||||
|
const hasSourceChangedRef = useRef(false);
|
||||||
|
|
||||||
|
// 当播放器因重建而触发一次额外的 sourcechange 时,用于忽略那一次
|
||||||
|
const ignoreSourceChangeRef = useRef(false);
|
||||||
|
|
||||||
// 同步最新值到 refs
|
// 同步最新值到 refs
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
currentSourceRef.current = currentSource;
|
currentSourceRef.current = currentSource;
|
||||||
@@ -415,6 +421,7 @@ function PlayPageClient() {
|
|||||||
if (playerRef.current && !playerRef.current.paused) {
|
if (playerRef.current && !playerRef.current.paused) {
|
||||||
saveCurrentPlayProgress();
|
saveCurrentPlayProgress();
|
||||||
}
|
}
|
||||||
|
playerRef.current;
|
||||||
setCurrentEpisodeIndex(episodeIndex);
|
setCurrentEpisodeIndex(episodeIndex);
|
||||||
setShowEpisodePanel(false);
|
setShowEpisodePanel(false);
|
||||||
}
|
}
|
||||||
@@ -1041,6 +1048,9 @@ function PlayPageClient() {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Safari(WebKit) 专用:用于强制重新挂载 <MediaPlayer>,实现"销毁并重建"效果
|
||||||
|
const [playerReloadKey, setPlayerReloadKey] = useState(0);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className='min-h-[100dvh] bg-black flex items-center justify-center overflow-hidden overscroll-contain'>
|
<div className='min-h-[100dvh] bg-black flex items-center justify-center overflow-hidden overscroll-contain'>
|
||||||
@@ -1194,6 +1204,32 @@ function PlayPageClient() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSourceChange = () => {
|
||||||
|
// 仅在 WebKit(Safari)环境下重建播放器,解决部分资源切换后黑屏或无法播放的问题
|
||||||
|
const isWebkit =
|
||||||
|
typeof window !== 'undefined' &&
|
||||||
|
typeof (window as any).webkitConvertPointFromNodeToPage === 'function';
|
||||||
|
|
||||||
|
if (ignoreSourceChangeRef.current) {
|
||||||
|
// 这一次是由我们手动重建引起的,直接忽略
|
||||||
|
ignoreSourceChangeRef.current = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWebkit) {
|
||||||
|
// 第一次真实的 sourcechange,仅设置标记,不重建
|
||||||
|
if (!hasSourceChangedRef.current) {
|
||||||
|
hasSourceChangedRef.current = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第二次(用户真正切换源)开始重建播放器
|
||||||
|
// 设置标志,下一次由重建带来的 sourcechange 忽略
|
||||||
|
ignoreSourceChangeRef.current = true;
|
||||||
|
setPlayerReloadKey((k) => k + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={playerContainerRef}
|
ref={playerContainerRef}
|
||||||
@@ -1263,13 +1299,14 @@ function PlayPageClient() {
|
|||||||
autoPlay
|
autoPlay
|
||||||
crossOrigin='anonymous'
|
crossOrigin='anonymous'
|
||||||
controlsDelay={3000}
|
controlsDelay={3000}
|
||||||
keyDisabled
|
key={playerReloadKey}
|
||||||
onCanPlay={onCanPlay}
|
onCanPlay={onCanPlay}
|
||||||
onEnded={onEnded}
|
onEnded={onEnded}
|
||||||
onTimeUpdate={onTimeUpdate}
|
onTimeUpdate={onTimeUpdate}
|
||||||
onPause={saveCurrentPlayProgress}
|
onPause={saveCurrentPlayProgress}
|
||||||
onError={handlePlayerError}
|
onError={handlePlayerError}
|
||||||
onProviderChange={onProviderChange}
|
onProviderChange={onProviderChange}
|
||||||
|
onSourceChange={onSourceChange}
|
||||||
>
|
>
|
||||||
<MediaProvider />
|
<MediaProvider />
|
||||||
<PlayerUITopbar
|
<PlayerUITopbar
|
||||||
|
|||||||
Reference in New Issue
Block a user