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

358 lines
16 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/video_processor/__init__.py](file://backend/video_processor/__init__.py)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py)
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py)
- [backend/video_processor/strategy_direct.py](file://backend/video_processor/strategy_direct.py)
- [tests/test_video_processor.py](file://tests/test_video_processor.py)
- [tests/test_video_cli.py](file://tests/test_video_cli.py)
- [requirements.txt](file://requirements.txt)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件围绕“视频数据提取”功能展开,目标是帮助用户理解如何利用 OpenAI Whisper API 从访谈视频中提取语音转录内容与关键时间戳,并将其整合进视频生成流水线。文档重点覆盖:
- VideoExtractor 类的架构设计与职责边界
- 与 FFmpeg 的音频提取集成
- 调用 Whisper 进行语音识别并生成包含时间点、文本内容与关键词的时间戳序列
- 在主流程 main.py 中的 extract_video 方法如何承接该能力,形成完整的数据输出结构(如 transcription 与 timestamps)
- 面向新手的处理流程图与面向资深开发者的优化建议(音频预处理策略、关键词提取逻辑、视频片段分割建议、与 B-Roll 匹配机制)
## 项目结构
该项目采用“Python 后端 + Node.js 前端”的混合架构,视频数据提取位于 Python 后端模块中,主要涉及以下目录与文件:
- backend/extractor.py:PDF 与视频提取器的接口定义(当前视频提取仍为占位)
- backend/video_processor/:视频分析策略与工具集
- __init__.py:统一入口 analyze_video,按策略分发
- utils.py:FFmpeg 封装(音频提取、时长查询、视频切片)
- schemas.py:标准化的数据结构(VideoSegment、KeyMoment、VideoAnalysisResult)
- strategy_audio.py:音频优先策略(FFmpeg → Whisper → 文本分析)
- strategy_direct.py:直接视频分析策略(占位,后续扩展)
- tests/:独立测试脚本与单元测试
- main.py:视频生成流水线入口,负责调用 extract_video 并产出渲染所需数据
```mermaid
graph TB
A["main.py<br/>视频生成流水线"] --> B["backend/extractor.py<br/>PDF/视频提取器接口"]
A --> C["backend/video_processor/__init__.py<br/>analyze_video 入口"]
C --> D["backend/video_processor/strategy_audio.py<br/>音频优先策略"]
D --> E["backend/video_processor/utils.py<br/>FFmpeg 工具集"]
D --> F["backend/video_processor/schemas.py<br/>数据结构"]
C --> G["backend/video_processor/strategy_direct.py<br/>直接视频策略占位"]
```
图表来源
- [main.py](file://main.py#L99-L114)
- [backend/extractor.py](file://backend/extractor.py#L45-L84)
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L31-L60)
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py#L30-L187)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L49-L164)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L12-L91)
- [backend/video_processor/strategy_direct.py](file://backend/video_processor/strategy_direct.py#L27-L58)
章节来源
- [PROJECT_README.md](file://PROJECT_README.md#L132-L142)
- [main.py](file://main.py#L99-L114)
## 核心组件
- VideoExtractor(占位实现):定义了视频提取器的接口与返回结构,包含 transcription、timestamps、segments 字段,用于承载 Whisper 输出与后续脚本/字幕生成。
- AudioFirstStrategy:音频优先策略的核心实现,串联 FFmpeg 提取音频、Whisper 识别、文本段落化与关键时刻识别。
- FFmpeg 工具集:提供音频提取、视频切片、时长查询等基础能力。
- 数据结构:VideoSegment、KeyMoment、VideoAnalysisResult 统一输出格式,便于与前端渲染层对接。
章节来源
- [backend/extractor.py](file://backend/extractor.py#L45-L84)
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py#L30-L187)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L49-L164)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L12-L91)
## 架构总览
视频数据提取在整体流水线中的位置如下:
- 输入:PDF 报告与可选的面试视频
- 处理:若提供视频,则调用 extract_video,内部使用 analyze_video(音频优先策略),经 FFmpeg 提取音频后调用 Whisper 获取带时间戳的转录,再转换为 VideoAnalysisResult
- 输出:render_props.json 中的 script 与 assets 字段,供前端渲染
```mermaid
sequenceDiagram
participant U as "用户"
participant M as "main.py<br/>VideoGeneratorPipeline"
participant E as "backend/extractor.py<br/>VideoExtractor"
participant V as "backend/video_processor/__init__.py<br/>analyze_video"
participant S as "strategy_audio.py<br/>AudioFirstStrategy"
participant U2 as "utils.py<br/>FFmpeg 工具"
participant W as "OpenAI Whisper API"
U->>M : 运行命令可带 --video
M->>M : extract_video()mock
M->>E : 调用 extract_video_data(video_path)
E->>V : analyze_video(video_path, strategy="audio")
V->>S : 初始化 AudioFirstStrategy(config)
S->>U2 : extract_audio(video_path)
U2-->>S : 返回音频路径
S->>W : 调用 Whisperverbose_json,segment 级时间戳
W-->>S : 返回转录与时间戳
S->>S : _create_segments() 与 _identify_key_moments()
S-->>V : 返回 VideoAnalysisResult
V-->>E : 返回结果
E-->>M : 返回 transcription 与 timestampsmock
M-->>U : 产出渲染所需数据
```
图表来源
- [main.py](file://main.py#L99-L114)
- [backend/extractor.py](file://backend/extractor.py#L74-L84)
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L31-L60)
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py#L54-L187)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L49-L95)
## 详细组件分析
### VideoExtractor 类与接口
- 职责:定义视频提取器的统一接口,返回包含 transcription、timestamps、segments 的结构,便于后续脚本生成与字幕同步。
- 认证:通过 OPENAI_API_KEY 进行 Whisper 调用认证。
- 当前状态:占位实现,抛出未实现异常;实际功能由 analyze_video(音频优先策略)完成。
```mermaid
classDiagram
class VideoExtractor {
+api_key : str
+extract(video_path) Dict
}
class PDFExtractor {
+api_key : str
+extract(pdf_path) Dict
}
class VideoAnalysisResult {
+source_video : str
+duration : float
+strategy : str
+segments : VideoSegment[]
+key_moments : KeyMoment[]
+metadata : dict
+to_dict() dict
+get_high_importance_segments() VideoSegment[]
+get_quotes() KeyMoment[]
}
class VideoSegment {
+start_time : float
+end_time : float
+description : str
+transcript : str
+importance : str
+tags : str[]
+speaker : str
+duration() float
+to_dict() dict
}
class KeyMoment {
+timestamp : float
+type : str
+content : str
+context : str
+to_dict() dict
}
VideoExtractor --> VideoAnalysisResult : "生成"
VideoAnalysisResult --> VideoSegment : "包含"
VideoAnalysisResult --> KeyMoment : "包含"
```
图表来源
- [backend/extractor.py](file://backend/extractor.py#L45-L84)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L12-L91)
章节来源
- [backend/extractor.py](file://backend/extractor.py#L45-L84)
### 音频优先策略(AudioFirstStrategy)
- 流程要点:
- 使用 FFmpeg 提取音频(单声道、16kHz、PCM 编码)
- 调用 Whisper API,使用 verbose_json 与 segment 级时间戳
- 将 Whisper 段落映射为 VideoSegment
- 简单启发式识别关键时刻(如首段作为 quote)
- 返回 VideoAnalysisResult,包含时长、策略、段落与关键时刻
- 关键配置:
- language:语言代码(默认日语)
- model:Whisper 模型(默认 whisper-1)
- prompt:可选提示词(预留)
```mermaid
flowchart TD
Start(["开始:analyze(video_path)"]) --> Extract["提取音频<br/>extract_audio(video_path)"]
Extract --> Transcribe["Whisper 转录<br/>verbose_json + segment 时间戳"]
Transcribe --> Segments["构建 VideoSegment 列表"]
Segments --> KeyMoments["识别关键时刻启发式"]
KeyMoments --> Duration["获取视频时长<br/>get_video_duration(video_path)"]
Duration --> Cleanup["清理临时音频文件"]
Cleanup --> Result["返回 VideoAnalysisResult"]
Result --> End(["结束"])
```
图表来源
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py#L54-L187)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L49-L95)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L62-L91)
章节来源
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py#L30-L187)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L49-L164)
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L12-L91)
### FFmpeg 工具集
- extract_audio:将视频解复用为 WAV 音频,单声道、16kHz、PCM 编码,适配 Whisper 推荐采样率
- get_video_duration:使用 ffprobe 获取视频时长
- slice_video:基于流复制的快速切片(不重编码),适合生成 B-Roll 片段
- check_ffmpeg_installed:检测 FFmpeg 与 ffprobe 是否可用
```mermaid
flowchart TD
A["输入:video_path"] --> B{"是否指定 output_path?"}
B --> |否| C["生成默认输出路径同名.wav"]
B --> |是| D["使用指定输出路径"]
C --> E["执行 ffmpeg 命令<br/>提取音频单声道、16kHz、PCM"]
D --> E
E --> F{"执行成功?"}
F --> |是| G["返回音频路径"]
F --> |否| H["抛出运行时错误"]
```
图表来源
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L49-L95)
章节来源
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L13-L164)
### 数据结构与输出约定
- VideoSegment:包含起止时间、描述、转录、重要性、标签、说话人等字段,并提供 to_dict 序列化
- KeyMoment:包含时间戳、类型(quote/chart/emotion/action)、内容与上下文
- VideoAnalysisResult:包含源视频、总时长、策略、段落列表、关键时刻列表与元数据,并提供过滤方法
章节来源
- [backend/video_processor/schemas.py](file://backend/video_processor/schemas.py#L12-L91)
### 在主流程中的作用与数据输出
- main.py 的 extract_video 方法在流水线第二步被调用,当前为 mock 实现,返回包含 transcription 与 timestamps 的结构,供后续脚本生成与字幕同步使用
- 正式实现应调用 backend.video_processor.analyze_video,返回 VideoAnalysisResult,其中 segments 可映射为 script 的 narration 片段,key_moments 可用于生成字幕与 B-Roll 匹配
章节来源
- [main.py](file://main.py#L99-L114)
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L31-L60)
## 依赖关系分析
- 外部依赖:
- FFmpeg/ffprobe:用于音频提取与时长查询
- OpenAI Whisper:用于语音识别与时间戳提取
- requests:用于网络请求(如 B-Roll 下载)
- 内部模块耦合:
- strategy_audio 依赖 utils(FFmpeg)与 schemas(数据结构)
- __init__.py 作为统一入口,按策略导入具体实现
- tests 提供独立 CLI 与单元测试,验证依赖安装与策略执行
```mermaid
graph TB
subgraph "外部依赖"
FF["FFmpeg/ffprobe"]
WH["OpenAI Whisper"]
REQ["requests"]
end
subgraph "Python 模块"
U["utils.py"]
SC["schemas.py"]
SA["strategy_audio.py"]
SD["strategy_direct.py"]
INI["__init__.py"]
end
SA --> U
SA --> SC
SA --> WH
INI --> SA
INI --> SD
REQ -.-> SD
```
图表来源
- [requirements.txt](file://requirements.txt#L1-L34)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L49-L164)
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py#L30-L187)
- [backend/video_processor/__init__.py](file://backend/video_processor/__init__.py#L31-L60)
章节来源
- [requirements.txt](file://requirements.txt#L1-L34)
- [tests/test_video_cli.py](file://tests/test_video_cli.py#L1-L161)
## 性能考量
- 音频采样率与编码:Whisper 推荐 16kHz 单声道 PCM,有助于降低令牌消耗与提升识别精度
- 流复制切片:slice_video 使用流复制避免重编码,显著减少 CPU 开销
- 分段策略:对于长视频,可考虑按 Whisper 段落或主题变化进行切片,便于并行处理与缓存
- API 调用成本:音频优先策略相比直接视频分析更经济,适合对话密集型视频
## 故障排查指南
- API 密钥问题
- OPENAI_API_KEY 未设置:AudioFirstStrategy 初始化会抛出异常
- GEMINI_API_KEY 未设置:PDFExtractor 初始化会抛出异常
- 依赖缺失
- FFmpeg/ffprobe 未安装:check_ffmpeg_installed 返回 False,需先安装
- OpenAI 库未安装:测试 CLI 会提示安装
- 视频处理失败
- FFmpeg 执行失败:extract_audio/slice_video 会抛出运行时错误,检查输入路径与权限
- Whisper 请求失败:检查网络与 API 配额
章节来源
- [backend/video_processor/strategy_audio.py](file://backend/video_processor/strategy_audio.py#L48-L53)
- [backend/extractor.py](file://backend/extractor.py#L18-L22)
- [tests/test_video_cli.py](file://tests/test_video_cli.py#L70-L91)
- [backend/video_processor/utils.py](file://backend/video_processor/utils.py#L148-L164)
## 结论
视频数据提取功能以“音频优先策略”为核心,通过 FFmpeg 提取高质量音频并交由 Whisper 生成精确的时间戳转录,随后将结果标准化为 VideoAnalysisResult,为脚本生成与字幕同步提供可靠数据基础。尽管当前 main.py 中的 extract_video 仍为 mock,但 backend.video_processor 已具备完整的实现骨架,可无缝接入真实流水线。
## 附录
### 新手处理流程图(概念示意)
```mermaid
flowchart TD
A["输入:面试视频"] --> B["提取音频FFmpeg"]
B --> C["Whisper 转录含时间戳"]
C --> D["文本段落化VideoSegment"]
D --> E["关键信息提取KeyMoment"]
E --> F["生成 VideoAnalysisResult"]
F --> G["写入 render_props.json供前端渲染"]
```
### 高级实践建议
- 音频预处理
- 降噪与静音裁剪:在 extract_audio 之后增加降噪滤波,提升 Whisper 精度
- 多语言支持:根据视频语言动态切换 Whisper language 参数
- 关键词提取
- 基于主题词典与 TF-IDF 对 Whisper 段落进行关键词抽取,增强 timestamps 的可检索性
- 片段分割
- 依据 Whisper 段落边界与情感变化进行切片,便于并行处理与缓存
- B-Roll 匹配
- 将 KeyMoment 的内容与类型(quote/chart/emotion)映射到 Pexels 关键词,自动抓取匹配素材
### 可运行示例(路径指引)
- 独立测试视频分析
- 使用测试 CLI:python tests/test_video_cli.py --input sample.mp4 --strategy audio --language ja
- 输出:控制台打印或保存为 JSON 文件
- 单元测试验证
- pytest tests/test_video_processor.py -v
- 依赖检查
- python tests/test_video_cli.py --check-deps
章节来源
- [tests/test_video_cli.py](file://tests/test_video_cli.py#L1-L161)
- [tests/test_video_processor.py](file://tests/test_video_processor.py#L1-L143)