mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-09 00:48:54 -05:00
fix: Chapters: Play should not stop at the end of a chapter or a cutaway area, but should just continue play through.
This commit is contained in:
parent
ee7fb7950c
commit
f67021b17b
@ -39,8 +39,6 @@ const App = () => {
|
||||
isMobile,
|
||||
videoInitialized,
|
||||
setVideoInitialized,
|
||||
isPlayingSegments,
|
||||
handlePlaySegments,
|
||||
} = useVideoChapters();
|
||||
|
||||
const handlePlay = () => {
|
||||
@ -52,156 +50,17 @@ const App = () => {
|
||||
if (isPlaying) {
|
||||
video.pause();
|
||||
setIsPlaying(false);
|
||||
logger.debug('Video paused');
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPosition = Number(video.currentTime.toFixed(6));
|
||||
|
||||
// Find the next stopping point based on current position
|
||||
let stopTime = duration;
|
||||
let currentSegment = null;
|
||||
let nextSegment = null;
|
||||
|
||||
// Sort segments by start time to ensure correct order
|
||||
const sortedSegments = [...clipSegments].sort((a, b) => a.startTime - b.startTime);
|
||||
|
||||
// First, check if we're inside a segment or exactly at its start/end
|
||||
currentSegment = sortedSegments.find((seg) => {
|
||||
const segStartTime = Number(seg.startTime.toFixed(6));
|
||||
const segEndTime = Number(seg.endTime.toFixed(6));
|
||||
|
||||
// Check if we're inside the segment
|
||||
if (currentPosition > segStartTime && currentPosition < segEndTime) {
|
||||
return true;
|
||||
}
|
||||
// Check if we're exactly at the start
|
||||
if (currentPosition === segStartTime) {
|
||||
return true;
|
||||
}
|
||||
// Check if we're exactly at the end
|
||||
if (currentPosition === segEndTime) {
|
||||
// If we're at the end of a segment, we should look for the next one
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// If we're not in a segment, find the next segment
|
||||
if (!currentSegment) {
|
||||
nextSegment = sortedSegments.find((seg) => {
|
||||
const segStartTime = Number(seg.startTime.toFixed(6));
|
||||
return segStartTime > currentPosition;
|
||||
});
|
||||
}
|
||||
|
||||
// Determine where to stop based on position
|
||||
if (currentSegment) {
|
||||
// If we're in a segment, stop at its end
|
||||
stopTime = Number(currentSegment.endTime.toFixed(6));
|
||||
} else if (nextSegment) {
|
||||
// If we're in a cutaway and there's a next segment, stop at its start
|
||||
stopTime = Number(nextSegment.startTime.toFixed(6));
|
||||
}
|
||||
|
||||
// Create a boundary checker function with high precision
|
||||
const checkBoundary = () => {
|
||||
if (!video) return;
|
||||
|
||||
const currentPosition = Number(video.currentTime.toFixed(6));
|
||||
const timeLeft = Number((stopTime - currentPosition).toFixed(6));
|
||||
|
||||
// If we've reached or passed the boundary
|
||||
if (timeLeft <= 0 || currentPosition >= stopTime) {
|
||||
// First pause playback
|
||||
video.pause();
|
||||
|
||||
// Force exact position with multiple verification attempts
|
||||
const setExactPosition = () => {
|
||||
if (!video) return;
|
||||
|
||||
// Set to exact boundary time
|
||||
video.currentTime = stopTime;
|
||||
handleMobileSafeSeek(stopTime);
|
||||
|
||||
const actualPosition = Number(video.currentTime.toFixed(6));
|
||||
const difference = Number(Math.abs(actualPosition - stopTime).toFixed(6));
|
||||
|
||||
logger.debug('Position verification:', {
|
||||
target: formatDetailedTime(stopTime),
|
||||
actual: formatDetailedTime(actualPosition),
|
||||
difference: difference,
|
||||
});
|
||||
|
||||
// If we're not exactly at the target position, try one more time
|
||||
if (difference > 0) {
|
||||
video.currentTime = stopTime;
|
||||
handleMobileSafeSeek(stopTime);
|
||||
}
|
||||
};
|
||||
|
||||
// Multiple attempts to ensure precision, with increasing delays
|
||||
setExactPosition();
|
||||
setTimeout(setExactPosition, 5); // Quick first retry
|
||||
setTimeout(setExactPosition, 10); // Second retry
|
||||
setTimeout(setExactPosition, 20); // Third retry if needed
|
||||
setTimeout(setExactPosition, 50); // Final verification
|
||||
|
||||
// Remove our boundary checker
|
||||
video.removeEventListener('timeupdate', checkBoundary);
|
||||
setIsPlaying(false);
|
||||
|
||||
// Log the final position for debugging
|
||||
logger.debug('Stopped at position:', {
|
||||
target: formatDetailedTime(stopTime),
|
||||
actual: formatDetailedTime(video.currentTime),
|
||||
type: currentSegment ? 'segment end' : nextSegment ? 'next segment start' : 'end of video',
|
||||
segment: currentSegment
|
||||
? {
|
||||
id: currentSegment.id,
|
||||
start: formatDetailedTime(currentSegment.startTime),
|
||||
end: formatDetailedTime(currentSegment.endTime),
|
||||
}
|
||||
: null,
|
||||
nextSegment: nextSegment
|
||||
? {
|
||||
id: nextSegment.id,
|
||||
start: formatDetailedTime(nextSegment.startTime),
|
||||
end: formatDetailedTime(nextSegment.endTime),
|
||||
}
|
||||
: null,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Start our boundary checker
|
||||
video.addEventListener('timeupdate', checkBoundary);
|
||||
|
||||
// Start playing
|
||||
// Start playing - no boundary checking, play through entire timeline
|
||||
video
|
||||
.play()
|
||||
.then(() => {
|
||||
setIsPlaying(true);
|
||||
setVideoInitialized(true);
|
||||
logger.debug('Playback started:', {
|
||||
from: formatDetailedTime(currentPosition),
|
||||
to: formatDetailedTime(stopTime),
|
||||
currentSegment: currentSegment
|
||||
? {
|
||||
id: currentSegment.id,
|
||||
start: formatDetailedTime(currentSegment.startTime),
|
||||
end: formatDetailedTime(currentSegment.endTime),
|
||||
}
|
||||
: 'None',
|
||||
nextSegment: nextSegment
|
||||
? {
|
||||
id: nextSegment.id,
|
||||
start: formatDetailedTime(nextSegment.startTime),
|
||||
end: formatDetailedTime(nextSegment.endTime),
|
||||
}
|
||||
: 'None',
|
||||
});
|
||||
logger.debug('Continuous playback started from:', formatDetailedTime(video.currentTime));
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Error playing video:', err);
|
||||
@ -231,10 +90,8 @@ const App = () => {
|
||||
onReset={handleReset}
|
||||
onUndo={handleUndo}
|
||||
onRedo={handleRedo}
|
||||
onPlaySegments={handlePlaySegments}
|
||||
onPlay={handlePlay}
|
||||
isPlaying={isPlaying}
|
||||
isPlayingSegments={isPlayingSegments}
|
||||
canUndo={historyPosition > 0}
|
||||
canRedo={historyPosition < history.length - 1}
|
||||
/>
|
||||
@ -243,6 +100,7 @@ const App = () => {
|
||||
<TimelineControls
|
||||
currentTime={currentTime}
|
||||
duration={duration}
|
||||
thumbnails={[]}
|
||||
trimStart={trimStart}
|
||||
trimEnd={trimEnd}
|
||||
splitPoints={splitPoints}
|
||||
@ -262,7 +120,6 @@ const App = () => {
|
||||
isPlaying={isPlaying}
|
||||
setIsPlaying={setIsPlaying}
|
||||
onPlayPause={handlePlay}
|
||||
isPlayingSegments={isPlayingSegments}
|
||||
/>
|
||||
|
||||
{/* Clip Segments */}
|
||||
|
||||
@ -561,111 +561,11 @@ const TimelineControls = ({
|
||||
}
|
||||
}, [currentTime, zoomLevel, duration, selectedSegmentId, showEmptySpaceTooltip, currentTimePercent]);
|
||||
|
||||
// Effect to check active segment boundaries during playback
|
||||
// Effect to check active segment boundaries during playback - DISABLED for continuous playback
|
||||
useEffect(() => {
|
||||
// Skip if no video or no active segment
|
||||
const video = videoRef.current;
|
||||
if (!video || !activeSegment || !isPlayingSegment) {
|
||||
// Log why we're skipping
|
||||
if (!video) logger.debug('Skipping segment boundary check - no video element');
|
||||
else if (!activeSegment) logger.debug('Skipping segment boundary check - no active segment');
|
||||
else if (!isPlayingSegment) logger.debug('Skipping segment boundary check - not in segment playback mode');
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip boundary checking when playing all segments
|
||||
if (isPlayingSegments) {
|
||||
logger.debug('Skipping segment boundary check during segments playback');
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
'Segment boundary check ACTIVATED for segment:',
|
||||
activeSegment.id,
|
||||
'Start:',
|
||||
formatDetailedTime(activeSegment.startTime),
|
||||
'End:',
|
||||
formatDetailedTime(activeSegment.endTime)
|
||||
);
|
||||
|
||||
const handleTimeUpdate = () => {
|
||||
const timeLeft = activeSegment.endTime - video.currentTime;
|
||||
|
||||
// Log every second to show we're actually checking
|
||||
if (Math.round(timeLeft * 10) % 10 === 0) {
|
||||
logger.debug(
|
||||
'Segment playback - time remaining:',
|
||||
formatDetailedTime(timeLeft),
|
||||
'Current:',
|
||||
formatDetailedTime(video.currentTime),
|
||||
'End:',
|
||||
formatDetailedTime(activeSegment.endTime),
|
||||
'ContinuePastBoundary:',
|
||||
continuePastBoundary
|
||||
);
|
||||
}
|
||||
|
||||
// If we've already passed the segment end, stop immediately
|
||||
if (video.currentTime > activeSegment.endTime) {
|
||||
video.pause();
|
||||
video.currentTime = activeSegment.endTime;
|
||||
setIsPlayingSegment(false);
|
||||
// Reset continuePastBoundary when stopping at boundary
|
||||
setContinuePastBoundary(false);
|
||||
logger.debug(
|
||||
'Passed segment end - setting back to exact boundary:',
|
||||
formatDetailedTime(activeSegment.endTime)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we've reached very close to the end of the active segment
|
||||
// Use a small tolerance to ensure we stop as close as possible to boundary
|
||||
// But not exactly at the boundary to avoid rounding errors
|
||||
if (activeSegment.endTime - video.currentTime < 0.05) {
|
||||
if (!continuePastBoundary) {
|
||||
// Pause playback and set the time exactly at the end boundary
|
||||
video.pause();
|
||||
video.currentTime = activeSegment.endTime;
|
||||
setIsPlayingSegment(false);
|
||||
logger.debug('Paused at segment end boundary:', formatDetailedTime(activeSegment.endTime));
|
||||
|
||||
// Look for the next segment after this one (for potential continuation)
|
||||
const sortedSegments = [...clipSegments].sort((a, b) => a.startTime - b.startTime);
|
||||
const nextSegment = sortedSegments.find((seg) => seg.startTime > activeSegment.endTime);
|
||||
|
||||
// If there's a next segment immediately after this one, update the tooltip to show that segment
|
||||
if (nextSegment && Math.abs(nextSegment.startTime - activeSegment.endTime) < 0.1) {
|
||||
logger.debug('Found adjacent next segment:', nextSegment.id);
|
||||
setSelectedSegmentId(nextSegment.id);
|
||||
setActiveSegment(nextSegment);
|
||||
setDisplayTime(nextSegment.startTime);
|
||||
setClickedTime(nextSegment.startTime);
|
||||
video.currentTime = nextSegment.startTime;
|
||||
}
|
||||
} else {
|
||||
// We're continuing past the boundary
|
||||
logger.debug('Continuing past segment boundary:', formatDetailedTime(activeSegment.endTime));
|
||||
|
||||
// Reset the flag after we've passed the boundary to ensure we stop at the next boundary
|
||||
if (video.currentTime > activeSegment.endTime) {
|
||||
setContinuePastBoundary(false);
|
||||
logger.debug('Past segment boundary - resetting continuePastBoundary flag');
|
||||
// Remove the active segment to avoid boundary checking until next segment is activated
|
||||
setActiveSegment(null);
|
||||
sessionStorage.removeItem('continuingPastSegment');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add event listener for timeupdate to check segment boundaries
|
||||
video.addEventListener('timeupdate', handleTimeUpdate);
|
||||
|
||||
return () => {
|
||||
video.removeEventListener('timeupdate', handleTimeUpdate);
|
||||
logger.debug('Segment boundary check DEACTIVATED');
|
||||
};
|
||||
// Boundary checking disabled - allow continuous playback through all segments
|
||||
logger.debug('Segment boundary checking disabled - continuous playback enabled');
|
||||
return;
|
||||
}, [activeSegment, isPlayingSegment, continuePastBoundary, clipSegments]);
|
||||
|
||||
// Update display time and check for transitions between segments and empty spaces
|
||||
@ -2140,129 +2040,15 @@ const TimelineControls = ({
|
||||
if (!video) return;
|
||||
|
||||
const handlePlay = () => {
|
||||
if (!videoRef.current) return;
|
||||
|
||||
const video = videoRef.current;
|
||||
const currentPosition = video.currentTime;
|
||||
|
||||
// Reset continuePastBoundary flag when starting new playback
|
||||
setContinuePastBoundary(false);
|
||||
|
||||
// Find the next stopping point based on current position
|
||||
let stopTime = duration;
|
||||
let currentSegment = null;
|
||||
let nextSegment = null;
|
||||
|
||||
// First, check if we're inside a segment with high precision
|
||||
currentSegment = clipSegments.find((seg) => {
|
||||
const isWithinSegment = currentPosition >= seg.startTime && currentPosition <= seg.endTime;
|
||||
const isAtExactStart = Math.abs(currentPosition - seg.startTime) < 0.001; // Within 1ms of start
|
||||
const isAtExactEnd = Math.abs(currentPosition - seg.endTime) < 0.001; // Within 1ms of end
|
||||
return isWithinSegment || isAtExactStart || isAtExactEnd;
|
||||
});
|
||||
|
||||
// Find the next segment with high precision
|
||||
nextSegment = clipSegments
|
||||
.filter((seg) => {
|
||||
const isAfterCurrent = seg.startTime > currentPosition;
|
||||
const isNotAtExactPosition = Math.abs(seg.startTime - currentPosition) > 0.001;
|
||||
return isAfterCurrent && isNotAtExactPosition;
|
||||
})
|
||||
.sort((a, b) => a.startTime - b.startTime)[0];
|
||||
|
||||
// Determine where to stop based on position
|
||||
if (currentSegment) {
|
||||
// If we're in a segment, stop at its end
|
||||
stopTime = currentSegment.endTime;
|
||||
setActiveSegment(currentSegment);
|
||||
} else if (nextSegment) {
|
||||
// If we're in a cutaway and there's a next segment, stop at its start
|
||||
stopTime = nextSegment.startTime;
|
||||
// Don't set active segment since we're in a cutaway
|
||||
}
|
||||
|
||||
// Create a boundary checker function with high precision
|
||||
const checkBoundary = () => {
|
||||
if (!video) return;
|
||||
|
||||
const currentPosition = video.currentTime;
|
||||
const timeLeft = stopTime - currentPosition;
|
||||
|
||||
// If we're approaching the boundary (within 1ms) or have passed it
|
||||
if (timeLeft <= 0.001 || currentPosition >= stopTime) {
|
||||
// First pause playback
|
||||
video.pause();
|
||||
|
||||
// Force exact position with multiple verification attempts
|
||||
const setExactPosition = () => {
|
||||
if (!video) return;
|
||||
|
||||
// Set to exact boundary time
|
||||
video.currentTime = stopTime;
|
||||
onSeek(stopTime);
|
||||
setDisplayTime(stopTime);
|
||||
setClickedTime(stopTime);
|
||||
|
||||
logger.debug('Position verification:', {
|
||||
target: formatDetailedTime(stopTime),
|
||||
actual: formatDetailedTime(video.currentTime),
|
||||
difference: Math.abs(video.currentTime - stopTime).toFixed(3),
|
||||
});
|
||||
};
|
||||
|
||||
// Multiple attempts to ensure precision
|
||||
setExactPosition();
|
||||
setTimeout(setExactPosition, 10);
|
||||
setTimeout(setExactPosition, 20);
|
||||
setTimeout(setExactPosition, 50);
|
||||
|
||||
// Update UI based on where we stopped
|
||||
if (currentSegment) {
|
||||
setSelectedSegmentId(currentSegment.id);
|
||||
setShowEmptySpaceTooltip(false);
|
||||
} else if (nextSegment) {
|
||||
setSelectedSegmentId(nextSegment.id);
|
||||
setShowEmptySpaceTooltip(false);
|
||||
setActiveSegment(nextSegment);
|
||||
} else {
|
||||
setSelectedSegmentId(null);
|
||||
setShowEmptySpaceTooltip(true);
|
||||
setActiveSegment(null);
|
||||
}
|
||||
|
||||
// Remove our boundary checker
|
||||
video.removeEventListener('timeupdate', checkBoundary);
|
||||
setIsPlaying(false);
|
||||
setIsPlayingSegment(false);
|
||||
// Reset continuePastBoundary flag when stopping at boundary
|
||||
setContinuePastBoundary(false);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Start our boundary checker
|
||||
video.addEventListener('timeupdate', checkBoundary);
|
||||
|
||||
// Start playing
|
||||
video
|
||||
.play()
|
||||
.then(() => {
|
||||
setIsPlaying(true);
|
||||
setIsPlayingSegment(true);
|
||||
logger.debug('Playback started:', {
|
||||
from: formatDetailedTime(currentPosition),
|
||||
to: formatDetailedTime(stopTime),
|
||||
currentSegment: currentSegment ? `Segment ${currentSegment.id}` : 'None',
|
||||
nextSegment: nextSegment ? `Segment ${nextSegment.id}` : 'None',
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Error playing video:', err);
|
||||
});
|
||||
// Simple play handler - just update UI state, no boundary checking
|
||||
setIsPlaying(true);
|
||||
setIsPlayingSegment(true);
|
||||
logger.debug('Continuous playback started from TimelineControls');
|
||||
};
|
||||
|
||||
const handlePause = () => {
|
||||
logger.debug('Video paused from external control');
|
||||
setIsPlaying(false);
|
||||
setIsPlayingSegment(false);
|
||||
};
|
||||
|
||||
@ -2273,7 +2059,7 @@ const TimelineControls = ({
|
||||
video.removeEventListener('play', handlePlay);
|
||||
video.removeEventListener('pause', handlePause);
|
||||
};
|
||||
}, [clipSegments, duration, onSeek]);
|
||||
}, []);
|
||||
|
||||
// Handle mouse movement over timeline to remember position
|
||||
const handleTimelineMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
@ -3281,181 +3067,7 @@ const TimelineControls = ({
|
||||
setActiveSegment(cutawaySegment);
|
||||
}, 0);
|
||||
|
||||
// Add a manual boundary check specifically for cutaway playback
|
||||
// This ensures we detect when we reach the next segment's start
|
||||
const checkCutawayBoundary = () => {
|
||||
if (!videoRef.current) return;
|
||||
|
||||
// Check if we've entered a segment (i.e., reached a boundary)
|
||||
const currentPosition = videoRef.current.currentTime;
|
||||
const segments = [...clipSegments].sort(
|
||||
(a, b) => a.startTime - b.startTime
|
||||
);
|
||||
|
||||
// Find the next segment we're approaching - use a wider detection range
|
||||
// to catch the boundary earlier
|
||||
const nextSegment = segments.find(
|
||||
(seg) => seg.startTime > currentPosition - 0.3
|
||||
);
|
||||
|
||||
// We need to detect boundaries much earlier to allow for time to react
|
||||
// This is a key fix - we need to detect the boundary BEFORE we reach it
|
||||
// But don't stop if we're in continuePastBoundary mode
|
||||
const shouldStop =
|
||||
nextSegment &&
|
||||
currentPosition >= nextSegment.startTime - 0.25 &&
|
||||
currentPosition <= nextSegment.startTime + 0.1 &&
|
||||
!continuePastBoundary;
|
||||
|
||||
// Add logging to show boundary check decisions
|
||||
if (
|
||||
nextSegment &&
|
||||
currentPosition >= nextSegment.startTime - 0.25 &&
|
||||
currentPosition <= nextSegment.startTime + 0.1
|
||||
) {
|
||||
logger.debug(
|
||||
`Approaching boundary at ${formatDetailedTime(
|
||||
nextSegment.startTime
|
||||
)}, continuePastBoundary=${continuePastBoundary}, willStop=${shouldStop}`
|
||||
);
|
||||
}
|
||||
|
||||
// Also check if we've entered a different segment - we need to detect this too
|
||||
const segmentAtCurrentTime = segments.find(
|
||||
(seg) =>
|
||||
currentPosition >= seg.startTime &&
|
||||
currentPosition <= seg.endTime
|
||||
);
|
||||
|
||||
// If we've moved directly into a segment during playback, we need to update the active segment
|
||||
if (
|
||||
segmentAtCurrentTime &&
|
||||
activeSegment?.id !== segmentAtCurrentTime.id
|
||||
) {
|
||||
logger.debug(
|
||||
`Entered segment ${segmentAtCurrentTime.id} during cutaway playback`
|
||||
);
|
||||
setActiveSegment(segmentAtCurrentTime);
|
||||
setSelectedSegmentId(segmentAtCurrentTime.id);
|
||||
setShowEmptySpaceTooltip(false);
|
||||
|
||||
// Remove our boundary checker since we're now in a standard segment
|
||||
videoRef.current.removeEventListener(
|
||||
'timeupdate',
|
||||
checkCutawayBoundary
|
||||
);
|
||||
|
||||
// Reset continuation flags
|
||||
setContinuePastBoundary(false);
|
||||
sessionStorage.removeItem('continuingPastSegment');
|
||||
return;
|
||||
}
|
||||
|
||||
// If we've entered a segment, stop at its boundary
|
||||
if (shouldStop && nextSegment) {
|
||||
logger.debug(
|
||||
`CUTAWAY MANUAL BOUNDARY CHECK: Current position ${formatDetailedTime(
|
||||
currentPosition
|
||||
)} approaching segment at ${formatDetailedTime(
|
||||
nextSegment.startTime
|
||||
)} (distance: ${Math.abs(
|
||||
currentPosition - nextSegment.startTime
|
||||
).toFixed(3)}s) - STOPPING`
|
||||
);
|
||||
|
||||
videoRef.current.pause();
|
||||
// Force exact time position with high precision and multiple attempts
|
||||
setTimeout(() => {
|
||||
if (videoRef.current) {
|
||||
// First seek directly to exact start time, no offset
|
||||
videoRef.current.currentTime = nextSegment.startTime;
|
||||
// Update UI immediately to match video position
|
||||
onSeek(nextSegment.startTime);
|
||||
// Also update tooltip time displays
|
||||
setDisplayTime(nextSegment.startTime);
|
||||
setClickedTime(nextSegment.startTime);
|
||||
|
||||
// Reset continuePastBoundary when stopping at a boundary
|
||||
setContinuePastBoundary(false);
|
||||
|
||||
// Update tooltip to show the segment at the boundary
|
||||
setSelectedSegmentId(nextSegment.id);
|
||||
setShowEmptySpaceTooltip(false);
|
||||
setActiveSegment(nextSegment);
|
||||
|
||||
// Force multiple adjustments to ensure exact precision
|
||||
const verifyPosition = () => {
|
||||
if (videoRef.current) {
|
||||
// Always force the exact time in every verification
|
||||
videoRef.current.currentTime =
|
||||
nextSegment.startTime;
|
||||
|
||||
// Make sure we update the UI to reflect the corrected position
|
||||
onSeek(nextSegment.startTime);
|
||||
|
||||
// Update the displayTime and clickedTime state to match exact position
|
||||
setDisplayTime(nextSegment.startTime);
|
||||
setClickedTime(nextSegment.startTime);
|
||||
|
||||
logger.debug(
|
||||
`Position corrected to exact segment boundary: ${formatDetailedTime(
|
||||
videoRef.current.currentTime
|
||||
)} (target: ${formatDetailedTime(nextSegment.startTime)})`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Apply multiple correction attempts with increasing delays
|
||||
setTimeout(verifyPosition, 10); // Immediate correction
|
||||
setTimeout(verifyPosition, 20); // First correction
|
||||
setTimeout(verifyPosition, 50); // Second correction
|
||||
setTimeout(verifyPosition, 100); // Third correction
|
||||
setTimeout(verifyPosition, 200); // Final correction
|
||||
|
||||
// Also add event listeners to ensure position is corrected whenever video state changes
|
||||
videoRef.current.addEventListener('seeked', verifyPosition);
|
||||
videoRef.current.addEventListener(
|
||||
'canplay',
|
||||
verifyPosition
|
||||
);
|
||||
videoRef.current.addEventListener(
|
||||
'waiting',
|
||||
verifyPosition
|
||||
);
|
||||
|
||||
// Remove these event listeners after a short time
|
||||
setTimeout(() => {
|
||||
if (videoRef.current) {
|
||||
videoRef.current.removeEventListener(
|
||||
'seeked',
|
||||
verifyPosition
|
||||
);
|
||||
videoRef.current.removeEventListener(
|
||||
'canplay',
|
||||
verifyPosition
|
||||
);
|
||||
videoRef.current.removeEventListener(
|
||||
'waiting',
|
||||
verifyPosition
|
||||
);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
}, 10);
|
||||
setIsPlayingSegment(false);
|
||||
setActiveSegment(null);
|
||||
|
||||
// Remove our boundary checker
|
||||
videoRef.current.removeEventListener(
|
||||
'timeupdate',
|
||||
checkCutawayBoundary
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Start our manual boundary checker
|
||||
videoRef.current.addEventListener('timeupdate', checkCutawayBoundary);
|
||||
// No boundary checking - allow continuous playback
|
||||
|
||||
// Start playing with proper promise handling - use setTimeout to ensure
|
||||
// that our activeSegment setting has had time to take effect
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user