FFmpeg 可以从视频中捕获图像,这些图像可以用作缩略图来表示视频。最常见的方法是在FFmpeg 维基。
但是,我不想在某些间隔内随机挑选帧。我在 FFmpeg 上找到了一些使用过滤器来捕捉场景变化的选项:
该过滤器thumbnail
尝试找到视频中最具代表性的帧:
ffmpeg -i input.mp4 -vf "thumbnail,scale=640:360" -frames:v 1 thumb.png
以下命令仅选择与之前相比变化超过 40% 的帧(因此可能是场景变化)并生成 5 个 PNG 序列。
ffmpeg -i input.mp4 -vf "select=gt(scene\,0.4),scale=640:360" -frames:v 5 thumb%03d.png
以上命令的信息来源法比奥·索纳蒂。第二个方法似乎更好,因为我可以获取 n 张图片并挑选出最好的一张。我试了一下,它生成了 5 次相同的图像。
进一步的调查让我发现:
ffmpeg -i input.mp4 -vf "select=gt(scene\,0.5)" -frames:v 5 -vsync vfr out%02d.png
-vsync vfr
确保您获得不同的图像。这仍然总是选择视频的第一帧,在大多数情况下,第一帧是片尾字幕/徽标,没有意义,所以我添加了-ss
3 以丢弃视频的前 3 秒。
我的最终命令如下:
ffmpeg -ss 3 -i input.mp4 -vf "select=gt(scene\,0.5)" -frames:v 5 -vsync vfr out%02d.jpg
这是我能做的最好的了。我注意到,由于我只挑选了 5 个视频,它们大多都是从视频的开头开始的,可能会错过视频后面发生的重要场景
我希望向您请教是否有其他更好的选择。
答案1
理想情况下,如何在 5 个时间跨度内寻找第一个 >40% 变化的帧,其中时间跨度是视频的第 1、2、3、4 和 5 个 20%。
您也可以将其分成 6 个时间跨度并忽略第一个时间跨度以避免损失信用。
实际上,这意味着在应用场景变化检查和参数来丢弃视频的第一部分时,将 fps 设置为一个较低的数字。
...就像是:
ffmpeg -ss 3 -i input.mp4 -vf "select=gt(scene\,0.4)" -frames:v 5 -vsync vfr -vf fps=fps=1/600 out%02d.jpg
答案2
定义有意义的很难,但如果你想有效地制作跨越整个视频文件的 N 个缩略图,这就是我在制作时使用用户上传的内容生成缩略图的方法。
伪代码
for X in 1..N
T = integer( (X - 0.5) * D / N )
run `ffmpeg -ss <T> -i <movie>
-vf select="eq(pict_type\,I)" -vframes 1 image<X>.jpg`
在哪里:
- D -
ffmpeg -i <movie>
单独读取视频时长,或者ffprobe
顺便说一下,具有很好的 JSON 输出编写器 - N - 您想要的缩略图总数
- X - 缩略图编号,从 1 到 N
- T - 缩略图的时间点
简单来说,上面记录了电影每个分区的中心关键帧。例如,如果电影时长 300 秒,而您想要 3 个缩略图,那么在 50 秒、150 秒和 250 秒后需要一个关键帧。对于 5 个缩略图,则分别为 30 秒、90 秒、150 秒、210 秒、270 秒。您可以根据电影时长 D 调整 N,例如,5 分钟的电影将有 3 个缩略图,但超过 1 小时的电影将有 20 个缩略图。
表现
对于~1GB H.264,每次调用上述ffmpeg
命令只需几分之一秒(!)。这是因为它会立即跳转到<time>
位置(记住-ss
之前-i
)并获取第一个关键帧,这实际上是完整的 JPEG。渲染电影以匹配精确的时间位置不会浪费时间。
后期处理
您可以将上述方法与scale
或任何其他调整大小方法混合使用。您还可以删除纯色框或尝试将其与其他滤镜(如)混合使用thumbnail
。
答案3
尝试这个
ffmpeg -i input.mp4 -vf fps= no_of_thumbs_req/total_video_time out%d.png
使用此命令,我可以生成代表整个视频的所需数量的缩略图。
答案4
我曾经做过类似的事情,但我导出了视频的所有帧(以 1 fps 为单位),并将它们与我找到的用于计算图像之间差异的 perl 实用程序进行比较。我将每一帧与之前的缩略图进行比较,如果它与所有缩略图都不同,我会将其添加到缩略图集合中。这样做的好处是,如果您的视频从场景 A 移动到 B,然后又返回到 A,ffmpeg 将导出 A 的 2 帧。