修正切视频同步逻辑
This commit is contained in:
@@ -1594,6 +1594,63 @@ function PlayPageClient() {
|
|||||||
initSkipConfig();
|
initSkipConfig();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// 监听 URL 参数变化,处理换源和换视频(用于房员跟随房主操作)
|
||||||
|
useEffect(() => {
|
||||||
|
const urlSource = searchParams.get('source');
|
||||||
|
const urlId = searchParams.get('id');
|
||||||
|
|
||||||
|
// 只在URL参数存在且与当前状态不同时才处理
|
||||||
|
if (urlSource && urlId && (urlSource !== currentSource || urlId !== currentId)) {
|
||||||
|
console.log('[PlayPage] Detected source/id change from URL:', {
|
||||||
|
urlSource,
|
||||||
|
urlId,
|
||||||
|
currentSource,
|
||||||
|
currentId
|
||||||
|
});
|
||||||
|
|
||||||
|
// 检查新的source和id是否在可用源列表中
|
||||||
|
const targetSource = availableSources.find(
|
||||||
|
(source) => source.source === urlSource && source.id === urlId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (targetSource) {
|
||||||
|
console.log('[PlayPage] Found matching source in available sources, updating...');
|
||||||
|
|
||||||
|
// 记录当前播放进度
|
||||||
|
const currentPlayTime = artPlayerRef.current?.currentTime || 0;
|
||||||
|
|
||||||
|
// 获取URL中的episode参数
|
||||||
|
const episodeParam = searchParams.get('episode');
|
||||||
|
const targetEpisode = episodeParam ? parseInt(episodeParam, 10) - 1 : 0;
|
||||||
|
|
||||||
|
// 更新视频源信息
|
||||||
|
setCurrentSource(urlSource);
|
||||||
|
setCurrentId(urlId);
|
||||||
|
setVideoTitle(targetSource.title);
|
||||||
|
setVideoYear(targetSource.year);
|
||||||
|
setVideoCover(targetSource.poster);
|
||||||
|
setVideoDoubanId(targetSource.douban_id || 0);
|
||||||
|
setDetail(targetSource);
|
||||||
|
|
||||||
|
// 更新集数
|
||||||
|
if (targetEpisode >= 0 && targetEpisode < targetSource.episodes.length) {
|
||||||
|
setCurrentEpisodeIndex(targetEpisode);
|
||||||
|
|
||||||
|
// 如果是同一集,保存播放进度以便恢复
|
||||||
|
if (targetEpisode === currentEpisodeIndex && currentPlayTime > 1) {
|
||||||
|
resumeTimeRef.current = currentPlayTime;
|
||||||
|
} else {
|
||||||
|
resumeTimeRef.current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('[PlayPage] Source not found in available sources, reloading page...');
|
||||||
|
// 如果新源不在可用列表中,强制刷新页面重新加载
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [searchParams, currentSource, currentId, availableSources, currentEpisodeIndex]);
|
||||||
|
|
||||||
// 处理换源
|
// 处理换源
|
||||||
const handleSourceChange = async (
|
const handleSourceChange = async (
|
||||||
newSource: string,
|
newSource: string,
|
||||||
|
|||||||
@@ -248,8 +248,8 @@ export function usePlaySync({
|
|||||||
const url = `/play?${params.toString()}`;
|
const url = `/play?${params.toString()}`;
|
||||||
console.log('[PlaySync] Member redirecting to:', url);
|
console.log('[PlaySync] Member redirecting to:', url);
|
||||||
|
|
||||||
// 使用 window.location.href 强制完整刷新页面,确保播放器重新加载
|
// 使用 router.push 进行导航,支持在同一页面更新参数
|
||||||
window.location.href = url;
|
router.push(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.on('play:update', handlePlayUpdate);
|
socket.on('play:update', handlePlayUpdate);
|
||||||
@@ -367,18 +367,45 @@ export function usePlaySync({
|
|||||||
};
|
};
|
||||||
}, [socket, currentRoom, artPlayerRef, watchRoom, broadcastPlayState, isInRoom, playerReady]);
|
}, [socket, currentRoom, artPlayerRef, watchRoom, broadcastPlayState, isInRoom, playerReady]);
|
||||||
|
|
||||||
|
// 使用ref跟踪上一次的值,用于检测真正的变化
|
||||||
|
const lastBroadcastRef = useRef<{
|
||||||
|
videoId: string;
|
||||||
|
source: string;
|
||||||
|
episode: number;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
// 房主:监听视频/集数/源变化并广播
|
// 房主:监听视频/集数/源变化并广播
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOwner || !socket || !currentRoom || !isInRoom || !watchRoom) return;
|
if (!isOwner || !socket || !currentRoom || !isInRoom || !watchRoom) {
|
||||||
|
// 如果不是房主或不在房间,重置跟踪
|
||||||
|
lastBroadcastRef.current = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!videoId || !videoUrl) return;
|
if (!videoId || !videoUrl) return;
|
||||||
|
|
||||||
console.log('[PlaySync] Video params changed, will broadcast after delay:', {
|
const currentState = {
|
||||||
videoId,
|
videoId,
|
||||||
currentSource,
|
source: currentSource,
|
||||||
currentEpisode
|
episode: currentEpisode || 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 检查是否需要广播
|
||||||
|
const shouldBroadcast = !lastBroadcastRef.current ||
|
||||||
|
lastBroadcastRef.current.videoId !== currentState.videoId ||
|
||||||
|
lastBroadcastRef.current.source !== currentState.source ||
|
||||||
|
lastBroadcastRef.current.episode !== currentState.episode;
|
||||||
|
|
||||||
|
if (!shouldBroadcast) {
|
||||||
|
console.log('[PlaySync] No change detected, skipping broadcast');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[PlaySync] Detected change, will broadcast:', {
|
||||||
|
from: lastBroadcastRef.current,
|
||||||
|
to: currentState
|
||||||
});
|
});
|
||||||
|
|
||||||
// 延迟广播,避免初始化时触发
|
// 延迟广播,确保页面已经稳定
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
const state: PlayState = {
|
const state: PlayState = {
|
||||||
type: 'play',
|
type: 'play',
|
||||||
@@ -395,10 +422,66 @@ export function usePlaySync({
|
|||||||
|
|
||||||
console.log('[PlaySync] Broadcasting play:change:', state);
|
console.log('[PlaySync] Broadcasting play:change:', state);
|
||||||
watchRoom.changeVideo(state);
|
watchRoom.changeVideo(state);
|
||||||
}, 1000); // 1秒延迟,给页面足够时间初始化
|
|
||||||
|
// 更新跟踪值
|
||||||
|
lastBroadcastRef.current = currentState;
|
||||||
|
}, 500); // 减少延迟到500ms
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, [isOwner, socket, currentRoom, isInRoom, watchRoom, videoId, currentEpisode, currentSource]);
|
}, [isOwner, socket, currentRoom, isInRoom, watchRoom, videoId, currentEpisode, currentSource, videoUrl, videoName, videoYear, searchTitle, artPlayerRef]);
|
||||||
|
|
||||||
|
// 房主:加入房间时立即广播当前播放状态
|
||||||
|
const lastRoomStateRef = useRef<{ isOwner: boolean; roomId: string | null }>({ isOwner: false, roomId: null });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const currentRoomId = currentRoom?.id || null;
|
||||||
|
const prevRoomState = lastRoomStateRef.current;
|
||||||
|
|
||||||
|
// 检测是否刚成为房主或刚加入房间
|
||||||
|
const justBecameOwner = !prevRoomState.isOwner && isOwner;
|
||||||
|
const justJoinedRoom = !prevRoomState.roomId && currentRoomId;
|
||||||
|
|
||||||
|
// 更新ref
|
||||||
|
lastRoomStateRef.current = { isOwner, roomId: currentRoomId };
|
||||||
|
|
||||||
|
if (!isOwner || !socket || !currentRoom || !isInRoom || !watchRoom) return;
|
||||||
|
if (!videoId || !videoUrl) return;
|
||||||
|
if (!justBecameOwner && !justJoinedRoom) return;
|
||||||
|
|
||||||
|
console.log('[PlaySync] Owner joined room, broadcasting current state immediately:', {
|
||||||
|
justBecameOwner,
|
||||||
|
justJoinedRoom
|
||||||
|
});
|
||||||
|
|
||||||
|
// 立即广播当前状态
|
||||||
|
const state: PlayState = {
|
||||||
|
type: 'play',
|
||||||
|
url: videoUrl,
|
||||||
|
currentTime: artPlayerRef.current?.currentTime || 0,
|
||||||
|
isPlaying: artPlayerRef.current?.playing || false,
|
||||||
|
videoId,
|
||||||
|
videoName,
|
||||||
|
videoYear,
|
||||||
|
searchTitle,
|
||||||
|
episode: currentEpisode,
|
||||||
|
source: currentSource,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 短暂延迟确保房间连接已稳定
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
console.log('[PlaySync] Broadcasting play:change on room join:', state);
|
||||||
|
watchRoom.changeVideo(state);
|
||||||
|
|
||||||
|
// 同时更新跟踪值,避免立即重复广播
|
||||||
|
lastBroadcastRef.current = {
|
||||||
|
videoId,
|
||||||
|
source: currentSource,
|
||||||
|
episode: currentEpisode || 1,
|
||||||
|
};
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [isOwner, currentRoom, socket, isInRoom, watchRoom, videoId, videoUrl, videoName, videoYear, searchTitle, currentEpisode, currentSource, artPlayerRef]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isInRoom,
|
isInRoom,
|
||||||
|
|||||||
Reference in New Issue
Block a user