19 KiB
数据处理
**本文引用的文件** - [main.py](file://main.py) - [PROJECT_README.md](file://PROJECT_README.md) - [backend/extractor.py](file://backend/extractor.py) - [backend/data_builder.py](file://backend/data_builder.py) - [backend/scripter.py](file://backend/scripter.py) - [backend/media_fetcher.py](file://backend/media_fetcher.py) - [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py) - [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py) - [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts) - [.env.example](file://.env.example) - [requirements.txt](file://requirements.txt) - [tests/test_video_processor.py](file://tests/test_video_processor.py)目录
简介
本文件聚焦于数据处理子系统,围绕财务规划PDF与访谈视频的提取流程展开,解释以下要点:
- extractor.py 模块如何通过 Google Gemini API 解析财务规划PDF报告,抽取客户基本信息、资产状况、收支数据等关键字段;
- main.py 中的 extract_pdf 与 extract_video 方法在整体流水线中的协调机制;
- 针对初学者的数据提取流程图,展示从原始文件到结构化数据的转换过程;
- 面向高级开发者的提示工程策略、错误处理机制与数据验证模式;
- 实际代码示例路径,帮助扩展支持新的PDF模板或处理不同格式的视频文件。
项目结构
数据处理子系统位于 backend 目录,主要由以下模块组成:
- extractor.py:负责 PDF 与视频的结构化提取(当前为占位实现,预留 API 调用与提示工程);
- data_builder.py:基于提取结果进行财务模拟与图表数据构建;
- scripter.py:基于 PDF 与视频内容生成日语叙述脚本(占位);
- media_fetcher.py:基于关键词抓取 B-Roll 视频(占位);
- video_processor:视频分析策略与数据结构定义(音频优先策略已实现,直接分析待实现)。
graph TB
A["main.py<br/>主入口与流水线编排"] --> B["backend/extractor.py<br/>PDF/视频提取器"]
A --> C["backend/data_builder.py<br/>财务模拟与图表数据构建"]
A --> D["backend/scripter.py<br/>脚本生成器"]
A --> E["backend/media_fetcher.py<br/>B-Roll抓取器"]
A --> F["backend/video_processor/__init__.py<br/>视频分析策略入口"]
F --> G["backend/video_processor/schemas.py<br/>视频分析数据结构"]
A --> H["frontend/src/render-props-types.ts<br/>渲染契约类型定义"]
图表来源
- main.py
- backend/extractor.py
- backend/data_builder.py
- backend/scripter.py
- backend/media_fetcher.py
- backend/video_processor/init.py
- backend/video_processor/schemas.py
- frontend/src/render-props-types.ts
章节来源
核心组件
- PDFExtractor:封装 PDF 提取逻辑,初始化时校验 Gemini API 密钥,提供 extract 接口用于返回结构化数据字典(当前抛出未实现异常,留待实现)。
- VideoExtractor:封装视频提取逻辑,初始化时校验 OpenAI API 密钥,提供 extract 接口用于返回包含转录文本、时间戳与关键字的字典(当前抛出未实现异常,留待实现)。
- FinancialSimulator:根据提取参数进行年金现金流模拟,产出资产枯竭与现金流量两种图表数据,支持通胀、投资回报与赤字复利等参数。
- ScriptGenerator:封装脚本生成逻辑,初始化时校验 Gemini API 密钥,提供 generate 接口用于返回脚本段落与同步点(当前抛出未实现异常,留待实现)。
- MediaFetcher:封装 B-Roll 抓取逻辑,初始化时校验 Pexels API 密钥,提供 fetch_broll 接口用于返回按关键词分组的视频链接(当前抛出未实现异常,留待实现)。
- VideoProcessor:提供 analyze_video 入口,支持“音频优先”与“直接分析”两种策略;音频优先策略依赖 Whisper 进行转录与时间戳抽取,直接分析策略待实现。
章节来源
- backend/extractor.py
- backend/data_builder.py
- backend/scripter.py
- backend/media_fetcher.py
- backend/video_processor/init.py
- backend/video_processor/schemas.py
架构总览
数据处理子系统在 main.py 的流水线中承担“提取”阶段,随后进入“生成脚本”“抓取素材”“构建渲染参数”“渲染视频”的后续步骤。PDF 提取与视频提取分别由 extractor.py 中的 PDFExtractor 与 VideoExtractor 负责;最终的渲染参数由 data_builder.py 生成,前端通过 render-props-types.ts 的类型定义进行强约束。
sequenceDiagram
participant CLI as "命令行"
participant Main as "main.py"
participant Ext as "backend/extractor.py"
participant Sim as "backend/data_builder.py"
participant Script as "backend/scripter.py"
participant Media as "backend/media_fetcher.py"
participant Render as "Remotion 前端"
CLI->>Main : 启动流水线
Main->>Ext : extract_pdf()
Ext-->>Main : 结构化PDF数据
Main->>Ext : extract_video()
Ext-->>Main : 视频转录与时间戳
Main->>Script : generate_script(pdf_data, video_data)
Script-->>Main : 叙述脚本
Main->>Media : fetch_broll(script)
Media-->>Main : B-Roll资源
Main->>Sim : build_chart_data(pdf_data)
Sim-->>Main : 图表数据
Main->>Render : 写入 render_props.json 并触发渲染
Render-->>CLI : 输出视频
图表来源
- main.py
- backend/extractor.py
- backend/data_builder.py
- backend/scripter.py
- backend/media_fetcher.py
- frontend/src/render-props-types.ts
详细组件分析
PDF提取器(PDFExtractor)
PDFExtractor 负责调用 Gemini API 对财务规划PDF进行解析,抽取客户基本信息、资产状况、收支数据等关键字段。当前实现为占位,抛出未实现异常,留待完成。
classDiagram
class PDFExtractor {
+api_key : str
+extract(pdf_path) Dict
}
图表来源
章节来源
视频提取器(VideoExtractor)
VideoExtractor 负责调用 Whisper API 对视频进行转录与时间戳抽取,返回包含转录文本、时间戳与关键字的结构化数据。当前实现为占位,抛出未实现异常,留待完成。
classDiagram
class VideoExtractor {
+api_key : str
+extract(video_path) Dict
}
图表来源
章节来源
财务模拟与图表数据构建(FinancialSimulator)
FinancialSimulator 基于提取参数进行年金现金流模拟,产出资产枯竭与现金流量两种图表数据。其核心逻辑包括:
- 按年龄循环推进,计算每年收入、通胀调整支出、事件成本;
- 当资产余额为正时应用投资回报,为负时应用赤字利息(复利);
- 将年度快照转换为现金流量图表数据,便于前端可视化。
flowchart TD
Start(["开始模拟"]) --> Init["读取参数<br/>当前年龄/退休年龄/寿命预期/资产/收入/支出/事件"]
Init --> Loop{"按年龄循环"}
Loop --> |计算| Income["收入 = 年收入 或 0退休后"]
Income --> Inflation["通胀调整支出"]
Inflation --> Events["事件成本累加"]
Events --> Net["净现金流 = 收入 - 支出 - 事件"]
Net --> Balance{"资产余额 >= 0 ?"}
Balance --> |是| Invest["正余额:应用投资回报"]
Balance --> |否| Deficit["负余额:应用赤字利息"]
Invest --> Snapshot["生成年度快照"]
Deficit --> Snapshot
Snapshot --> Next{"是否到达寿命预期?"}
Next --> |否| Loop
Next --> |是| Cashflow["转换为现金流量数据"]
Cashflow --> End(["结束"])
图表来源
章节来源
渲染参数构建(build_chart_data)
该函数将 PDF 提取结果输入到 FinancialSimulator,得到两条时间线并打包为 render_props.json 的 charts 字段,供前端渲染使用。
sequenceDiagram
participant Caller as "调用方"
participant Builder as "build_chart_data"
participant Simulator as "FinancialSimulator"
Caller->>Builder : 传入 pdf_data
Builder->>Simulator : simulate_timeline(...)
Simulator-->>Builder : 年度快照列表
Builder->>Simulator : build_cashflow_data(timeline)
Simulator-->>Builder : 现金流量数据
Builder-->>Caller : 返回 charts 对象
图表来源
章节来源
视频分析策略(video_processor)
视频分析模块提供两种策略:
- 音频优先策略:先提取音频,再调用 Whisper 进行转录与时间戳抽取;
- 直接分析策略:直接将视频送入 Gemini 进行分析(当前未实现)。
classDiagram
class VideoProcessor {
+analyze_video(video_path, strategy, config) VideoAnalysisResult
}
class AudioFirstStrategy {
+analyze(video_path) VideoAnalysisResult
}
class DirectStrategy {
+analyze(video_path) VideoAnalysisResult
}
class VideoAnalysisResult {
+source_video : str
+duration : float
+strategy : str
+segments : list
+key_moments : list
+metadata : dict
+to_dict() dict
+get_high_importance_segments() list
+get_quotes() list
}
class VideoSegment {
+start_time : float
+end_time : float
+description : str
+transcript : str
+importance : str
+tags : list
+speaker : str
+duration : float
+to_dict() dict
}
class KeyMoment {
+timestamp : float
+type : str
+content : str
+context : str
+to_dict() dict
}
VideoProcessor --> AudioFirstStrategy : "音频优先"
VideoProcessor --> DirectStrategy : "直接分析"
AudioFirstStrategy --> VideoAnalysisResult
DirectStrategy --> VideoAnalysisResult
VideoAnalysisResult --> VideoSegment : "包含"
VideoAnalysisResult --> KeyMoment : "包含"
图表来源
章节来源
主流水线中的协调机制(main.py)
main.py 的 VideoGeneratorPipeline.run 负责串联各阶段:
- Step 1:extract_pdf 调用 PDFExtractor(当前为占位),返回结构化数据;
- Step 2:extract_video 调用 VideoExtractor(当前为占位),返回转录与时间戳;
- Step 3:generate_script 调用 ScriptGenerator(当前为占位),返回脚本;
- Step 4:fetch_broll 调用 MediaFetcher(当前为占位),返回 B-Roll;
- Step 5:build_render_props 调用 data_builder.build_chart_data,生成图表数据;
- Step 6:render_video 调用 Remotion 渲染引擎。
flowchart TD
A["run()"] --> B["extract_pdf() 占位实现"]
A --> C["extract_video() 占位实现"]
A --> D["generate_script() 占位实现"]
A --> E["fetch_broll() 占位实现"]
A --> F["build_render_props() 调用 data_builder.build_chart_data()"]
F --> G["写入 render_props.json"]
A --> H["render_video() 调用 Remotion"]
图表来源
章节来源
依赖关系分析
- 外部依赖:Google Gemini API(PDF解析、脚本生成)、OpenAI Whisper(音频转录)、Pexels API(B-Roll抓取)、FFmpeg(视频处理工具链)。
- 环境变量:GEMINI_API_KEY、OPENAI_API_KEY、PEXELS_API_KEY,以及默认财务参数(通胀率、赤字利率、投资回报率)。
- 类型契约:前端通过 render-props-types.ts 定义了严格的渲染参数结构,确保后端输出与前端消费一致。
graph TB
Env[".env.example<br/>环境变量"] --> Keys["API密钥"]
Keys --> Gemini["Google Gemini API"]
Keys --> OpenAI["OpenAI Whisper API"]
Keys --> Pexels["Pexels API"]
FF["FFmpeg"] --> VP["backend/video_processor"]
VP --> Main["main.py"]
Main --> Types["frontend/src/render-props-types.ts"]
图表来源
- .env.example
- requirements.txt
- backend/video_processor/init.py
- main.py
- frontend/src/render-props-types.ts
章节来源
性能考量
- API 调用成本控制:PDF 与视频提取均依赖外部 LLM 与转录服务,建议:
- 批量请求与缓存重复任务结果;
- 控制并发数量,避免触发配额限制;
- 使用本地缓存翻译与关键词映射,减少重复 API 调用。
- 视频处理优化:音频优先策略可显著降低视频上传体积,建议优先采用该策略;同时合理设置语言与分段长度以提升转录质量。
- 模拟计算优化:FinancialSimulator 的循环次数与复杂度与寿命预期成线性关系,可通过参数裁剪或并行化(如多进程)加速大规模场景。
故障排查指南
- API 密钥缺失
- 现象:初始化 PDFExtractor/VideoExtractor/ScriptGenerator/MediaFetcher 时抛出异常。
- 处理:复制 .env.example 到 .env 并填入有效密钥。
- PDF 提取失败
- 现象:extract_pdf 占位抛出未实现异常或外部 API 返回错误。
- 处理:检查 PDF 是否可读、网络连通性与配额;确认 Gemini API 版本与权限。
- 视频转录失败
- 现象:extract_video 占位抛出未实现异常或 Whisper 返回空结果。
- 处理:确认 FFmpeg 已安装且在 PATH 中;检查音频质量与语言设置。
- 渲染参数不匹配
- 现象:前端类型校验失败。
- 处理:对照 render-props-types.ts 的接口定义,逐项核对字段类型与必填项。
章节来源
- backend/extractor.py
- backend/scripter.py
- backend/media_fetcher.py
- PROJECT_README.md
- frontend/src/render-props-types.ts
结论
本数据处理子系统以 extractor.py 为核心入口,结合 data_builder.py 的财务模拟能力,形成从 PDF/视频到结构化数据再到渲染参数的完整链路。当前模块多为占位实现,建议优先完成 PDF 与视频提取的提示工程与错误处理,再逐步完善脚本生成、B-Roll 抓取与视频分析策略。通过严格的类型契约与环境配置管理,可确保前后端协作稳定可靠。
附录
初学者数据提取流程图(PDF → 结构化数据)
flowchart TD
A["输入:财务规划PDF"] --> B["上传至 Gemini API"]
B --> C["提示工程:提取客户信息/资产/收支/事件"]
C --> D["结构化JSON输出"]
D --> E["main.py 接收并传递给后续模块"]
图表来源
初学者数据提取流程图(视频 → 结构化数据)
flowchart TD
A["输入:访谈视频"] --> B["音频优先策略:提取音频"]
B --> C["Whisper 转录与时间戳抽取"]
C --> D["结构化字典:转录文本/时间戳/关键字"]
D --> E["main.py 接收并传递给脚本与素材模块"]
图表来源
高级开发者:提示工程策略与数据验证模式
- 提示工程策略(PDF)
- 明确输出格式要求(JSON 字段清单),限定关键字段(客户姓名、年龄、退休年龄、寿命预期、资产、年收入、年支出、重大事件等);
- 引入上下文约束(货币单位、时间起点、生命周期范围),减少歧义;
- 使用示例与反例引导模型输出稳定结构。
- 提示工程策略(视频)
- 在音频优先策略下,先用 Whisper 获取高置信度转录,再用 Gemini 进行摘要与关键帧标注;
- 对时间戳与关键词进行一致性校验,避免漂移。
- 错误处理机制
- 初始化阶段严格校验 API 密钥是否存在;
- 对外部 API 返回进行重试与降级策略(如缓存上次结果);
- 对空结果与异常进行显式捕获与日志记录。
- 数据验证模式
- 前端使用 Zod Schema 对 render_props.json 进行运行时校验,保证字段类型与必填项一致;
- 后端在构建图表数据时进行边界值与合理性检查(如资产为负时标记 isCritical)。
章节来源
实际代码示例(扩展新模板/新格式)
- 扩展 PDF 模板支持
- 在 PDFExtractor.extract 中实现:
- 上传 PDF 至 Gemini API;
- 构建针对新模板的提示工程,明确字段映射;
- 对输出进行模式匹配与校验,必要时回退到二次校正。
- 示例路径参考:PDFExtractor.extract
- 在 PDFExtractor.extract 中实现:
- 处理不同格式的视频文件
- 在 VideoExtractor.extract 中实现:
- 通过 FFmpeg 提取音频并转码;
- 调用 Whisper API 获取转录与时间戳;
- 对多说话人场景增加 speaker 字段与分段策略。
- 示例路径参考:VideoExtractor.extract
- 在 VideoExtractor.extract 中实现:
- 视频分析策略扩展
- 在 video_processor 中新增策略类,复用 VideoAnalysisResult/VideoSegment/KeyMoment 数据结构;
- 在 analyze_video 中注册新策略入口。
- 示例路径参考: