9.9 KiB
视频渲染与合成
**本文档引用的文件** - [index.ts](file://src/index.ts) - [Root.tsx](file://src/Root.tsx) - [render-props-types.ts](file://frontend/src/render-props-types.ts) - [LifePlanChart.tsx](file://src/LifePlanChart.tsx) - [CashFlowChart.tsx](file://src/CashFlowChart.tsx) - [DualChartView.tsx](file://src/DualChartView.tsx) - [data_builder.py](file://backend/data_builder.py) - [scripter.py](file://backend/scripter.py) - [remotion.config.ts](file://remotion.config.ts) - [mock-data.json](file://src/mock-data.json) - [mock-cashflow.json](file://src/mock-cashflow.json)目录
简介
本项目是一个混合型Python/Node.js系统,能够将静态的财务规划报告(PDF)和原始访谈视频自动转换为动态、个性化的3-5分钟解说视频。系统结合了动画图表、AI生成的旁白、B-Roll素材和同步的访谈片段,为用户提供直观的财务规划可视化体验。该系统采用前后端分离架构,后端使用Python进行数据处理和AI推理,前端使用Remotion框架进行视频渲染。
项目结构
该项目采用清晰的分层架构,将后端数据处理与前端视频渲染分离。根目录包含主配置文件(如package.json、remotion.config.ts)和入口脚本(main.py)。backend/目录存放Python模块,负责PDF解析、脚本生成、数据模拟等核心逻辑。frontend/src/目录存放Remotion前端代码,包括React组件和渲染逻辑。assets/目录作为共享存储,分为输入、处理中和输出三个子目录,确保数据流清晰。这种结构实现了关注点分离,便于团队协作和独立开发。
graph TB
subgraph "输入层"
PDF[PDF报告]
Video[访谈视频]
end
subgraph "后端处理层"
Extractor[extractor.py]
DataBuilder[data_builder.py]
Scripter[scripter.py]
MediaFetcher[media_fetcher.py]
end
subgraph "数据契约"
RenderProps[render_props.json]
end
subgraph "前端渲染层"
Remotion[Remotion]
Components[React组件]
end
subgraph "输出层"
Output[最终视频]
end
PDF --> Extractor
Video --> Extractor
Extractor --> DataBuilder
Extractor --> Scripter
DataBuilder --> RenderProps
Scripter --> RenderProps
MediaFetcher --> RenderProps
RenderProps --> Remotion
Remotion --> Output
图源
核心组件
系统的核心在于render_props.json数据契约和Remotion渲染引擎的协同工作。后端Python模块生成包含财务数据、脚本和媒体引用的JSON文件,前端Remotion应用加载此文件并驱动React组件进行时间轴同步渲染。LifePlanChart.tsx和CashFlowChart.tsx是两个关键的可视化组件,它们接收来自render_props.json的数据并生成动态动画图表。DualChartView.tsx组件则将两个图表并排显示,实现更复杂的可视化布局。
本节来源
架构概述
系统采用“导演-演员”模式,Python后端作为“导演”负责数据准备和决策,Remotion前端作为“演员”负责执行渲染。数据流始于PDF和视频输入,通过后端模块提取、模拟和生成,最终形成render_props.json数据契约。该文件被Remotion加载,驱动React组件根据时间轴动态渲染图表和UI元素。音视频同步通过脚本段落的duration字段和B-Roll的assetUrl精确编排,确保旁白、动画和背景素材的完美同步。
graph LR
A[PDF/视频输入] --> B[Python后端]
B --> C[render_props.json]
C --> D[Remotion前端]
D --> E[动态视频输出]
F[API密钥] --> B
G[外部API] --> B
H[本地预览] --> D
图源
详细组件分析
渲染入口与数据加载
src/index.ts是Remotion应用的入口文件,它通过registerRoot函数注册根组件RemotionRoot。RemotionRoot在Root.tsx中定义,它使用<Composition>组件来注册多个可渲染的视频序列,如“LifePlanSimulation”和“CashFlowChart”。每个<Composition>都指定了一个React组件、视频时长、帧率和分辨率,并通过defaultProps将模拟数据(如mockData和mockCashFlow)传递给组件。在生产环境中,这些数据将被render_props.json中的真实数据替换。
本节来源
RenderPropsSchema数据契约
frontend/src/render-props-types.ts文件定义了RenderProps接口和RenderPropsSchema,它们是前后端之间的核心数据契约。该契约包含四个主要部分:meta(元数据,如标题和时长)、charts(资产消耗和现金流图表数据)、script(按时间轴排列的旁白脚本段落)和assets(B-Roll和访谈片段的引用)。Zod库用于在运行时验证render_props.json的结构,确保数据的完整性和正确性,防止因数据格式错误导致的渲染失败。
classDiagram
class RenderProps {
+meta : Meta
+charts : Charts
+script : ScriptSegment[]
+assets : AssetCollection
}
class Meta {
+title : string
+currencyUnit : string
+duration : number
}
class Charts {
+assetDepletion : AssetDepletionChartData
+cashFlow : CashFlowChartData
}
class ScriptSegment {
+id : number
+text : string
+duration : number
+type : ScriptSegmentType
+assetUrl? : string
+chartSync? : ChartSync
}
class AssetCollection {
+broll : Record~string, string~
+videoClips : VideoClipReference[]
+ttsAudio? : string
}
RenderProps --> Meta
RenderProps --> Charts
RenderProps --> ScriptSegment
RenderProps --> AssetCollection
图源
数据可视化组件
LifePlanChart.tsx和CashFlowChart.tsx是两个核心的可视化组件。LifePlanChart使用recharts的AreaChart来展示资产余额随时间的变化趋势,其X轴包含年份、本人年龄和配偶年龄三行信息。CashFlowChart使用ComposedChart来展示收入与支出的对比,其中收入为红线,支出为堆叠的彩色柱状图。两个组件都利用useCurrentFrame和interpolate函数实现与视频时间轴同步的平滑动画效果,数据点会随着视频播放进度逐步显现。
本节来源
音视频同步机制
音视频同步由script数组中的ScriptSegment对象精确控制。每个段落包含duration(持续时间)和type(类型,如旁白、图表介绍等)。当类型为chart_highlight时,chartSync字段会指定要高亮的图表ID和年份,触发相应的动画。B-Roll视频片段通过assetUrl字段引用,并根据脚本段落的持续时间进行精确编排。TTS音频文件(如果生成)会作为assets.ttsAudio被引用,并在渲染时与视频同步播放。
本节来源
依赖分析
项目依赖清晰地分为前端和后端两部分。前端依赖remotion、react和recharts用于视频渲染和UI构建,zod用于数据验证。后端依赖google-generativeai(Gemini)、openai(Whisper)和pexels-api用于AI处理和媒体获取。render_props.json作为唯一的依赖接口,确保了前后端的松耦合。这种设计允许团队独立开发和测试前后端,只需确保数据契约的稳定性。
graph TD
A[Remotion] --> B[React]
A --> C[Recharts]
A --> D[Zod]
E[Python Backend] --> F[Gemini API]
E --> G[Whisper API]
E --> H[Pexels API]
I[render_props.json] --> A
I --> E
图源
性能考虑
为了优化渲染性能,组件使用了React.memo进行记忆化,防止不必要的重渲染。图表的Y轴域(yAxisDomain)基于完整时间线计算,而不是当前可见数据,这可以防止Y轴在播放过程中跳动。对于长视频,建议在remotion.config.ts中设置Config.setOverwriteOutput(true)以覆盖输出,并使用jpeg格式作为视频图像格式以平衡质量和性能。本地预览时,可以使用npm run dev启动Remotion Studio进行快速迭代。
本节来源
故障排除指南
常见问题包括API密钥缺失、依赖安装失败和数据格式错误。确保.env文件包含有效的GEMINI_API_KEY、OPENAI_API_KEY和PEXELS_API_KEY。运行npm install和pip install -r requirements.txt以安装所有依赖。使用npm run type-check和npm run lint检查前端代码,使用python -m pytest测试后端逻辑。如果渲染失败,检查render_props.json是否符合RenderPropsSchema的定义,可以使用validateRenderProps函数进行验证。
本节来源
结论
本系统成功地将复杂的财务数据和静态报告转化为生动、直观的动态视频。通过render_props.json这一精心设计的数据契约,实现了Python后端与Remotion前端的无缝集成。系统具备良好的可扩展性,可以通过添加新的React组件和更新数据契约来支持新的动画模板或交互式元素。未来的工作可以集中在优化AI脚本生成的质量和增加更多类型的可视化图表上。