import React, { useMemo } from 'react'; import { AbsoluteFill, useVideoConfig, useCurrentFrame, interpolate, spring, Easing, } from 'remotion'; import { RecordingSession, RecordEvent } from '../types/record-mode'; export const WebsiteVideo: React.FC<{ session: RecordingSession | null; siteUrl: string; }> = ({ session, siteUrl }) => { const { fps, width, height, durationInFrames } = useVideoConfig(); const frame = useCurrentFrame(); const sortedEvents = useMemo(() => { if (!session) return []; return [...session.events].sort((a, b) => a.timestamp - b.timestamp); }, [session]); if (!session || !session.events.length) { return ( No session data found. ); } const elapsedTimeMs = (frame / fps) * 1000; // --- Interpolation Logic --- // 1. Find the current window (between which two events are we?) const nextEventIndex = sortedEvents.findIndex((e) => e.timestamp > elapsedTimeMs); let currentEventIndex; if (nextEventIndex === -1) { // We are past the last event, stay at the end currentEventIndex = sortedEvents.length - 1; } else { currentEventIndex = Math.max(0, nextEventIndex - 1); } const currentEvent = sortedEvents[currentEventIndex]; // If there is no next event, we just stay at current (next=current) const nextEvent = nextEventIndex !== -1 ? sortedEvents[nextEventIndex] : currentEvent; // 2. Calculate Progress between events const gap = nextEvent.timestamp - currentEvent.timestamp; const progress = gap > 0 ? (elapsedTimeMs - currentEvent.timestamp) / gap : 1; const easedProgress = Easing.cubic(Math.min(Math.max(progress, 0), 1)); // 3. Calculate Cursor Position from Rects const getCenter = (event: RecordEvent) => { if (event.rect) { return { x: event.rect.x + event.rect.width / 2, y: event.rect.y + event.rect.height / 2, }; } return { x: width / 2, y: height / 2 }; }; const p1 = getCenter(currentEvent); const p2 = getCenter(nextEvent); const cursorX = interpolate(easedProgress, [0, 1], [p1.x, p2.x]); const cursorY = interpolate(easedProgress, [0, 1], [p1.y, p2.y]); // 4. Zoom & Blur const zoom = interpolate(easedProgress, [0, 1], [currentEvent.zoom || 1, nextEvent.zoom || 1]); const isBlurry = currentEvent.motionBlur || nextEvent.motionBlur; return (