AI-video-lifeplan-demo/.qoder/repowiki/zh/content/架构设计/数据处理/数据处理.md

428 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据处理
<cite>
**本文引用的文件**
- [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)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件聚焦于数据处理子系统,围绕财务规划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:视频分析策略与数据结构定义(音频优先策略已实现,直接分析待实现)。
```mermaid
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](file://main.py#L33-L226)
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
- [backend/scripter.py](file://backend/scripter.py#L1-L69)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L1-L72)
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L1-L60)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L1-L91)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L1-L251)
章节来源
- [PROJECT_README.md](file://PROJECT_README.md#L132-L208)
- [main.py](file://main.py#L33-L226)
## 核心组件
- 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](file://backend/extractor.py#L1-L84)
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
- [backend/scripter.py](file://backend/scripter.py#L1-L69)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L1-L72)
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L1-L60)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L1-L91)
## 架构总览
数据处理子系统在 main.py 的流水线中承担“提取”阶段,随后进入“生成脚本”“抓取素材”“构建渲染参数”“渲染视频”的后续步骤。PDF 提取与视频提取分别由 extractor.py 中的 PDFExtractor 与 VideoExtractor 负责;最终的渲染参数由 data_builder.py 生成,前端通过 render-props-types.ts 的类型定义进行强约束。
```mermaid
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](file://main.py#L48-L226)
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
- [backend/data_builder.py](file://backend/data_builder.py#L150-L200)
- [backend/scripter.py](file://backend/scripter.py#L1-L69)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L1-L72)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L117-L135)
## 详细组件分析
### PDF提取器(PDFExtractor)
PDFExtractor 负责调用 Gemini API 对财务规划PDF进行解析,抽取客户基本信息、资产状况、收支数据等关键字段。当前实现为占位,抛出未实现异常,留待完成。
```mermaid
classDiagram
class PDFExtractor {
+api_key : str
+extract(pdf_path) Dict
}
```
图表来源
- [backend/extractor.py](file://backend/extractor.py#L15-L43)
章节来源
- [backend/extractor.py](file://backend/extractor.py#L15-L43)
### 视频提取器(VideoExtractor)
VideoExtractor 负责调用 Whisper API 对视频进行转录与时间戳抽取,返回包含转录文本、时间戳与关键字的结构化数据。当前实现为占位,抛出未实现异常,留待完成。
```mermaid
classDiagram
class VideoExtractor {
+api_key : str
+extract(video_path) Dict
}
```
图表来源
- [backend/extractor.py](file://backend/extractor.py#L45-L72)
章节来源
- [backend/extractor.py](file://backend/extractor.py#L45-L72)
### 财务模拟与图表数据构建(FinancialSimulator)
FinancialSimulator 基于提取参数进行年金现金流模拟,产出资产枯竭与现金流量两种图表数据。其核心逻辑包括:
- 按年龄循环推进,计算每年收入、通胀调整支出、事件成本;
- 当资产余额为正时应用投资回报,为负时应用赤字利息(复利);
- 将年度快照转换为现金流量图表数据,便于前端可视化。
```mermaid
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(["结束"])
```
图表来源
- [backend/data_builder.py](file://backend/data_builder.py#L15-L148)
章节来源
- [backend/data_builder.py](file://backend/data_builder.py#L15-L148)
### 渲染参数构建(build_chart_data)
该函数将 PDF 提取结果输入到 FinancialSimulator,得到两条时间线并打包为 render_props.json 的 charts 字段,供前端渲染使用。
```mermaid
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 对象
```
图表来源
- [backend/data_builder.py](file://backend/data_builder.py#L150-L200)
章节来源
- [backend/data_builder.py](file://backend/data_builder.py#L150-L200)
### 视频分析策略(video_processor)
视频分析模块提供两种策略:
- 音频优先策略:先提取音频,再调用 Whisper 进行转录与时间戳抽取;
- 直接分析策略:直接将视频送入 Gemini 进行分析(当前未实现)。
```mermaid
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 : "包含"
```
图表来源
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L31-L60)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L12-L91)
章节来源
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L1-L60)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L1-L91)
### 主流水线中的协调机制(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 渲染引擎。
```mermaid
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"]
```
图表来源
- [main.py](file://main.py#L48-L226)
- [backend/data_builder.py](file://backend/data_builder.py#L150-L200)
章节来源
- [main.py](file://main.py#L48-L226)
## 依赖关系分析
- 外部依赖:Google Gemini API(PDF解析、脚本生成)、OpenAI Whisper(音频转录)、Pexels API(B-Roll抓取)、FFmpeg(视频处理工具链)。
- 环境变量:GEMINI_API_KEY、OPENAI_API_KEY、PEXELS_API_KEY,以及默认财务参数(通胀率、赤字利率、投资回报率)。
- 类型契约:前端通过 render-props-types.ts 定义了严格的渲染参数结构,确保后端输出与前端消费一致。
```mermaid
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](file://.env.example#L1-L23)
- [requirements.txt](file://requirements.txt#L1-L34)
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L1-L60)
- [main.py](file://main.py#L48-L226)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L117-L135)
章节来源
- [.env.example](file://.env.example#L1-L23)
- [requirements.txt](file://requirements.txt#L1-L34)
- [PROJECT_README.md](file://PROJECT_README.md#L132-L208)
## 性能考量
- 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](file://backend/extractor.py#L15-L43)
- [backend/scripter.py](file://backend/scripter.py#L14-L49)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L15-L42)
- [PROJECT_README.md](file://PROJECT_README.md#L218-L233)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L117-L135)
## 结论
本数据处理子系统以 extractor.py 为核心入口,结合 data_builder.py 的财务模拟能力,形成从 PDF/视频到结构化数据再到渲染参数的完整链路。当前模块多为占位实现,建议优先完成 PDF 与视频提取的提示工程与错误处理,再逐步完善脚本生成、B-Roll 抓取与视频分析策略。通过严格的类型契约与环境配置管理,可确保前后端协作稳定可靠。
## 附录
### 初学者数据提取流程图(PDF → 结构化数据)
```mermaid
flowchart TD
A["输入:财务规划PDF"] --> B["上传至 Gemini API"]
B --> C["提示工程:提取客户信息/资产/收支/事件"]
C --> D["结构化JSON输出"]
D --> E["main.py 接收并传递给后续模块"]
```
图表来源
- [backend/extractor.py](file://backend/extractor.py#L15-L43)
- [main.py](file://main.py#L85-L114)
### 初学者数据提取流程图(视频 → 结构化数据)
```mermaid
flowchart TD
A["输入:访谈视频"] --> B["音频优先策略:提取音频"]
B --> C["Whisper 转录与时间戳抽取"]
C --> D["结构化字典:转录文本/时间戳/关键字"]
D --> E["main.py 接收并传递给脚本与素材模块"]
```
图表来源
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L31-L60)
- [backend/extractor.py](file://backend/extractor.py#L45-L72)
- [main.py](file://main.py#L99-L114)
### 高级开发者:提示工程策略与数据验证模式
- 提示工程策略(PDF)
- 明确输出格式要求(JSON 字段清单),限定关键字段(客户姓名、年龄、退休年龄、寿命预期、资产、年收入、年支出、重大事件等);
- 引入上下文约束(货币单位、时间起点、生命周期范围),减少歧义;
- 使用示例与反例引导模型输出稳定结构。
- 提示工程策略(视频)
- 在音频优先策略下,先用 Whisper 获取高置信度转录,再用 Gemini 进行摘要与关键帧标注;
- 对时间戳与关键词进行一致性校验,避免漂移。
- 错误处理机制
- 初始化阶段严格校验 API 密钥是否存在;
- 对外部 API 返回进行重试与降级策略(如缓存上次结果);
- 对空结果与异常进行显式捕获与日志记录。
- 数据验证模式
- 前端使用 Zod Schema 对 render_props.json 进行运行时校验,保证字段类型与必填项一致;
- 后端在构建图表数据时进行边界值与合理性检查(如资产为负时标记 isCritical)。
章节来源
- [backend/extractor.py](file://backend/extractor.py#L15-L72)
- [backend/scripter.py](file://backend/scripter.py#L14-L49)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L140-L231)
### 实际代码示例(扩展新模板/新格式)
- 扩展 PDF 模板支持
- 在 PDFExtractor.extract 中实现:
- 上传 PDF 至 Gemini API;
- 构建针对新模板的提示工程,明确字段映射;
- 对输出进行模式匹配与校验,必要时回退到二次校正。
- 示例路径参考:[PDFExtractor.extract](file://backend/extractor.py#L23-L43)
- 处理不同格式的视频文件
- 在 VideoExtractor.extract 中实现:
- 通过 FFmpeg 提取音频并转码;
- 调用 Whisper API 获取转录与时间戳;
- 对多说话人场景增加 speaker 字段与分段策略。
- 示例路径参考:[VideoExtractor.extract](file://backend/extractor.py#L53-L71)
- 视频分析策略扩展
- 在 video_processor 中新增策略类,复用 VideoAnalysisResult/VideoSegment/KeyMoment 数据结构;
- 在 analyze_video 中注册新策略入口。
- 示例路径参考:
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L31-L60)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L12-L91)