任务,以及为什么它比看起来更复杂
“给我这个剪辑的每秒一帧”是最常见的视频杂务之一。 QA 测试人员需要均匀间隔的屏幕截图才能附加到错误报告中。研究人员需要将采样的图像序列输入注释工具。一位社交编辑需要从两分钟的剪辑中截取二十张候选剧照,而无需手动清理时间线。
任务本身很简单。让它变得棘手的是,当你仔细观察时,“每秒一帧”是模糊的。您的意思是每秒播放时间一帧,还是每个 N第一个帧?这些是不同的事情:24 fps 剪辑和 60 fps 剪辑在第一次读数下产生相同的计数,而在第二次读数下产生截然不同的计数。选择错误的一个,您要么得到一个几乎重复的文件夹,要么得到一个太稀疏而无用的序列。
下面的两种方法都会产生相同的像素。它们的不同之处在于你表达你想要的东西的方式,以及你发现你表达错误的速度。
方法 1:FFmpeg,逐个参数
规范的命令很短:
ffmpeg -i input.mp4 -vf fps=1 -q:v 2 frame_%04d.jpg
每一部分都很重要:
-i input.mp4—源文件。 FFmpeg 读一遍,从头到尾;它不会单独查找每个时间戳。-vf fps=1- 执行实际工作的视频过滤器。fps=1意味着 播放时间每秒输出一帧,无论源帧速率如何。使用fps=1/5每五秒一帧,或fps=2每秒两帧。这是播放时的读数。-q:v 2— JPEG 质量,按倒转比例计算,其中 2 接近无损,31 被严重压缩。省略它,您将获得 FFmpeg 的默认值,它明显比大多数人预期的要柔和。如果您想要无损输出,请写入frame_%04d.png,然后完全删除此标志。frame_%04d.jpg—输出模式。%04d将计数器补零为四位数:frame_0001.jpg,frame_0002.jpg。填充物不是装饰性的;请参阅下面的编号问题。
如果您想要其他阅读 - 每个 N第一个编码帧而不是编码流的每个 N 秒 - 过滤器更改:
ffmpeg -i input.mp4 -vf "select=not(mod(n\,10))" -vsync vfr frame_%04d.png
这会将帧保留在帧索引 n 可被 10 整除, -vsync vfr 阻止 FFmpeg 复制帧以填充恒定的输出速率。关闭该标志,您将获得比您要求的更多的文件,这是一个常见且令人困惑的第一个结果。
为了将工作限制在一个片段中, -ss 之前 -i 因此 FFmpeg 在解码之前进行搜索,而不是解码和丢弃:
ffmpeg -ss 00:01:30 -to 00:02:15 -i input.mp4 -vf fps=1 frame_%04d.png
方法2:在浏览器中执行相同的作业
此网站上的帧提取器 映射到相同的两个读数,并且歧义在界面中明确显示,而不是隐藏在过滤器字符串中。
- 将文件放入。 它直接从磁盘读取到浏览器内存中 - 没有上传,因此 3 GB 源立即开始处理,而不是在传输后。
- 选择提取方法。 “时间间隔”相当于
fps=1/N—您以秒为单位输入间隙。 “帧速率 (FPS)”相当于select/mod过滤器 - 您输入 N 保留每一帧 N第帧。 - 提取前请阅读帧计数提示。 这是最节省时间的部分。界面显示当前设置将生成多少图像 之前 任何东西都可以运行,因此 4,000 个文件的错误变成您看到的数字,而不是您发现的文件夹。
- 设置格式和质量。 PNG 进行无损、当尺寸很重要时,JPG 或 WebP 具有 10–100% 滑块。当帧进入分析或编辑时,滑块位置对应于
-q:v控件,表达了大多数人的想法。 - 根据需要修剪范围。 双手柄滑块是
-ss/-to等效,拖动时会显示时间戳。 - 出口。 帧出现在预览网格中;单击其中一个单独保存,或将整个集合作为单个 ZIP。
导出规则用于选择间隔的拇指: 进行说话或屏幕录制,每 2-5 秒 1 帧捕获每个有意义的内容状态改变。对于运动或任何快速运动的事物,每秒 2-5 帧。保留“每一帧”进行真正的帧精确分析 - 每分钟 60 fps 相当于 3,600 张图像和几 GB 的 PNG。
三个实际上花费了人们时间的问题
1. 输出是数千个几乎相同的帧
几乎总是单位混淆:你的意思是“每 10 帧”并写道 fps=10,这意味着十帧 每秒 — 在 30 fps 源上,图像比天真的预期多 3 倍,而不是少 3 倍。
在运行任何操作之前,先进行算术运算。播放时间模式: duration ÷ interval。帧索引模式: duration × source_fps ÷ N。 “每 10 帧”的 10 分钟 30 fps 剪辑为 600 × 30 ÷ 10 = 1,800 个图像。如果这个数字让您感到惊讶,请在开始之前而不是之后进行调整。在浏览器工具中,相同的数字会自动出现在间隔字段下。
2. 提取在长视频中途停止
双方的原因不同,所以修复方法也不同。
对于 FFmpeg,停顿通常与磁盘相关 - 数千个 PNG 登陆一个目录和文件系统(而不是解码器)成为瓶颈。写入一个新的空目录,当您不需要无损时,首选 JPG,并将很长的源分成具有 -ss/-to.
在浏览器中,限制是 RAM:每个提取的帧都保存在内存中,直到您下载 ZIP。几百个4K PNG就是好几GB,一个tab就可以干掉了。可靠的模式是分块工作 - 使用时间范围滑块选择 0:00–2:00,下载 ZIP,然后将范围移动到 2:00–4:00。在进行大型作业之前关闭其他选项卡确实有帮助,并且质量为 85-90% 的 JPG 可以将内存压力降低几倍,对于大多数用途来说没有明显差异。
3.帧编号破坏了导入顺序
导出后看起来不错。将文件名按文本排序的工具(大多数都是这样) frame_10.png 之前 frame_2.png,因为“1”逐个字符地排在“2”之前。您的序列回放时是混乱的,原因尚不清楚。
修复方法是零填充,宽度足以容纳您将要获得的最大计数。产生。这就是 %04d 用于; use %05d 如果您可能超过 9,999 帧。浏览器工具会自动填充,这是其输出倾向于直接放入图像序列导入器而无需重命名的主要原因。
当FFmpeg仍然是正确的选择
很多时间。这并不是浏览器全面获胜的情况:
- 任何有脚本或计划的事情。 cron 作业、CI 步骤、服务器端管道——浏览器根本无法参与这些。
- 批处理多个文件。 超过 200 个剪辑的 shell 循环在 FFmpeg 中是微不足道的,而在其他地方则很乏味。
- 浏览器不会解码的编解码器。 ProRes、DNxHD、原始相机格式、不寻常的容器。如果浏览器无法播放它,则无法从中提取。 FFmpeg 几乎可以处理所有事情。
- 提取期间过滤。 去隔行、缩放、色彩空间转换、裁剪、场景变化检测——所有这些都可以在同一通道中作为滤镜使用。
- 可重复性。 自述文件中的命令是准确的。 “将滑块设置到大约此处”不是。
浏览器工具更适合一次性工作,适合那些不想为临时任务安装和维护工具链的人,当源足够机密以至于仅本地处理很重要时,以及当您想在提交导出之前查看框架时。这些是真正不同的情况,而不是排名。
快速参考
| 你想要什么 | FFmpeg | 浏览器工具 |
|---|---|---|
| 每秒一帧 | -vf fps=1 |
时间间隔 = 1 |
| 每 5 秒一帧 | -vf fps=1/5 |
时间间隔 = 5 |
| 每 10 个编码帧 | -vf "select=not(mod(n\,10))" -vsync vfr |
帧速率模式,N = 10 |
| 仅 1:30 到 2:15 | -ss 00:01:30 -to 00:02:15 |
时间范围滑块 |
| 无损输出 | .png 输出模式 |
格式 = PNG |
| 较小的文件 | -q:v 5 和 .jpg |
JPG + 质量滑块 |
| 运行前查看计数 | 手动计算 | 显示在间隔字段下 |
| 保存前预览 | 打开输出文件夹 | 内置预览网格 |
| 自动化/批量 | Shell 循环、cron、CI | 不可能 |
| ProRes、DNxHD、原始 | 支持 | 仅浏览器解码的内容 |
无论您选择哪条路线,间隔决策都是第一位的,工具是第二位的。计算出您实际需要的帧数,在开始之前确认计数,其余的都是机械的。