使用 FFmpeg / ImageMagick 从 MP4 中获取清晰的缩略图

使用 FFmpeg / ImageMagick 从 MP4 中获取清晰的缩略图

我的最终目标是从 30 分钟或 1 小时的视频中获取有意义的快照。“有意义”有点雄心勃勃,所以我简化了我的要求。

图像应该清晰,不模糊。

最初,我以为这意味着获取“关键帧”。由于关键帧很多,我决定选择最接近视频第三分钟的关键帧,这对我来说通常足够“有意义”。我遵循了以下建议:FFmpeg 命令查找最接近第 3 分钟的关键帧

但问题是这些关键帧通常(并非总是)模糊。例如:

在此处输入图片描述

然后我尝试使用 FFmpeg 为视频制作有意义的缩略图这确实有助于获得更有意义的快照,但我仍然经常(并非总是)得到像上面那样的模糊帧。

您会注意到,这种图像本质上是两个不同场景的重叠。然而,有时我会得到适合我的图像——像这样:

在此处输入图片描述

上面的图像虽然没有什么意义,但是很清晰。

理想情况下,我希望 FFmpeg 不返回模糊帧。或者,我想使用脚本来检测模糊帧并从 5 帧中选择最不模糊的帧。有人知道怎么做吗?

答案1

“有意义”是非常主观的,但“模糊”是相当客观且容易检测的。

我遇到了类似的问题,经过一番研究后,最终得到了以下算法:

  • 确定视频文件的长度(以秒为单位)。
  • 使用 ffmpeg 和场景变化检测生成 10 个 png 缩略图,例如:

    ffmpeg -ss {$skip} -i {$input} -vf "select=gt(scene\,0.3)" -r 1 -frames:v 1 {$output}
    

每次迭代$skip都会将视频长度(以秒为单位)增加 10%。参数 0.3 可能不是最合适的,但您可以随意尝试。这解决了场景重叠和/或图像完全模糊的问题。

  • 检测这 10 个缩略图的边缘并缩小它们以获得更好的 ImageMagick 性能:

    convert {$input} -thumbnail {$w}x{$h} -colorspace Gray -edge 1 {$path_to_downscaled_image}
    

我用它-thumbnail来缩放图像。然后我添加一个黑白滤镜。最后我使用半径 1 进行边缘检测。这将生成一个黑白图像,但边缘标记为白色。这意味着图像越白,其中的边缘就越多。您将得到如下结果:

在此处输入图片描述

  • 使用 ImageMagick 识别生成的黑白图像:

    identify -format '{$format}' {$path_to_downscaled_image}
    

您应该感兴趣的是 %[mean] 和 %[standard-deviation]。尝试一下,看看哪个最适合您。例如,只需按“%[mean] + %[standard-deviation]”对所有结果图像进行排序即可。在我们开始调整大小和过滤之前,找到相同的图像。

  • 最后选择最“前卫”的一个,找到它的原始版本并选择性地再次转换它:

    convert {$input} -thumbnail {$w}x{$h} -adaptive-sharpen 1.25x0.75 {$final_output}
    

我发现这-adaptive-sharpen确实有助于最终结果,因为它只会在相同的边缘处锐化图像。我尝试了不同的几何形状,发现当我将分辨率缩小到原始分辨率的四分之一时,1.25x0.75 最适合我。

我已经在 PHP 中完成了这个操作,播放一部 12 分钟的电影大约需要 25 秒,这对我来说没问题。

我希望这可以帮到你。

相关内容