视频素材理解管线
从视频上传到 AI 理解的完整管线:FFmpeg 场景检测 + 补帧 + pHash 去重 + 视觉 AI 分析 + Dify 集成。
[!info] related notes
- 核心概念: 视频关键帧提取, pHash 图片去重, FFmpeg 镜头检测, 视觉语言模型 VLM
- 相关工具: FFmpeg, Cloudflare, Cloudflare Workers AI Vision, Wrangler, Dify
- 相关项目: Dify video-craft-agent Workflow, AI 功能模块设计
- 所属 MOC: AI MOC
视频素材理解管线
范围
这篇笔记把视频素材理解涉及的多个技术点串成一条完整管线:从用户上传视频,到 AI 输出结构化的素材理解 JSON,再到 Dify 生成脚本。
为什么要放在一起理解
视频素材理解不是单一技术问题,而是一个多层管线:
- 抽帧用 FFmpeg
- 去重用 pHash
- 理解用视觉 AI
- 编排用 Dify
单独理解任何一个环节都不够,需要看到完整的数据流和每层的职责边界。
管线架构
用户上传 video.mp4
↓
FFmpeg 获取元数据(时长、fps、分辨率)
↓
每秒抽 1 张候选帧(低分辨率)
↓
FFmpeg scene detection 补充镜头切换帧
↓
pHash 去重,保留变化明显的帧
↓
限制最多 N 张关键帧
↓
压缩到 512px / 768px
↓
发给 Cloudflare Workers AI Vision 分析
↓
得到每张图的 JSON 分析结果
↓
聚合成 video_material_json
↓
传给 Dify Workflow 生成脚本
每层的职责
第 1 层:本地元数据提取
工具:ffprobe
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
获取:时长、帧率、分辨率、编码格式。
这一步不消耗 AI 资源。
第 2 层:候选帧采样
工具:ffmpeg
# 每秒抽 1 帧
ffmpeg -i input.mp4 -vf "fps=1" -q:v 5 frames/candidate_%03d.jpg
30 秒视频得到 30 张候选帧。-q:v 5 控制质量,文件更小便于后续处理。
第 3 层:镜头切换补充
用 select='gt(scene,0.3)' 检测画面变化明显的位置,补充候选帧。这一步捕获每秒抽帧可能漏掉的快速切换。
第 4 层:去重
工具:pHash
对所有候选帧做 dHash 比较,去掉视觉上太相似的帧。阈值建议 8。
第 5 层:数量限制
视频 ≤ 15 秒:最多 4 张
15~30 秒:最多 6 张
30~60 秒:最多 8 张
> 60 秒:最多 10~12 张
如果候选帧不足,按固定时间点(0%、25%、50%、75%、90%)补充。
第 6 层:压缩
将关键帧缩放到 512px 或 768px 宽,降低传输成本和 AI 处理时间。
第 7 层:视觉 AI 分析
工具:Cloudflare Workers AI Vision
通过 Cloudflare Worker 调用 @cf/meta/llama-3.2-11b-vision-instruct 模型。图片转 base64 后 POST 给 Worker 的 /analyze-frame 端点:
import base64, requests
WORKER_URL = "https://video-frame-analyzer.xxxx.workers.dev/analyze-frame"
def analyze_frame(image_path):
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode("utf-8")
resp = requests.post(WORKER_URL, json={"image": b64})
return resp.json()
每张关键帧返回结构化 JSON:
{
"description_cn": "一只手正在打开产品包装盒",
"shot_type": "unboxing",
"main_subject": "产品包装盒",
"objects": ["hands", "product_box", "desk"],
"has_person": false,
"has_product": true,
"quality": "clear",
"marketing_role": "hook",
"tags": ["开箱", "包装", "桌面"]
}
免费额度:每天 10,000 Neurons。30 秒视频抽 5~8 帧,每帧消耗约几百 Neurons,单个视频分析在免费范围内。
第 8 层:聚合
将所有关键帧的分析结果合并成视频级别的素材理解:
{
"duration": 30,
"fps": 30,
"analyzed_keyframes": 6,
"summary": "视频包含开箱、产品特写和使用演示",
"shots": [
{
"timestamp": 0,
"type": "unboxing",
"best_for": "hook"
},
{
"timestamp": 6,
"type": "product_closeup",
"best_for": "product_intro"
},
{
"timestamp": 14,
"type": "usage_demo",
"best_for": "feature_demo"
}
]
}
第 9 层:Dify 集成
将聚合后的 JSON 传给 Dify video-craft-agent Workflow,生成分镜脚本。
分层职责表
| 层级 | 工具 | 作用 | 是否消耗 AI |
|---|---|---|---|
| 元数据 | ffprobe | 获取时长/fps/分辨率 | 否 |
| 采样 | ffmpeg | 每秒抽候选帧 | 否 |
| 镜头检测 | ffmpeg scene | 找画面变化点 | 否 |
| 去重 | pHash | 去掉相似帧 | 否 |
| 理解 | Vision AI | 看懂画面内容 | 是 |
| 编排 | Dify | 生成脚本 | 是 |
前 4 层都是本地计算,不消耗 AI API。只有最后 2 层需要调用外部服务。
MVP 路线
V1:最简方案
固定抽 5 帧 → 发给 Vision AI → 汇总给 Dify
V2:加场景检测
FFmpeg scene detection + 固定补帧 → Vision AI → Dify
V3:完整管线
FFmpeg scene detection + pHash 去重 + 数量限制 → Vision AI → Dify
建议从 V1 开始,验证管线跑通后再逐步升级。
成本估算
以 30 秒视频为例:
| 方案 | AI 请求数 | 评价 |
|---|---|---|
| 逐帧分析 | 900 次 | 完全不现实 |
| 每秒抽帧 | 30 次 | 仍然偏贵 |
| 固定 5 帧 | 5 次 | 最简单 |
| 场景检测 + 去重 | 5~8 次 | 推荐 |
边界与易混淆点
- 这不是视频编辑管线:目标是理解视频有什么素材,不是生成最终视频
- Vision AI 不能替代视频时序分析:关键帧理解丢失了时间连续性,不能理解动作过程
- Dify 不直接调 FFmpeg:视频处理在本地后端完成,Dify 只负责脚本生成
- Cloudflare Workers AI 有免费额度限制:需要控制关键帧数量避免超限