fived background video issue in presentations

This commit is contained in:
Dmitri 2026-04-23 13:23:52 +04:00
parent 7e54cc8858
commit 71f8b060a8
4 changed files with 21 additions and 6 deletions

View File

@ -33,6 +33,8 @@ interface CanvasBackgroundProps {
videoMuted?: boolean; videoMuted?: boolean;
videoStartTime?: number | null; videoStartTime?: number | null;
videoEndTime?: number | null; videoEndTime?: number | null;
/** Original storage path for video - used for play-once tracking (not the resolved blob URL) */
videoStoragePath?: string;
} }
const CanvasBackground: React.FC<CanvasBackgroundProps> = ({ const CanvasBackground: React.FC<CanvasBackgroundProps> = ({
@ -50,10 +52,13 @@ const CanvasBackground: React.FC<CanvasBackgroundProps> = ({
videoMuted = true, videoMuted = true,
videoStartTime = null, videoStartTime = null,
videoEndTime = null, videoEndTime = null,
videoStoragePath,
}) => { }) => {
// Use background video playback hook for custom start/end time handling // Use background video playback hook for custom start/end time handling
// Use storagePath for play-once tracking (falls back to videoUrl if not provided)
const { videoRef, shouldBlockAutoplay } = useBackgroundVideoPlayback({ const { videoRef, shouldBlockAutoplay } = useBackgroundVideoPlayback({
videoUrl: backgroundVideoUrl, videoUrl: backgroundVideoUrl,
videoStoragePath: videoStoragePath || backgroundVideoUrl,
autoplay: videoAutoplay, autoplay: videoAutoplay,
loop: videoLoop, loop: videoLoop,
muted: videoMuted, muted: videoMuted,

View File

@ -653,6 +653,7 @@ export default function RuntimePresentation({
videoMuted={videoMuted} videoMuted={videoMuted}
videoStartTime={videoStartTime} videoStartTime={videoStartTime}
videoEndTime={videoEndTime} videoEndTime={videoEndTime}
videoStoragePath={selectedPage?.background_video_url}
/> />
</div> </div>
{/* End page background wrapper */} {/* End page background wrapper */}

View File

@ -16,8 +16,10 @@ import { logger } from '../lib/logger';
const playedVideos = new Set<string>(); const playedVideos = new Set<string>();
export interface UseBackgroundVideoPlaybackOptions { export interface UseBackgroundVideoPlaybackOptions {
/** URL of the video to play */ /** URL of the video to play (may be a blob URL) */
videoUrl?: string; videoUrl?: string;
/** Original storage path for play-once tracking (stable across navigations) */
videoStoragePath?: string;
/** Whether to autoplay the video (default: true) */ /** Whether to autoplay the video (default: true) */
autoplay?: boolean; autoplay?: boolean;
/** Whether to loop the video (default: true) */ /** Whether to loop the video (default: true) */
@ -58,6 +60,7 @@ export interface UseBackgroundVideoPlaybackResult {
*/ */
export function useBackgroundVideoPlayback({ export function useBackgroundVideoPlayback({
videoUrl, videoUrl,
videoStoragePath,
autoplay = true, autoplay = true,
loop = true, loop = true,
muted = true, muted = true,
@ -66,8 +69,12 @@ export function useBackgroundVideoPlayback({
}: UseBackgroundVideoPlaybackOptions): UseBackgroundVideoPlaybackResult { }: UseBackgroundVideoPlaybackOptions): UseBackgroundVideoPlaybackResult {
const videoRef = useRef<HTMLVideoElement | null>(null); const videoRef = useRef<HTMLVideoElement | null>(null);
// Use storage path for tracking (stable across blob URL changes)
// Falls back to videoUrl if no storage path provided
const trackingKey = videoStoragePath || videoUrl;
// Block autoplay if video already played this session (only when loop=false) // Block autoplay if video already played this session (only when loop=false)
const shouldBlockAutoplay = !loop && videoUrl ? playedVideos.has(videoUrl) : false; const shouldBlockAutoplay = !loop && trackingKey ? playedVideos.has(trackingKey) : false;
// Store current values in refs for event handlers to access // Store current values in refs for event handlers to access
const startTimeRef = useRef(startTime); const startTimeRef = useRef(startTime);
const endTimeRef = useRef(endTime); const endTimeRef = useRef(endTime);
@ -188,12 +195,13 @@ export function useBackgroundVideoPlayback({
// Session-scoped "play once" behavior when loop is disabled // Session-scoped "play once" behavior when loop is disabled
// Videos that have already played show last frame on revisit // Videos that have already played show last frame on revisit
// Uses trackingKey (storage path) for stable tracking across blob URL changes
useEffect(() => { useEffect(() => {
const video = videoRef.current; const video = videoRef.current;
if (!video || !videoUrl || loop) return; if (!video || !videoUrl || !trackingKey || loop) return;
// If video already played this session, show last frame // If video already played this session, show last frame
if (playedVideos.has(videoUrl)) { if (playedVideos.has(trackingKey)) {
const showLastFrame = () => { const showLastFrame = () => {
video.currentTime = video.duration - 0.01; video.currentTime = video.duration - 0.01;
video.pause(); video.pause();
@ -208,11 +216,11 @@ export function useBackgroundVideoPlayback({
// Mark video as played when it ends // Mark video as played when it ends
const handleEnded = () => { const handleEnded = () => {
playedVideos.add(videoUrl); playedVideos.add(trackingKey);
}; };
video.addEventListener('ended', handleEnded); video.addEventListener('ended', handleEnded);
return () => video.removeEventListener('ended', handleEnded); return () => video.removeEventListener('ended', handleEnded);
}, [videoUrl, loop]); }, [videoUrl, trackingKey, loop]);
return { videoRef, shouldBlockAutoplay }; return { videoRef, shouldBlockAutoplay };
} }

View File

@ -1534,6 +1534,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
videoMuted={backgroundVideoMuted} videoMuted={backgroundVideoMuted}
videoStartTime={backgroundVideoStartTime} videoStartTime={backgroundVideoStartTime}
videoEndTime={backgroundVideoEndTime} videoEndTime={backgroundVideoEndTime}
videoStoragePath={backgroundVideoUrl || activePage?.background_video_url}
/> />
</div> </div>