视频抽帧这件事,说起来很简单,就是把视频里的一帧帧画面提取成图片,但真正做起来,坑比想象中多。我早期做目标检测数据集时,面对几十个小时的监控视频,直接按帧全部导出,结果半小时后磁盘爆了,训练集里还全是模糊帧和重复帧,模型效果惨不忍睹。后来慢慢把FFmpeg、OpenCV、场景切分这些方法都摸了一遍,才算把抽帧这件事真正玩明白。
这篇笔记整理的,就是我从纯小白到能应对各种抽帧需求的完整方法合集。不管你是做深度学习数据集、做视频封面、做内容审核,还是单纯想把某个精彩瞬间保存下来,这里面都有可以直接抄的方案。
1. 视频抽帧到底在解决什么问题
1.1 什么是视频抽帧,常见业务场景
视频本质上是连续播放的静态图片序列,常见的帧率有24fps、25fps、30fps、60fps等。以30fps为例,一秒视频就有30张完整画面,十分钟的短视频就有18000张。如果全部导出,不仅占空间,处理起来也是灾难。视频抽帧的核心,就是按照某种规则从这一大堆画面中,挑选出真正有价值的少量画面。
我接触过的高频场景大概有这几类:
- 深度学习数据集制作:目标检测、图像分类、动作识别等任务,需要大量的标注图片。从视频中抽帧是获取训练数据最经济高效的方式之一。比如训练一个安全帽检测模型,你只需要从工地监控视频里每隔几秒抽一帧,然后标注,就能快速攒出几千张图片。
- 视频封面和缩略图:视频平台需要好看的封面,直接从视频中间截取一帧,或者抽取多个候选帧再人工挑选,比专门设计封面省事得多。
- 内容审核和视频检索:审核人员不可能一秒一秒看视频,抽帧后按图片审核效率高得多。视频相似度检索、指纹提取,也大量依赖关键帧。
- OCR和文本识别:扫描版视频、PPT录屏、字幕提取,都需要先把视频画面转成图片再跑OCR。
- 摄影和剪辑辅助:从连拍视频中选出一张最清晰的瞬间,或者用抽帧做延时摄影效果。
可以说,只要视频和图像处理沾边,抽帧就是绕不开的前置步骤。而不同场景对抽帧的要求完全不同,有的要均匀,有的要清晰,有的要智能识别关键内容,盲目用一种方法走天下,后面肯定要返工。
1.2 抽帧方案选型的底层逻辑
很多人上来就问"用什么工具抽帧",但我的建议是,先想清楚四件事:抽出来的图给谁用、需要多均匀、允许多少重复、对清晰度有没有要求。
- 给谁用:如果人看,比如做封面,那抽出来的帧要好看有意义;如果给模型训练,那均匀性和多样性更重要;如果给OCR,那清晰度第一,模糊帧必须过滤。
- 均匀性:按固定时间间隔抽,能保证时间上的均匀分布,比如每2秒一帧;按固定帧数抽,适合帧率稳定的视频;按关键帧(I帧)抽,抽出来的是编码器认为的关键画面,但时间间隔不均匀。
- 重复性:如果视频场景变化小,比如会议室监控,均匀抽帧可能抽到大量几乎一模一样的画面,白白浪费存储。这时应该用场景切换检测,只在画面变化大时抽帧。
- 清晰度:镜头抖动、人物快速运动都可能造成模糊帧。运动模糊严重的帧,人眼可能勉强能看,但喂给模型就是毒药。抽帧后加一个清晰度筛选步骤,能省下后面不少清洗数据的功夫。
拿我做数据集的亲身体验来说,当时图省事,用一个最简单的命令把监控视频按1秒抽一帧,结果抽出来5000张图,有3000张画面几乎没变化,训练出来的模型检测精度低了整整好几个点。后面改用"时间均匀抽帧+Laplacian方差筛选"的组合,数据量少了三分之一,模型精度反而上去了。所以选型这件事,真不能马虎。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 三类主流抽帧方式对比
2.1 FFmpeg命令行抽帧:最普适的主力工具
FFmpeg几乎是所有音视频处理任务的首选,抽帧也只是它的基础功能之一。它的优势在于:
- 全平台支持,Windows、Linux、macOS都能跑;
- 性能极高,底层是C语言优化过的解码和滤镜链;
- 支持几乎所有的视频编码格式;
- 抽帧的同时还能做缩放、裁剪、质量压缩等操作,一步到位。
FFmpeg的抽帧思路主要分四种:
第一种是按时间间隔抽帧,用 fps 过滤器。fps=1 表示每秒输出1帧,fps=1/5 表示每5秒输出1帧,fps=2 表示每秒输出2帧。这个过滤器会丢弃不符合时间点的帧,同时保留符合时间的画面,输出稳定。
命令示例:
bash复制# 每1秒抽1帧
ffmpeg -i input.mp4 -vf fps=1 output_%04d.jpg
# 每5秒抽1帧
ffmpeg -i input.mp4 -vf fps=1/5 output_%04d.jpg
# 每秒抽2帧
ffmpeg -i input.mp4 -vf fps=2 output_%04d.jpg
第二种是按帧号间隔抽帧,用 select 过滤器和 mod 函数。select='not(mod(n,30))' 表示每30帧抽1帧,n是帧序号,从0开始。这种方式的优势是精确,不受时间精度影响,但有一个前提——你得知道视频的帧率,才能算清楚30帧到底对应多少秒。
bash复制# 每30帧抽1帧,假设视频30fps,即每1秒抽1帧
ffmpeg -i input.mp4 -vf "select='not(mod(n,30))'" -vsync vfr output_%04d.jpg
第三种是抽关键帧(I帧)。视频编码时为了压缩,会周期性地插入完整编码的I帧,直接解码I帧就能得到完整画面,不需要参考其他帧。用 eq(pict_type,I) 可以把所有I帧抽出来。
bash复制# 抽出全部I帧
ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -vsync vfr i_frames_%03d.jpg
I帧的抽取速度和压缩率都很高,但时间分布不均匀,适合做视频粗索引、快速预览,不适合做时间均匀的数据集。
第四种是按场景切换抽帧,也是用 select,但凭借的是 scene 评分。FFmpeg会对相邻帧做画面差异分析,计算一个0到1之间的场景变化值,gt(scene,0.3) 表示当画面变化超过0.3时输出这一帧。
bash复制# 场景变化阈值0.3
ffmpeg -i input.mp4 -vf "select='gt(scene,0.3)',showinfo" -vsync vfr scene_%03d.jpg
这个方法最适合从长时间监控、录屏中抽取有内容差异的关键画面。阈值的调校我后面会细说,太高会漏帧,太低会产生大量相似帧。
2.2 OpenCV逐帧处理:适合二次开发和精细控制
FFmpeg虽强,但当你需要结合业务逻辑做判断时,比如"抽出的帧中包含人脸才保存""画面太暗跳过"等,FFmpeg的滤镜写起来就非常痛苦。这时候OpenCV就派上用场了。
OpenCV用 VideoCapture 读取视频流,通过 read() 一帧一帧地读,然后用Python代码自由控制保存逻辑。它的核心优势是灵活,所有判断都可以自己写。缺点是纯Python逐帧读取速度较慢,需要手动管理内存和文件I/O。
一个基本的OpenCV抽帧骨架:
python复制import cv2
import os
video_path = "input.mp4"
out_dir = "frames"
os.makedirs(out_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS) # 视频帧率
frame_count = 0
saved_count = 0
# 每2秒保存一帧
interval = int(round(fps * 2))
while True:
ret, frame = cap.read()
if not ret:
break
if frame_count % interval == 0:
out_path = os.path.join(out_dir, f"{saved_count:06d}.jpg")
cv2.imwrite(out_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 95])
saved_count += 1
frame_count += 1
cap.release()
print(f"处理完成,共读取{frame_count}帧,保存{saved_count}张图片")
这段代码的逻辑很简单:读视频、算间隔、按帧号取模保存。实际项目中,我会在这个框架上叠加时间戳判断、清晰度过滤、内容判断等逻辑。
2.3 按场景/关键帧智能抽帧:面向内容理解的高级玩法
如果说FFmpeg的scene过滤器是"初阶版"场景抽帧,那基于深度学习的内容理解抽帧,就是"进阶版"的玩法。这个思路适用于对画面内容有更高要求的场景,比如:
- 从一段对话视频中抽帧,需要确保画面里始终有人脸且人脸清晰;
- 从教学录屏中抽帧,需要保留每个PPT页面变化的瞬间;
- 从运动视频中抽帧,需要避开剧烈运动导致的运动模糊。
实现方式通常是把OpenCV抽出的候选帧,送进一个轻量级分类器或检测器(比如YOLO、RetinaFace),只保留满足条件的帧。虽然速度会慢不少,但输出的帧质量极高,几乎不需要二次清洗。
我做过一个课堂录播的视频切片项目,录屏里面内容切换频繁,但FFmpeg的scene阈值很难调到完美。最后我采用"每0.5秒抽一帧 → 用感知哈希计算帧间相似度 → 只保存相似度低于阈值的帧"的方案,效果立竿见影,视频去重率从不到50%提升到了90%以上。这里的感知哈希可以理解为给每张图算一个唯一的"指纹",指纹差异越大,画面变化就越大,这个方法比像素级的scene计算更稳定。
3. 实操演示:FFmpeg与OpenCV的完整抽帧流程
3.1 FFmpeg按时间间隔抽帧的完整命令与参数说明
先看一个最常用的完整示例,把一段视频每3秒抽一帧,保存成高质量JPEG,并且把分辨率控制到1280宽度:
bash复制ffmpeg -i input.mp4 -vf "fps=1/3,scale=1280:-1" -q:v 2 frames_%04d.jpg
这里有几个参数值得展开讲:
fps=1/3:每3秒输出一帧。注意fps表示输出帧率,1/3这个分数值非常直观,就是每3秒一个画面。如果你要每0.5秒抽一帧,就是fps=2;每10秒一帧,就是fps=1/10。scale=1280:-1:把画面宽度缩放到1280,高度按比例自动计算。做数据集时,分辨率不一定要原图全尺寸,统一缩放到一个适中的尺寸,能显著减少存储和后续处理时间。但要注意,如果业务要保留所有细节,比如OCR识别小字,就不要缩放。-q:v 2:JPEG质量参数,取值范围一般是2到31,数值越小质量越高。2到5是高质量区间,肉眼几乎看不出压缩痕迹。默认值是2,我建议数据集用2,日常缩略图用5就行。%04d.jpg:输出文件名按4位数字补零递增,输出为frames_0001.jpg、frames_0002.jpg……如果想从1开始而不从0开始,可以在输出前加-start_number 1。
如果只需要抽取视频中间某段时间内的帧,可以用 -ss 和 -t 限定范围:
bash复制# 从第1分钟开始,抽取10秒,每1秒一帧
ffmpeg -ss 00:01:00 -t 10 -i input.mp4 -vf "fps=1" segments_%04d.jpg
这里有个经验:当 -ss 放在 -i 前面时,FFmpeg会先快速定位再解码,速度极快;放在 -i 后面时,会从视频开头解码到指定时间点才停,很慢。但如果要的抽帧时间戳极其精确,放在 -i 后面的方式更准。一般场景下,建议把 -ss 放在 -i 前,兼顾速度和精度。
3.2 FFmpeg按帧号间隔抽帧与场景抽帧的操作细节
按帧号间隔抽帧,核心是 select 过滤器加 mod 函数。这里有个容易踩的坑:用 select 抽了帧以后,输出帧率会变得不连续,必须在后头加上 -vsync vfr,告诉FFmpeg用可变帧率输出,否则它会用空帧把时间戳补齐,导致输出一堆空白或重复帧。
bash复制# 每30帧抽1帧
ffmpeg -i input.mp4 -vf "select='not(mod(n,30))'" -vsync vfr frames_%04d.jpg
n 就是帧序号,mod(n,30) 是帧序号对30取余,not() 取反,意思是余数为0,也就是第0帧、第30帧、第60帧……满足条件。这个逻辑很直白,你可以把30改成任意数字,比如15就是每15帧抽一帧。
按场景抽帧的命令:
bash复制ffmpeg -i input.mp4 -vf "select='gt(scene,0.3)',showinfo" -vsync vfr scene_%04d.jpg
注意这里的两个点。第一,gt(scene,0.3) 表示场景变化评分大于0.3才输出。这个阈值怎么定?我实测的经验是:0.1到0.2之间,抽帧比较敏感,适合PPT切换、字幕变化这种小变化;0.3到0.5之间,适合摄像头快速晃动、场景大幅切换的视频;超过0.6,基本只抽硬切镜头了。建议先用小范围视频试跑,看输出数量再调阈值。
第二,我加了 showinfo,这个参数会在命令行输出日志里打印每个保留帧的时间戳和帧号,方便你对比抽出的图片是否合理。每张图片对应的 pts_time 会显示在日志里,这个信息在排查问题时非常有用。
3.3 OpenCV逐帧保存与时间戳抽帧实战
OpenCV的基础抽帧代码前面已经给了,但实际项目里,我更推荐用时间戳控制抽帧,而不是帧号。原因很简单:CAP_PROP_POS_MSEC 返回的是当前帧在视频中的毫秒位置,按时间间隔抽不依赖帧率,逻辑更直观。
python复制import cv2
import os
video_path = "input.mp4"
out_dir = "frames_by_time"
os.makedirs(out_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
interval_ms = 2000 # 每2秒
next_target_ms = 0
saved_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
current_ms = cap.get(cv2.CAP_PROP_POS_MSEC)
if current_ms >= next_target_ms:
out_path = os.path.join(out_dir, f"{saved_count:06d}.jpg")
cv2.imwrite(out_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 95])
saved_count += 1
next_target_ms += interval_ms
cap.release()
print(f"已保存 {saved_count} 张图片")
这段代码唯一要注意的是 cv2.imwrite 的质量参数。JPEG质量在OpenCV里通过 [cv2.IMWRITE_JPEG_QUALITY, 95] 控制,范围0到100,95已经是很高的质量了。如果你要保存无损PNG,可以用 [cv2.IMWRITE_PNG_COMPRESSION, 3],压缩级别0到9,3是速度和体积的平衡点。
3.4 批量处理多视频的脚本框架
实际工作中,很少只抽一个视频。几十个上百个视频批量处理才是常态。这里给一个我用OpenCV封装的批量处理框架,支持遍历目录、自动创建输出目录、按时间戳抽帧、过滤模糊帧,全部包含:
python复制import cv2
import os
import glob
from pathlib import Path
def variance_of_laplacian(image):
# 拉普拉斯方差,值越大代表图像纹理越清晰,越小越模糊
return cv2.Laplacian(image, cv2.CV_64F).var()
def process_video(video_path, out_root, interval_ms=2000, blur_threshold=50.0):
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print(f"[跳过] 无法打开: {video_path}")
return 0
video_name = Path(video_path).stem
out_dir = os.path.join(out_root, video_name)
os.makedirs(out_dir, exist_ok=True)
next_target_ms = 0
saved_count = 0
total_read = 0
while True:
ret, frame = cap.read()
if not ret:
break
total_read += 1
current_ms = cap.get(cv2.CAP_PROP_POS_MSEC)
if current_ms >= next_target_ms:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
score = variance_of_laplacian(gray)
if score >= blur_threshold:
out_path = os.path.join(out_dir, f"{saved_count:06d}.jpg")
cv2.imwrite(out_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 95])
saved_count += 1
next_target_ms += interval_ms
cap.release()
print(f"[完成] {video_name}: 读取{total_read}帧, 保存{saved_count}张, 输出到{out_dir}")
return saved_count
def batch_process(input_dir, out_root):
video_files = glob.glob(os.path.join(input_dir, "*.mp4")) + \
glob.glob(os.path.join(input_dir, "*.avi")) + \
glob.glob(os.path.join(input_dir, "*.mov"))
total = 0
for vf in video_files:
total += process_video(vf, out_root)
print(f"批量处理结束,共保存 {total} 张图片")
if __name__ == "__main__":
batch_process("videos", "output_frames")
这个脚本里加入了拉普拉斯方差筛选,blur_threshold 默认50。这个阈值的物理意义是:画面纹理越丰富,拉普拉斯方差越大。纯色背景的画面方差几乎为0,复杂场景能到几百上千。监控视频的抽帧,50到100是一个比较合理的区间;如果是高清电影,画面本身细节多,阈值可以放宽到100以上。需要提醒的是,这个阈值不是固定的,最好抽出来一批后,肉眼检查一下被过滤的和保留的,再微调。
4. 抽帧质量优化与效率调优
4.1 抽帧频率与输出格式怎么选最合适
抽帧频率是最基础也最容易被拍脑袋决定的参数。我的建议是,先想清楚下游任务对画面时间粒度的要求:
- 视频封面/缩略图:全视频抽5到20张候选图就够了,人工挑选。
- 动作识别/行为分析:时间粒度要细,通常每秒1到5帧,太快会重复,太慢会丢失关键动作。
- 目标检测/图像分类数据集:时间间隔大一点,每1到5秒一帧即可,关键是要场景多样,而不是时间密集。
- OCR/文本识别:PPT类录屏建议每0.5到1秒一帧,因为文字停留时间短,间隔太大容易漏页。
- 视频指纹/去重:按场景切换抽帧,不做固定间隔。
输出格式方面,我强烈建议:训练数据用JPEG,质量85到95;需要二次编辑或标注的用PNG;不需要透明度信息的,别用PNG,太占空间。 JPEG的一张1920x1080高质量图片大概500KB到1MB,PNG可能5MB以上。1000张图,差距就是几个GB的磁盘空间。
输出分辨率上也提个醒。很多新人直接把原视频分辨率全量输出,4K视频一帧就是10MB,很快磁盘就满了。正确做法是:如果模型输入端就是640x640,就先用 scale 把帧缩到合适大小再输出;如果后面要人工标注,1280宽度足够看清细节。保存前缩放到目标精度,是省空间最直接的方式。
4.2 加速与资源控制技巧
抽帧看着简单,但视频一多,时间成本立刻显现。这里分享几个我常用的提速手段:
第一,优先用FFmpeg,不要用OpenCV逐帧跑长视频。OpenCV的Python接口逐帧读取有巨大的GIL开销,同样的任务FFmpeg可能几秒完成,OpenCV要几分钟。OpenCV的值在业务逻辑,不在速度。
第二,FFmpeg加 -preset ultrafast 和解码硬件加速。-preset ultrafast 主要影响编码速度(输出图片时不明显),真正提速的是 -hwaccel。比如Nvidia显卡可以加 -hwaccel cuda,Intel核显可以加 -hwaccel qsv:
bash复制# 用Nvidia硬件解码加速抽帧
ffmpeg -hwaccel cuda -i input.mp4 -vf fps=1 frames_%04d.jpg
硬件解码能显著降低CPU占用,尤其是批量处理4K视频时,效果非常明显。但没有合适的显卡驱动时,加了反而报错,稳妥起见先不加。
第三,用 -ss 做时间定位跳跃。如果你只需要视频中某几段的内容,直接用 -ss 跳跃,不要从头解码,能省大量时间。
第四,多进程并行处理多视频。多个视频文件之间完全独立,用Python的 multiprocessing 或Shell的 xargs -P 开多进程同时跑,能把CPU吃满,整体时间缩短好几倍。但要注意磁盘I/O可能成为瓶颈,如果同时写入几百个文件,建议每个进程输出到独立目录,减少锁竞争。
第五,磁盘空间预估算。抽帧之前先算一下会有多少张图片。比如视频时长10分钟,每3秒抽1帧,总共200帧,每帧1MB,总占用200MB。批量处理前先按这个公式算一遍,避免跑一半磁盘满了。
5. 常见问题与避坑经验
5.1 常见问题速查表
我在抽帧过程中踩过和帮别人排查过不少问题,整理成了一张速查表,基本覆盖了90%的报错和异常。
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 抽出的帧数量远少于预期 | fps 参数理解错误,以为 fps=1/10 是每秒抽10帧 |
fps=1/10 表示每10秒抽1帧,每秒抽10帧要写 fps=10 |
| 抽出的帧全是重复的黑屏帧 | 视频编码有问题,或 select 输出时没有加 -vsync vfr |
使用 -vsync vfr;或者改用按时间间隔抽帧 |
| 输出文件名不连续 | FFmpeg默认从0开始计数,且中间可能有输入错误帧 | 加 -start_number 1,并检查输入视频是否有损坏片段 |
| 图片有明显锯齿或模糊 | 缩放后未做滤波,或 scale 尺寸和原始宽高比不一致 |
用 scale=1280:-2 保证偶数高度,必要时用 -sws_flags lanczos |
| 抽帧非常慢,CPU占用100% | 纯CPU软解高清视频,没有启用硬件加速 | 尝试 -hwaccel cuda 或 -hwaccel qsv;或用 -threads 0 自动多线程 |
| OpenCV读取帧时间戳不准 | 部分封装格式中 CAP_PROP_POS_MSEC 不稳定 |
改用帧号计数,或先读取 fps 按帧数换算时间 |
视频明明是25fps,按 mod(n,25) 抽出来间隔不均 |
视频实际是可变帧率(VFR),帧的时间戳不一致 | 先用 ffprobe 查看 avg_frame_rate 和 r_frame_rate,确认帧率稳定后再用帧号抽帧 |
| 抽出来的帧画面偏色 | 视频流是HDR或10bit色彩,解码映射不对 | 加 -pix_fmt yuv420p 强制转8bit;或使用 -vf "zscale=t=linear:npl=100,tonemap=clip" 处理 |
| 批量抽帧到一半报错"Permission denied" | 输出目录没有写权限,或已有文件被占用 | 检查目录权限,换一个输出目录;或先删除已有输出文件再重跑 |
5.2 基于内容筛选模糊帧的实用技巧
除了拉普拉斯方差,还有几个判断画面质量的指标可以组合使用:
- Tenengrad梯度:用Sobel算子计算水平和垂直方向的梯度,响应值越高越清晰。比拉普拉斯方差对噪声更鲁棒,特别适合夜景或低光视频。
- FFT高频能量:把图像转成频域,看高频分量占比。清晰图像高频分量多,模糊图像只有低频信息。这个计算量偏大,适合离线筛选。
- 图像熵:熵值衡量信息量,纯色背景熵低,复杂场景熵高。但它无法区分"清晰复杂"和"噪声复杂",所以通常和梯度方法组合使用。
我自己常用的组合是:先用拉普拉斯方差粗筛,再抽出来人工抽检。公式很简单,score < 阈值 的直接扔掉。阈值怎么定?找10张你认为"勉强能用"的模糊帧,计算它们的方差值,取一个比这个值稍高的数作为阈值。这个方法比拍脑袋猜靠谱得多。
5.3 抽帧前的视频体检与元数据检查
很多抽帧问题其实在视频本身,和代码没关系。我强烈建议,在任何批量抽帧开始前,先用 ffprobe 把视频的元数据看一下:
bash复制ffprobe -v error -show_format -show_streams input.mp4
重点关注这几个字段:
duration:视频时长。如果你预期"每2秒抽1帧",但抽出来的帧数比时长/2少很多,说明视频有流截断或者损坏。avg_frame_rate:平均帧率。如果显示30000/1001,说明是NTSC制式(29.97fps),直接按30fps算间隔会有时间漂移,越往后误差越大。nb_frames:总的帧数,和duration × fps对比一下。如果相差很大,可能存在丢帧。codec_name:编码格式。h264、hevc、av1的处理复杂度不同。av1的软解特别慢,有条件一定要开硬件加速。
有一次我排查了半天,发现抽帧数量忽多忽少,最后用 ffprobe 一看,那个视频是拍摄设备导致的可变帧率,帧的时间戳完全不均匀。用帧号抽帧就飘了,改用时间戳抽帧才正常。这个教训让我养成了"先体检、后抽帧"的习惯。
最后再分享一个工作流技巧
从纯命令行到一个可用的抽帧流程,我建议你把所有步骤固化成一个固定工作流:先 ffprobe 看元数据,再根据业务需求选抽帧策略,然后小样本试抽(比如先抽20帧检查质量和数量),最后批量执行。批量执行以后别忘了做抽检,随机看20到50张图,确认没有黑屏、重复和严重模糊。
另外,抽帧输出目录最好带上视频名和抽帧策略参数,比如 input_1fps_1280w。这样不仅方便排查问题,后续清洗数据时,你也知道这批图片是怎么来的。否则过了几个月,你自己都分不清哪个目录是哪个视频抽出来的。
抽帧是个看似简单、实则细节极多的工作。希望这篇笔记能帮你把每条路上的坑都提前填平。
