import { AbsoluteFill, Img, Sequence, useVideoConfig, useCurrentFrame, Html5Audio, spring, interpolate } from "remotion";
export type WordTiming = {
word: string;
startFrame: number;
endFrame: number;
};
export type ImageCompositionProps = {
images: string[];
overlayText?: string;
audioUrl?: string;
wordTimings?: WordTiming[];
musicUrl?: string;
musicVolume?: number;
logoUrl?: string;
storeName?: string;
endingFrames?: number;
};
/**
* Ken Burns presets — deterministic per image index.
* Each entry: starting transform → ending transform over the slide duration.
* Scale > 1 to avoid black edges when translating.
*/
const KB_PRESETS = [
// zoom in, center
{ fromScale: 1.0, toScale: 1.14, fromX: "0%", toX: "0%", fromY: "0%", toY: "0%" },
// zoom in + drift right
{ fromScale: 1.06, toScale: 1.18, fromX: "-3%", toX: "3%", fromY: "0%", toY: "0%" },
// zoom in + drift left
{ fromScale: 1.06, toScale: 1.18, fromX: "3%", toX: "-3%", fromY: "0%", toY: "0%" },
// zoom out, center
{ fromScale: 1.16, toScale: 1.04, fromX: "0%", toX: "0%", fromY: "0%", toY: "0%" },
// pan up + slight zoom
{ fromScale: 1.1, toScale: 1.14, fromX: "0%", toX: "0%", fromY: "3%", toY: "-3%" },
// pan down + zoom in
{ fromScale: 1.06, toScale: 1.16, fromX: "0%", toX: "0%", fromY: "-3%", toY: "3%" },
// diagonal drift bottom-right
{ fromScale: 1.08, toScale: 1.18, fromX: "-2%", toX: "2%", fromY: "-2%", toY: "2%" },
// diagonal drift top-left + zoom out
{ fromScale: 1.18, toScale: 1.06, fromX: "2%", toX: "-2%", fromY: "2%", toY: "-2%" },
];
/**
* ImageSlide with Ken Burns effect (slow zoom / pan).
* The effect index is derived from the image index for deterministic behaviour in Remotion.
*/
const ImageSlide: React.FC<{ src: string; effectIndex: number }> = ({ src, effectIndex }) => {
const frame = useCurrentFrame();
const { durationInFrames } = useVideoConfig();
const preset = KB_PRESETS[effectIndex % KB_PRESETS.length];
// progress: 0 → 1 over the slide duration, using easeInOut via interpolate extrapolate clamp
const progress = interpolate(frame, [0, durationInFrames], [0, 1], { extrapolateRight: "clamp" });
const scale = interpolate(progress, [0, 1], [preset.fromScale, preset.toScale]);
const transX = interpolate(progress, [0, 1], [parseFloat(preset.fromX), parseFloat(preset.toX)]);
const transY = interpolate(progress, [0, 1], [parseFloat(preset.fromY), parseFloat(preset.toY)]);
return (