import React, { useMemo } from "react"; import { AbsoluteFill, Audio, Sequence, useCurrentFrame, useVideoConfig, staticFile, } from "remotion"; import type { RenderProps } from "../frontend/src/render-props-types"; import { DualChartView } from "./DualChartView"; import { Avatar } from "./Avatar"; export const MainVideo: React.FC = (props) => { const { charts, script, meta } = props; const frame = useCurrentFrame(); const { fps } = useVideoConfig(); // Convert script segments to frame-based timeline const timeline = useMemo(() => { let currentFrame = 0; return script.map((segment: any) => { const startFrame = currentFrame; const durationInFrames = Math.round(segment.duration * fps); currentFrame += durationInFrames; return { ...segment, startFrame, durationInFrames, }; }); }, [script, fps]); // Find current segment for subtitle display const currentSegment = timeline.find( (seg: any) => frame >= seg.startFrame && frame < seg.startFrame + seg.durationInFrames ); // Prepare cashflow data for DualChartView const cashflowTimeline = useMemo( () => charts.cashFlow.timeline.map((item: any) => { const totalExpense = item.totalExpense ?? item.expenses.living + item.expenses.housing + item.expenses.education + item.expenses.tax + item.expenses.event; const netCashFlow = item.netCashFlow ?? item.income.total - totalExpense; return { ...item, totalExpense, netCashFlow, assetBalance: item.assetBalance ?? 0, }; }), [charts.cashFlow.timeline] ); const cashflowData = useMemo( () => ({ timeline: cashflowTimeline, meta: charts.cashFlow.meta, }), [cashflowTimeline, charts.cashFlow.meta] ); return ( {/* Render each script segment as a Sequence */} {timeline.map((segment: any) => ( {/* Scene content based on segment type */} {segment.type === "chart_intro" || segment.type === "chart_highlight" ? ( ) : ( // For narration segments, show chart with overlay )} {/* Audio narration (if available) */} {segment.audioPath && ( ))} ); };