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;
videoStartTime?: 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> = ({
@ -50,10 +52,13 @@ const CanvasBackground: React.FC<CanvasBackgroundProps> = ({
videoMuted = true,
videoStartTime = null,
videoEndTime = null,
videoStoragePath,
}) => {
// 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({
videoUrl: backgroundVideoUrl,
videoStoragePath: videoStoragePath || backgroundVideoUrl,
autoplay: videoAutoplay,
loop: videoLoop,
muted: videoMuted,

View File

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

View File

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

View File

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