377 lines
16 KiB
Markdown
377 lines
16 KiB
Markdown
# 数据提取
|
||
|
||
<cite>
|
||
**本文引用的文件列表**
|
||
- [backend/extractor.py](file://backend/extractor.py)
|
||
- [backend/data_builder.py](file://backend/data_builder.py)
|
||
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py)
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py)
|
||
- [backend/investigate_video_extraction.py](file://backend/investigate_video_extraction.py)
|
||
- [backend/investigate_subtitle_extraction.py](file://backend/investigate_subtitle_extraction.py)
|
||
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts)
|
||
- [PROJECT_README.md](file://PROJECT_README.md)
|
||
- [requirements.txt](file://requirements.txt)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖关系分析](#依赖关系分析)
|
||
7. [性能考量](#性能考量)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 简介
|
||
本文件聚焦于“数据提取”模块,系统性阐述两类输入数据的提取与结构化流程:
|
||
- PDF 报告(财务规划类):通过大模型解析并抽取结构化信息(如客户基本信息、资产/收入/支出、重大事件、保险建议等)。
|
||
- 访谈视频:通过音频转写与时间戳抽取,生成可用于视频剪辑与B-Roll素材匹配的结构化片段。
|
||
|
||
同时,文档说明数据提取后的内部表示形式、与后续脚本生成与数据构建模块的数据契约关系,并给出常见问题与扩展方法。
|
||
|
||
## 项目结构
|
||
数据提取相关的核心文件分布如下:
|
||
- 提取层:backend/extractor.py(待实现)、backend/video_processor/utils.py(FFmpeg工具)、backend/investigate_video_extraction.py 与 backend/investigate_subtitle_extraction.py(演示实现)
|
||
- 结构化输出与契约:backend/video_processor/schemas.py(视频分析结果结构)、frontend/src/render-props-types.ts(前端渲染契约)
|
||
- 数据构建:backend/data_builder.py(基于PDF提取参数进行财务模拟)
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "输入"
|
||
PDF["PDF 报告"]
|
||
VIDEO["访谈视频"]
|
||
end
|
||
subgraph "提取层"
|
||
EX["extractor.py<br/>PDF/视频提取接口待实现"]
|
||
VU["video_processor/utils.py<br/>FFmpeg 工具"]
|
||
IVV["investigate_video_extraction.py<br/>视频提取演示"]
|
||
ISV["investigate_subtitle_extraction.py<br/>字幕/转写演示"]
|
||
end
|
||
subgraph "结构化输出"
|
||
VS["schemas.py<br/>VideoSegment/KeyMoment/VideoAnalysisResult"]
|
||
RP["render-props-types.ts<br/>前端渲染契约"]
|
||
end
|
||
subgraph "后续模块"
|
||
DB["data_builder.py<br/>财务模拟与图表数据"]
|
||
end
|
||
PDF --> EX
|
||
VIDEO --> EX
|
||
VIDEO --> VU
|
||
EX --> VS
|
||
VS --> RP
|
||
EX --> DB
|
||
DB --> RP
|
||
```
|
||
|
||
图表来源
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
- [backend/investigate_video_extraction.py](file://backend/investigate_video_extraction.py#L1-L291)
|
||
- [backend/investigate_subtitle_extraction.py](file://backend/investigate_subtitle_extraction.py#L1-L413)
|
||
- [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)
|
||
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
|
||
|
||
章节来源
|
||
- [PROJECT_README.md](file://PROJECT_README.md#L132-L142)
|
||
- [requirements.txt](file://requirements.txt#L1-L34)
|
||
|
||
## 核心组件
|
||
- PDF 提取器(PDFExtractor):面向财务规划PDF,期望返回结构化数据(客户信息、财务数据、重大事件、保险建议等),当前为占位实现,需接入大模型API完成解析。
|
||
- 视频提取器(VideoExtractor):面向访谈视频,期望返回转写文本、时间戳片段、推荐B-Roll片段等,当前为占位实现,需接入Whisper与FFmpeg。
|
||
- 视频处理工具(FFmpeg封装):提供视频时长查询、音频提取、视频切片等能力,支撑视频提取流程。
|
||
- 视频结构化模式(schemas.py):定义视频片段、关键时刻、完整分析结果的标准结构,确保与前端契约一致。
|
||
- 数据构建(data_builder.py):消费PDF提取结果,进行财务模拟与图表数据转换,输出与前端契约一致的结构。
|
||
|
||
章节来源
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L1-L91)
|
||
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
|
||
|
||
## 架构总览
|
||
下图展示了从原始文件到结构化数据再到前端渲染的整体流程。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant U as "用户"
|
||
participant EX as "extractor.py"
|
||
participant VU as "FFmpeg 工具"
|
||
participant IV as "视频提取演示"
|
||
participant IS as "字幕提取演示"
|
||
participant VS as "schemas.py"
|
||
participant DB as "data_builder.py"
|
||
participant RP as "render-props-types.ts"
|
||
U->>EX : 提供 PDF/视频
|
||
EX->>EX : 占位实现待完成
|
||
EX->>VU : 使用 FFmpeg 获取时长/提取音频视频流程
|
||
EX->>IV : 参考演示实现上传视频、结构化抽取
|
||
EX->>IS : 参考演示实现字幕/转写
|
||
EX-->>VS : 输出 VideoSegment/KeyMoment/VideoAnalysisResult
|
||
EX-->>DB : 输出 PDF 结构化数据
|
||
DB-->>RP : 输出图表数据资产枯竭/现金流
|
||
VS-->>RP : 输出视频片段与脚本同步点
|
||
```
|
||
|
||
图表来源
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
- [backend/investigate_video_extraction.py](file://backend/investigate_video_extraction.py#L1-L291)
|
||
- [backend/investigate_subtitle_extraction.py](file://backend/investigate_subtitle_extraction.py#L1-L413)
|
||
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L1-L91)
|
||
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
|
||
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L1-L251)
|
||
|
||
## 详细组件分析
|
||
|
||
### PDF 提取流程与内部表示
|
||
- 输入:财务规划PDF(日文)。
|
||
- 处理目标:结构化关键信息,便于后续财务模拟与脚本生成。
|
||
- 当前状态:占位实现,需接入大模型API完成PDF解析与结构化输出。
|
||
- 内部表示(预期):包含客户信息、财务数据、重大事件、保险建议等字段,作为data_builder的输入。
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["开始:接收 PDF 路径"]) --> CheckKey["检查环境变量<br/>GEMINI_API_KEY"]
|
||
CheckKey --> KeyOK{"密钥存在?"}
|
||
KeyOK --> |否| RaiseErr["抛出异常:缺少 API 密钥"]
|
||
KeyOK --> |是| Upload["上传 PDF 至 Gemini API"]
|
||
Upload --> Prompt["构造提示词<br/>要求结构化 JSON 输出"]
|
||
Prompt --> Parse["解析响应并校验结构"]
|
||
Parse --> Done(["返回结构化数据"])
|
||
RaiseErr --> End(["结束"])
|
||
Done --> End
|
||
```
|
||
|
||
图表来源
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
|
||
章节来源
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
|
||
### 视频元数据与转写流程(FFmpeg + Whisper)
|
||
- 元数据提取:使用ffprobe获取视频时长;使用ffmpeg提取音频(采样率、编码等可配置)。
|
||
- 转写与时间戳:参考演示脚本,先提取音频,再调用Whisper API进行转写与时间戳抽取。
|
||
- 片段结构化:输出VideoSegment/KeyMoment等结构,便于后续B-Roll匹配与视频剪辑。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant V as "视频文件"
|
||
participant U as "FFmpeg 工具"
|
||
participant W as "Whisper API"
|
||
participant S as "schemas.py"
|
||
participant R as "render-props-types.ts"
|
||
V->>U : get_video_duration()
|
||
U-->>V : 返回时长秒
|
||
V->>U : extract_audio()
|
||
U-->>V : 输出音频文件
|
||
V->>W : 上传音频并请求转写
|
||
W-->>V : 返回转写文本与时间戳
|
||
V->>S : 组装 VideoSegment/KeyMoment
|
||
S-->>R : 输出符合前端契约的结构
|
||
```
|
||
|
||
图表来源
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
- [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)
|
||
|
||
章节来源
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
- [backend/investigate_video_extraction.py](file://backend/investigate_video_extraction.py#L1-L291)
|
||
- [backend/investigate_subtitle_extraction.py](file://backend/investigate_subtitle_extraction.py#L1-L413)
|
||
- [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)
|
||
|
||
### 视频结构化模式(schemas.py)
|
||
- VideoSegment:视频片段,包含起止时间、描述、转写、重要性、标签、说话人等。
|
||
- KeyMoment:关键时刻,包含时间戳、类型(引述/图表/情感/动作)、内容与上下文。
|
||
- VideoAnalysisResult:完整分析结果,包含源视频路径、总时长、策略、片段列表、关键时刻列表与额外元数据。
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class VideoSegment {
|
||
+float start_time
|
||
+float end_time
|
||
+string description
|
||
+string transcript
|
||
+string importance
|
||
+string[] tags
|
||
+string speaker
|
||
+float duration
|
||
+to_dict() dict
|
||
}
|
||
class KeyMoment {
|
||
+float timestamp
|
||
+string type
|
||
+string content
|
||
+string context
|
||
+to_dict() dict
|
||
}
|
||
class VideoAnalysisResult {
|
||
+string source_video
|
||
+float duration
|
||
+string strategy
|
||
+VideoSegment[] segments
|
||
+KeyMoment[] key_moments
|
||
+dict metadata
|
||
+to_dict() dict
|
||
+get_high_importance_segments() VideoSegment[]
|
||
+get_quotes() KeyMoment[]
|
||
}
|
||
VideoAnalysisResult --> VideoSegment : "包含"
|
||
VideoAnalysisResult --> KeyMoment : "包含"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L1-L91)
|
||
|
||
章节来源
|
||
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L1-L91)
|
||
|
||
### 数据契约与前后端衔接
|
||
- 前端契约(render-props-types.ts):定义YearlySnapshot、CashFlowData、ScriptSegment、AssetCollection等类型,确保后端生成的数据与前端渲染一致。
|
||
- 后端数据构建(data_builder.py):将PDF提取参数转化为财务模拟时间线与图表数据,输出与前端契约一致的结构。
|
||
|
||
```mermaid
|
||
erDiagram
|
||
YEARLYSNAPSHOT {
|
||
int year
|
||
int repAge
|
||
int spouseAge
|
||
int income
|
||
int expenditure
|
||
int assetBalance
|
||
string[] events
|
||
boolean isCritical
|
||
}
|
||
CASHFLOWDATA {
|
||
int year
|
||
int age
|
||
int totalIncome
|
||
int livingExpense
|
||
int housingExpense
|
||
int educationExpense
|
||
int taxExpense
|
||
int eventExpense
|
||
int totalExpense
|
||
int netCashFlow
|
||
int assetBalance
|
||
}
|
||
RENDERPROPS {
|
||
string title
|
||
string currencyUnit
|
||
int duration
|
||
string clientName
|
||
string generatedAt
|
||
}
|
||
RENDERPROPS ||--o{ YEARLYSNAPSHOT : "assetDepletion.timeline"
|
||
RENDERPROPS ||--o{ CASHFLOWDATA : "cashFlow.timeline"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
|
||
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L1-L251)
|
||
|
||
章节来源
|
||
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
|
||
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L1-L251)
|
||
|
||
## 依赖关系分析
|
||
- 外部依赖:Google Gemini(PDF/视频理解)、OpenAI Whisper(音频转写)、FFmpeg/ffprobe(媒体处理)、Pexels(B-Roll素材检索,当前占位)。
|
||
- 内部耦合:extractor.py 与 video_processor/utils.py、video_processor/schemas.py 存在潜在协作关系;data_builder.py 依赖 PDF 提取结果;前端契约约束后端输出。
|
||
|
||
```mermaid
|
||
graph LR
|
||
REQ["requirements.txt"] --> GEM["google-generativeai"]
|
||
REQ --> OAI["openai"]
|
||
REQ --> FFPY["ffmpeg-python"]
|
||
REQ --> REQ["requests"]
|
||
EX["extractor.py"] --> GEM
|
||
EX --> OAI
|
||
EX --> FFPY
|
||
VU["video_processor/utils.py"] --> FFPY
|
||
VS["video_processor/schemas.py"] --> RP["render-props-types.ts"]
|
||
DB["data_builder.py"] --> RP
|
||
```
|
||
|
||
图表来源
|
||
- [requirements.txt](file://requirements.txt#L1-L34)
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
- [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)
|
||
- [backend/data_builder.py](file://backend/data_builder.py#L1-L200)
|
||
|
||
章节来源
|
||
- [requirements.txt](file://requirements.txt#L1-L34)
|
||
|
||
## 性能考量
|
||
- API成本控制:视频/音频上传与转写会产生Token/调用费用,应优先选择合适粒度(电影级摘要 vs 秒级/词级时间戳)以平衡精度与成本。
|
||
- 媒体处理优化:音频提取采用流复制(stream copy)可避免重编码,提升速度;批量处理时注意并发与资源限制。
|
||
- 缓存与复用:翻译与API调用结果可缓存,减少重复请求;视频片段与B-Roll素材可本地缓存以降低网络开销。
|
||
|
||
## 故障排查指南
|
||
- API密钥缺失
|
||
- 现象:初始化PDF/视频提取器时报错。
|
||
- 排查:确认环境变量是否正确设置;检查.env文件是否存在且包含有效密钥。
|
||
- FFmpeg/ffprobe不可用
|
||
- 现象:获取视频时长或提取音频失败。
|
||
- 排查:安装FFmpeg/ffprobe并加入PATH;使用工具函数检测可用性。
|
||
- PDF格式不兼容或加密
|
||
- 现象:PDF解析失败或返回空数据。
|
||
- 排查:确认PDF可读且未加密;若为扫描版PDF,考虑OCR预处理;优先使用大模型直接解析PDF而非本地库。
|
||
- 视频/音频质量差导致转写不准
|
||
- 现象:转写文本与实际内容不符。
|
||
- 排查:提高音频采样率、清理背景噪音;必要时人工校正关键片段。
|
||
|
||
章节来源
|
||
- [PROJECT_README.md](file://PROJECT_README.md#L217-L233)
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
|
||
## 结论
|
||
- 当前数据提取模块处于占位阶段,PDF与视频提取逻辑尚未实现,但已明确技术栈与数据契约。
|
||
- 建议优先完成以下工作:PDF解析(Gemini API)、视频转写(Whisper)、FFmpeg工具链完善、结构化输出规范化(schemas)。
|
||
- 完成后,数据将严格遵循前端契约,无缝衔接财务模拟与视频渲染流程。
|
||
|
||
## 附录
|
||
|
||
### 接口调用方式与错误处理(基于现有占位实现)
|
||
- PDF提取
|
||
- 函数入口:[extract_pdf_data](file://backend/extractor.py#L74-L84)
|
||
- 类入口:[PDFExtractor.extract](file://backend/extractor.py#L23-L43)
|
||
- 错误处理:当前抛出未实现异常,需补充API调用与参数校验。
|
||
- 视频提取
|
||
- 函数入口:[extract_video_data](file://backend/extractor.py#L79-L84)
|
||
- 类入口:[VideoExtractor.extract](file://backend/extractor.py#L53-L72)
|
||
- 错误处理:当前抛出未实现异常,需补充FFmpeg与Whisper调用。
|
||
- FFmpeg工具
|
||
- 获取时长:[get_video_duration](file://backend/video_processor/utils.py#L13-L47)
|
||
- 提取音频:[extract_audio](file://backend/video_processor/utils.py#L49-L95)
|
||
- 切片视频:[slice_video](file://backend/video_processor/utils.py#L97-L146)
|
||
- 检测安装:[check_ffmpeg_installed](file://backend/video_processor/utils.py#L148-L164)
|
||
|
||
章节来源
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L1-L164)
|
||
|
||
### 扩展自定义解析器的方法
|
||
- PDF解析器扩展
|
||
- 在PDFExtractor中实现extract方法,调用Gemini API并按预期字段返回。
|
||
- 建议:增加参数校验、响应解析与schema验证。
|
||
- 视频解析器扩展
|
||
- 在VideoExtractor中实现extract方法,调用Whisper API并解析时间戳。
|
||
- 建议:支持多粒度(电影级/秒级/词级)与多策略(视频直传/音频转写)。
|
||
- 媒体处理扩展
|
||
- 在video_processor/utils.py中新增工具函数,统一管理FFmpeg命令与错误处理。
|
||
- 契约一致性
|
||
- 保持输出结构与frontend/src/render-props-types.ts一致,避免前后端不匹配。
|
||
|
||
章节来源
|
||
- [backend/extractor.py](file://backend/extractor.py#L1-L84)
|
||
- [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) |