视频关键帧提取
从视频中提取少量代表性帧(关键帧)用于 AI 理解,避免逐帧分析的浪费。
#type / concept
#status / growing
#tech / ai
#media / video
[!info] related notes
- 相关概念: pHash 图片去重, FFmpeg 镜头检测
- 应用场景: 视频素材理解管线
- 相关资源: FFmpeg, Cloudflare
- 所属 MOC: AI MOC
视频关键帧提取
一句话定义
视频关键帧提取是从连续视频帧中选出少量有代表性的画面,用最小的分析成本覆盖视频的主要内容变化。
为什么要提取关键帧
一个 30 秒短视频,按常见帧率计算:
| 帧率 | 30 秒总帧数 |
|---|---|
| 24 fps | 720 帧 |
| 25 fps | 750 帧 |
| 30 fps | 900 帧 |
| 60 fps | 1800 帧 |
连续视频中绝大多数帧是重复或近似重复的——手的位置轻微变化、产品角度轻微变化、背景完全一样。逐帧发给视觉模型分析既浪费 API 调用,又得不到更多有用信息。
关键帧提取的目标:用 5~8 张图覆盖一个 30 秒视频的全部营销信息。
帧率与抽帧的关系
逐帧分析:900 次 AI 调用(完全不现实)
每秒抽 1 帧:30 次(仍然偏贵)
每 3 秒抽 1 帧:10 次(可用但可能重复)
固定 5 帧:5 次(最简单)
每秒抽帧 + 去重:5~8 次(推荐)
镜头切分 + 关键帧:3~8 次(更专业)
关键帧选择策略
策略一:固定时间点抽帧
最简单的 MVP 方案。30 秒视频抽 0s、6s、12s、18s、24s、29s 共 6 张。
- 优点:实现简单、速度快、成本低
- 缺点:可能错过中间突然出现的重要画面
策略二:每秒抽帧 + 图片相似度去重
每秒抽 1 张候选图(30 秒得 30 张),用本地算法(如 pHash)判断相似度,只保留变化明显的 5~10 张。
策略三:FFmpeg 镜头检测 + 补帧
用 FFmpeg scene detection 找镜头切换点,再按固定时间点补帧兜底。
混合策略(推荐)
1. FFmpeg scene detection 抽镜头切换帧
2. 如果少于 4 张,按 0%、25%、50%、75%、90% 补帧
3. 用 pHash 去重
4. 最多保留 6~8 张关键帧
推荐关键帧数量
| 视频时长 | 最多分析帧数 |
|---|---|
| ≤ 15 秒 | 4 张 |
| 15~30 秒 | 6 张 |
| 30~60 秒 | 8 张 |
| > 60 秒 | 10~12 张 |
为什么少量关键帧就够了
营销素材理解不需要电影级剧情分析。需要知道的是:
- 有没有产品?有没有人?
- 有没有开箱、使用演示、包装、logo、效果展示?
- 哪些画面适合开场 hook?哪些适合做功能展示?
这些信息通常几个关键帧就能覆盖。比如 30 秒产品视频:
0-5s:产品包装 → 取 1 帧
5-12s:产品特写 → 取 1 帧
12-22s:使用演示 → 取 1 帧
22-30s:效果展示 → 取 1 帧
最小算法伪代码
def select_keyframes(candidate_frames, max_frames=8):
keyframes = []
last_hash = None
for frame in candidate_frames:
current_hash = phash(frame)
if last_hash is None:
keyframes.append(frame)
last_hash = current_hash
continue
distance = hamming_distance(current_hash, last_hash)
if distance > 8: # 画面变化明显
keyframes.append(frame)
last_hash = current_hash
if len(keyframes) >= max_frames:
break
return keyframes
distance 阈值参考:5 更敏感(保留更多帧)、10 更严格、15 只保留明显镜头切换。
边界与易混淆点
- 关键帧 ≠ 缩略图:缩略图通常只取 1 张代表封面,关键帧取多张覆盖内容变化。
- 关键帧 ≠ I 帧:视频编码中的 I 帧(关键帧)是压缩概念,和素材理解的关键帧含义不同。
- 抽帧 ≠ 场景切分:抽帧是选出画面,场景切分是判断镜头边界。两者可以组合使用。