358 lines
16 KiB
Markdown
358 lines
16 KiB
Markdown
# 视频数据提取
|
||
|
||
<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) |