# B-Roll素材获取
**本文引用的文件**
- [backend/media_fetcher.py](file://backend/media_fetcher.py)
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json)
- [main.py](file://main.py)
- [PROJECT_README.md](file://PROJECT_README.md)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts)
- [requirements.txt](file://requirements.txt)
- [backend/extractor.py](file://backend/extractor.py)
- [backend/scripter.py](file://backend/scripter.py)
- [.gitignore](file://.gitignore)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本技术文档聚焦于B-Roll素材自动获取功能,围绕 backend/media_fetcher.py 展开,说明其如何通过 Pexels API 根据脚本内容智能检索匹配的背景视频片段。文档涵盖:
- 关键词提取与翻译:从日语解说脚本中识别关键主题(如“家庭”“退休”“教育”),并映射为英文搜索词。
- 视频筛选标准:分辨率、时长、版权许可等要求及下载管理机制。
- 代码示例路径:API请求构造、响应处理与本地缓存策略。
- broll_fetch_results.json 结构说明及其在后续渲染阶段的引用方式。
- 故障排查:API密钥失效、网络超时、素材质量不佳等问题的应对。
- 扩展方案:替换其他素材源(如Pixabay、Coverr等)的思路。
## 项目结构
该仓库采用“Python后端 + Node.js/Remotion 前端”的混合架构。与B-Roll素材获取直接相关的目录与文件如下:
- backend/media_fetcher.py:B-Roll素材抓取器,负责调用Pexels API、关键词翻译、下载与缓存。
- assets/1_processed/broll_fetch_results.json:已抓取素材的结果索引,供渲染阶段引用。
- main.py:主流程编排,串联PDF提取、脚本生成、B-Roll抓取、图表数据构建、渲染属性生成与渲染。
- frontend/src/render-props-types.ts:渲染属性的数据契约,定义了assets.broll的结构。
- requirements.txt:Python依赖清单,包含requests等网络与媒体处理相关库。
- backend/extractor.py、backend/scripter.py:分别负责PDF与视频提取、脚本生成(当前为占位实现,未来用于提供关键词)。
- .gitignore:忽略输出视频与环境变量文件,保留JSON元数据。
```mermaid
graph TB
A["main.py
主流程编排"] --> B["backend/media_fetcher.py
B-Roll抓取器"]
A --> C["assets/1_processed/broll_fetch_results.json
抓取结果索引"]
A --> D["frontend/src/render-props-types.ts
渲染属性契约"]
B --> E["Pexels API"]
B --> F["本地缓存目录
assets/1_processed/broll/"]
```
图示来源
- [main.py](file://main.py#L136-L144)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L1-L72)
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
章节来源
- [PROJECT_README.md](file://PROJECT_README.md#L132-L141)
- [.gitignore](file://.gitignore#L36-L58)
## 核心组件
- MediaFetcher 类:封装Pexels API交互、关键词翻译、视频下载与缓存逻辑。
- fetch_broll 函数:便捷入口,从脚本中抽取关键词并触发抓取。
- broll_fetch_results.json:记录每个关键词对应的英文名与本地视频列表,包含时长与摄影师信息。
- 渲染属性契约:定义 assets.broll 的键值映射,供前端渲染使用。
章节来源
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L15-L72)
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
## 架构总览
下图展示了B-Roll抓取在整体流水线中的位置与数据流。
```mermaid
sequenceDiagram
participant CLI as "命令行入口
main.py"
participant Gen as "脚本生成器
backend/scripter.py"
participant MF as "B-Roll抓取器
backend/media_fetcher.py"
participant PEX as "Pexels API"
participant FS as "本地存储
assets/1_processed/broll/"
participant RP as "渲染属性
render_props.json"
participant FE as "前端渲染
Remotion"
CLI->>Gen : 生成日语脚本
CLI->>MF : 提供脚本并请求B-Roll
MF->>MF : 抽取关键词并翻译为英文
MF->>PEX : 发送搜索请求
PEX-->>MF : 返回视频资源列表
MF->>FS : 下载并保存视频
MF-->>CLI : 返回本地路径映射
CLI->>RP : 写入render_props.json
FE-->>CLI : 使用render_props.json进行渲染
```
图示来源
- [main.py](file://main.py#L136-L144)
- [backend/scripter.py](file://backend/scripter.py#L1-L69)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L25-L72)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
## 详细组件分析
### MediaFetcher 类设计与职责
- 负责初始化与校验PEXELS_API_KEY,设置基础URL。
- 提供 fetch_broll(keywords, max_per_keyword) 接口,返回关键词到视频URL的映射。
- 提供 _translate_keyword(japanese_keyword) 占位方法,未来接入Gemini进行日英翻译并缓存。
- 提供 _download_video(url, output_path) 占位方法,未来实现下载、进度条、格式校验与缓存。
```mermaid
classDiagram
class MediaFetcher {
+api_key : string
+base_url : string
+__init__(api_key)
+fetch_broll(keywords, max_per_keyword) Dict
+_translate_keyword(japanese_keyword) string
+_download_video(url, output_path) string
}
```
图示来源
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L15-L72)
章节来源
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L15-L72)
### 关键词提取与翻译策略
- 输入:来自脚本生成器的脚本对象,包含分段文本。
- 提取:遍历脚本的分段,从每段文本中抽取关键词(占位实现,未来可结合NLP或LLM)。
- 翻译:将日文关键词翻译为英文(占位实现,建议使用Gemini Pro),并缓存翻译结果以减少重复调用。
- 映射:将英文关键词作为Pexels搜索词,限制每关键词最多返回若干个视频。
```mermaid
flowchart TD
Start(["开始"]) --> LoadScript["加载脚本对象"]
LoadScript --> Iterate["遍历脚本分段"]
Iterate --> Extract["抽取关键词占位"]
Extract --> Translate["翻译为英文Gemini并缓存"]
Translate --> Search["调用Pexels搜索接口"]
Search --> Filter["按分辨率/时长/许可筛选"]
Filter --> Download["下载到本地缓存目录"]
Download --> Index["写入broll_fetch_results.json"]
Index --> End(["结束"])
```
图示来源
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L25-L72)
- [backend/scripter.py](file://backend/scripter.py#L22-L48)
章节来源
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L25-L72)
- [backend/scripter.py](file://backend/scripter.py#L22-L48)
### 视频筛选标准与下载管理
- 分辨率与时长:建议在搜索后对返回结果按分辨率与目标时长范围进行过滤,优先选择高分辨率且时长接近目标的素材。
- 版权许可:Pexels默认许可适合商用,但应确保符合项目用途;必要时可在筛选中排除非CC0或非商业许可的素材。
- 下载与缓存:
- 将视频下载至 assets/1_processed/broll/ 目录,命名规则建议包含关键词与唯一标识,便于去重与复用。
- 在 broll_fetch_results.json 中记录每个关键词的英文名、本地文件路径、时长与摄影师信息,便于渲染阶段引用。
- 使用缓存避免重复下载同一素材,可基于哈希或URL指纹判断是否已存在。
```mermaid
flowchart TD
A["Pexels搜索结果"] --> B["按分辨率筛选"]
B --> C["按时长范围筛选"]
C --> D["按许可筛选"]
D --> E["下载到本地缓存"]
E --> F["更新broll_fetch_results.json"]
F --> G["返回本地路径映射"]
```
图示来源
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- [.gitignore](file://.gitignore#L36-L58)
章节来源
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- [.gitignore](file://.gitignore#L36-L58)
### API请求构造与响应处理
- 请求构造:使用 requests 库发送HTTP GET请求到 Pexels 搜索接口,携带认证头与查询参数(关键词、数量上限等)。
- 响应处理:解析JSON,提取视频URL、时长、分辨率、许可等字段;对不符合条件的条目进行过滤。
- 错误处理:捕获网络异常、超时、HTTP状态码错误;对空结果或失败重试进行降级处理。
章节来源
- [requirements.txt](file://requirements.txt#L16-L18)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L25-L72)
### broll_fetch_results.json 结构与渲染引用
- 结构要点:
- 键为日文关键词(如“家族”“老後”“教育”)。
- 字段 english:英文关键词。
- 字段 videos:数组,包含多个视频条目,每项含 filepath、duration、photographer。
- 渲染引用:
- 渲染属性 assets.broll 期望为“关键词 -> 路径”的映射;当前broll_fetch_results.json以关键词为根节点,渲染阶段需将其转换为 assets.broll 的扁平映射,或将渲染阶段直接读取该JSON并按需转换。
- 前端契约中 assets.broll 为 Record,即“关键词 -> 视频路径”。
```mermaid
erDiagram
KEYWORDS {
string 日文关键词 PK
string 英文关键词
}
VIDEOS {
string filepath
number duration
string photographer
}
KEYWORDS ||--o{ VIDEOS : "包含"
```
图示来源
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
章节来源
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
### 代码示例路径(不展示具体代码)
- 初始化与校验API密钥与基础URL
- 参考路径:[backend/media_fetcher.py](file://backend/media_fetcher.py#L18-L24)
- fetch_broll 接口与占位实现
- 参考路径:[backend/media_fetcher.py](file://backend/media_fetcher.py#L25-L43)
- _translate_keyword 占位方法
- 参考路径:[backend/media_fetcher.py](file://backend/media_fetcher.py#L44-L51)
- _download_video 占位方法
- 参考路径:[backend/media_fetcher.py](file://backend/media_fetcher.py#L52-L60)
- 主流程中调用 fetch_broll
- 参考路径:[main.py](file://main.py#L136-L144)
- 渲染属性契约中 assets.broll 的定义
- 参考路径:[frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
## 依赖关系分析
- 外部依赖:
- requests:用于HTTP请求与下载。
- ffmpeg-python:用于视频处理(当前媒体抓取模块为占位,未来可能在此集成)。
- 内部依赖:
- main.py 编排调用 media_fetcher.fetch_broll。
- frontend/src/render-props-types.ts 定义渲染阶段消费的数据结构。
- .gitignore 控制资产目录的版本控制行为,避免大文件入库。
```mermaid
graph LR
REQ["requests"] --> MF["backend/media_fetcher.py"]
FFPY["ffmpeg-python"] --> MF
MF --> MAIN["main.py"]
MF --> TYPES["frontend/src/render-props-types.ts"]
GIT[".gitignore"] --> MF
```
图示来源
- [requirements.txt](file://requirements.txt#L16-L18)
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L1-L72)
- [main.py](file://main.py#L136-L144)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
- [.gitignore](file://.gitignore#L36-L58)
章节来源
- [requirements.txt](file://requirements.txt#L16-L18)
- [main.py](file://main.py#L136-L144)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
- [.gitignore](file://.gitignore#L36-L58)
## 性能考量
- 并发与限速:Pexels搜索接口可能有限额,建议对关键词并发请求进行节流,避免触发速率限制。
- 缓存策略:对翻译结果与下载的视频建立本地缓存,命中则跳过网络请求,显著降低延迟与成本。
- 过滤前置:在下载前完成分辨率与时长过滤,减少无效IO。
- 断点续传:对于大文件下载,可考虑断点续传以提升稳定性。
## 故障排查指南
- API密钥失效
- 现象:初始化时报错或请求返回未授权。
- 处理:检查 .env 文件是否正确配置PEXELS_API_KEY;确认密钥有效且有访问权限。
- 参考路径:[backend/media_fetcher.py](file://backend/media_fetcher.py#L18-L24)
- 网络超时或连接失败
- 现象:请求抛出超时或连接异常。
- 处理:增加重试次数与指数退避;检查代理与防火墙;在网络稳定后再试。
- 素材质量不佳
- 现象:分辨率过低、时长不符、许可不满足需求。
- 处理:在筛选阶段严格限定分辨率与时长;优先选择高评分与合适许可的素材;必要时回退到备用关键词。
- 渲染阶段找不到B-Roll路径
- 现象:渲染报错提示缺少assets.broll映射。
- 处理:确认 broll_fetch_results.json 已生成且路径正确;若渲染阶段使用扁平映射,请在生成 render_props.json 时将该JSON转换为 assets.broll 的键值对。
- 参考路径:[assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- 参考路径:[frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
章节来源
- [backend/media_fetcher.py](file://backend/media_fetcher.py#L18-L24)
- [assets/1_processed/broll_fetch_results.json](file://assets/1_processed/broll_fetch_results.json#L1-L77)
- [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts#L107-L112)
## 结论
当前 B-Roll 素材获取功能处于占位实现阶段,核心流程已在 main.py 中串联,MediaFetcher 类已预留Pexels API集成、翻译与下载的扩展点。通过明确的筛选标准与本地缓存策略,可有效提升素材质量与系统性能。broll_fetch_results.json 作为中间产物,为渲染阶段提供了稳定的素材索引;未来建议在渲染阶段直接消费该JSON或转换为扁平映射,以契合前端契约。
## 附录
- 扩展方案:替换其他素材源
- Pixabay:提供免费与付费素材,支持相似的搜索与过滤能力;需适配其API与许可条款。
- Coverr:专注免费短视频,适合短时长B-Roll;注意其许可与可用性。
- 自建素材库:将已有素材归档到 assets/1_processed/broll/,并在 broll_fetch_results.json 中维护索引,便于统一管理与渲染引用。
- 开发建议
- 在 media_fetcher.py 中逐步实现 _translate_keyword 与 _download_video。
- 在 main.py 中启用实际的 backend.extractor 与 backend.scripter,以提供真实脚本与关键词。
- 在渲染阶段完善对 broll_fetch_results.json 的转换逻辑,确保 assets.broll 符合前端契约。