This commit is contained in:
parent
33624d3b02
commit
896a3b77d7
5 changed files with 293 additions and 85 deletions
|
|
@ -22,8 +22,11 @@
|
|||
let lastSeekTime = 0; // Track last seek time for rate-limiting
|
||||
let leadInEndedAt = 0; // Track when lead-in ended for grace period
|
||||
let wasInLeadIn = false; // Track previous lead-in state
|
||||
let restartInProgress = false; // Track when video restart is in progress (prevents drift detection)
|
||||
let restartStartedAt = 0; // When restart started
|
||||
|
||||
const SYNC_CHECK_INTERVAL = 1000; // Check sync every second (matches server sync interval)
|
||||
const RESTART_GRACE_PERIOD = 3000; // 3 seconds grace period during video restart
|
||||
const DRIFT_THRESHOLD = 2; // Seek if drift > 2 seconds (CyTube-style tight sync)
|
||||
const MIN_SYNC_INTERVAL = 1000; // Minimum 1 second between sync checks (server pushes every 1s)
|
||||
const CONTROLLER_SEEK_DEBOUNCE = 2000; // Debounce controller seeks by 2 seconds
|
||||
|
|
@ -122,6 +125,9 @@
|
|||
// YT.PlayerState: UNSTARTED (-1), ENDED (0), PLAYING (1), PAUSED (2), BUFFERING (3), CUED (5)
|
||||
// Always handle ENDED state - crucial for playlist advancement
|
||||
if (state === window.YT.PlayerState.ENDED) {
|
||||
// Set restart flag to prevent drift detection during transition
|
||||
restartInProgress = true;
|
||||
restartStartedAt = Date.now();
|
||||
dispatch('ended');
|
||||
// Also notify server directly - this is a fallback for when duration-based detection fails
|
||||
watchSync.videoEnded();
|
||||
|
|
@ -187,10 +193,29 @@
|
|||
const shouldBePlaying = storeState.playbackState === 'playing';
|
||||
const hasVideoEnded = playerState === window.YT.PlayerState.ENDED;
|
||||
|
||||
// During restart transition (video ended, waiting for server response), skip drift detection
|
||||
// This prevents false "Controller seek detected" when video loops/restarts
|
||||
if (restartInProgress) {
|
||||
if (now - restartStartedAt >= RESTART_GRACE_PERIOD) {
|
||||
// Grace period expired, reset flag
|
||||
restartInProgress = false;
|
||||
} else {
|
||||
// Still in grace period - only ensure video starts playing if needed, no sync
|
||||
if (shouldBePlaying && !isPlayerPlaying && !isBuffering && !hasVideoEnded) {
|
||||
ignoreStateChange = true;
|
||||
player.playVideo();
|
||||
setTimeout(() => { ignoreStateChange = false; }, 1500);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// During lead-in period, let video buffer without seeking
|
||||
// Server sends leadIn=true for 3 seconds after play starts
|
||||
if (storeState.leadIn) {
|
||||
wasInLeadIn = true;
|
||||
// Lead-in started, clear restart flag since server has responded
|
||||
restartInProgress = false;
|
||||
// During lead-in, just ensure video is loading/buffering
|
||||
// Don't seek or sync position - wait for lead-in to complete
|
||||
if (shouldBePlaying && !isPlayerPlaying && !isBuffering && !hasVideoEnded) {
|
||||
|
|
@ -266,6 +291,7 @@
|
|||
$: if (playerReady && $watchSync.currentVideo?.id !== currentPlaylistItemId) {
|
||||
currentPlaylistItemId = $watchSync.currentVideo?.id;
|
||||
durationReportedForItemId = null; // Reset so we report duration for new video
|
||||
restartInProgress = false; // Video changed, clear restart flag
|
||||
const newVideoId = $watchSync.currentVideo?.youtubeVideoId;
|
||||
if (newVideoId && player) {
|
||||
videoId = newVideoId;
|
||||
|
|
@ -302,13 +328,18 @@
|
|||
} else if (action === 'seek' && currentTime !== undefined) {
|
||||
player.seekTo(currentTime, true);
|
||||
} else if (action === 'skip' || action === 'video_changed') {
|
||||
// Server has responded, clear restart flag
|
||||
restartInProgress = false;
|
||||
// Video change will be handled by the reactive statement above
|
||||
setTimeout(() => checkAndSync(true), 1000);
|
||||
} else if (action === 'locked_restart' || action === 'repeat') {
|
||||
// Server has responded with restart, clear the restart flag
|
||||
restartInProgress = false;
|
||||
// Locked video loop - seek to beginning and play
|
||||
player.seekTo(0, true);
|
||||
player.playVideo();
|
||||
setTimeout(() => checkAndSync(true), 1000);
|
||||
// Delay sync check longer to allow player to stabilize
|
||||
setTimeout(() => checkAndSync(true), 2000);
|
||||
}
|
||||
|
||||
setTimeout(() => { ignoreStateChange = false; }, 1000);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue