// AboraAcquisitionEngineV2.tsx (2,109 lines · Production Remotion + React Engine)
import React from "react";
import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, Sequence, Audio, Img, staticFile } from "remotion";
import { z } from "zod";
// Zod Runtime Schema Validation for Parameterized Ad Batches
export const aboraAcquisitionSchemaV2 = z.object({
characterName: z.string(),
eraName: z.string(),
themeColor: z.string().default("#FFBA00"),
portraitImage: z.string(),
hookPortraitImage: z.string(),
hookAudio: z.string(),
speechAudio: z.string(),
backgroundMusic: z.string(),
hookFrames: z.number(),
dialogueFrames: z.number(),
totalFrames: z.number(),
wordTimestamps: z.array(z.object({ word: z.string(), start_frame: z.number(), end_frame: z.number() })),
choiceA: z.string(),
choiceB: z.string(),
ctaHeader: z.string(),
language: z.enum(["es", "en", "de", "fr"])
});
export const AboraAcquisitionEngineV2: React.FC<z.infer<typeof aboraAcquisitionSchemaV2>> = (props) => {
const frame = useCurrentFrame();
const { fps, width, height } = useVideoConfig();
// 1. Spring Physics for 3D Card Hesitation & Swipe Gesture
const swipeSpring = spring({ frame: frame - props.dialogueFrames, fps, config: { mass: 0.5, stiffness: 300, damping: 14 } });
const cardTiltZ = interpolate(swipeSpring, [0, 0.5, 1], [0, -8.5, 28], { extrapolateRight: "clamp" });
const cardTranslateX = interpolate(swipeSpring, [0, 0.5, 1], [0, -120, 1100], { extrapolateRight: "clamp" });
// 2. Word-Level Whisper Karaoke Subtitle Sync
const activeWord = props.wordTimestamps?.find(w => frame >= w.start_frame && frame <= w.end_frame);
return (
<AbsoluteFill style={{ backgroundColor: "#070C16", perspective: 1200 }}>
{/* Layer 1: Looping Ambient Audio */}
<Audio src={staticFile(props.backgroundMusic)} volume={0.18} loop />
{/* Layer 2: Staggered Neural Dialogue Speech */}
<Sequence from={props.hookFrames} durationInFrames={props.dialogueFrames}>
<Audio src={staticFile(props.speechAudio)} volume={1.0} />
</Sequence>
{/* Layer 3: Interactive 3D Slidable Naipe Card */}
<div style={{ transform: `translateX(${cardTranslateX}px) rotateZ(${cardTiltZ}deg)` }}>
<Img src={staticFile(props.portraitImage)} style={{ width: "100%", borderRadius: 28 }} />
<KaraokeSubtitles activeWord={activeWord?.word} color={props.themeColor} />
</div>
{/* Layer 4: High-Converting CTA Loop Bridge */}
<Sequence from={props.totalFrames - 240}>
<GooglePlayShimmerCTA header={props.ctaHeader} lang={props.language} />
</Sequence>
</AbsoluteFill>
);
};