从视频中提取特定帧的最快方法(PHP/ffmpeg/anything)


Fastest way to extract a specific frame from a video (PHP/ffmpeg/anything)

我有一个网页,它(除其他外)需要从用户上传的视频中提取特定的帧。用户在播放器中查找.mp4的特定部分,然后单击一个按钮,然后对php脚本进行ajax调用,该脚本获取.mp4和视频中的确切时间,并使用该时间提取"缩略图"帧。

我目前的解决方案是使用php exec命令:

exec("ffmpeg -i $videoPath -ss $timeOffset -vframes 1 $jpgOutputPath");

它工作得很好,只是它像糖蜜一样慢。我的猜测是,ffmpeg对于这份工作来说有点太多了,我可能可以通过利用底层库或其他东西做得更好。。。但是我完全不知道该怎么做。

理想情况下,我不想安装任何需要真正"安装过程"的东西。。。也就是说,用我的网络应用程序将可执行文件放入文件夹中是可以的,但我宁愿不必实际运行安装程序。此外,该解决方案应该能够在mac、linux和windows上运行(尽管linux是首要任务)。

我能做些什么来加快这个过程?

谢谢。

当然,您可以编写一些C/C++代码并链接到-lav*,基本上只为提取帧创建一个简化版本的ffmpeg,甚至可以将其作为php扩展(而且我不会以同一用户的身份运行它,更不用说在同一过程中了)。但结果不太可能更快,因为你只会避免一些分叉和设置开销,但你可能的问题实际上是解码,这仍然是一样的。

相反,您应该首先考虑在快速搜索模式(或快速/精确混合模式)中使用ffmpeg。他们的维基关于快速搜索:

需要在-i之前指定-ss参数

ffmpeg-ss 00:03:00-i Underorld.Awakening.avi-帧:v 1 out1.jpg

此示例将在某个位置生成一个图像帧(out1.jpg)电影开始后的第三分钟。输入将是使用关键帧进行解析,速度非常快。缺点是也将在某个关键帧(不一定位于在指定的时间(00:03:00),因此搜索将不那么准确正如预期的那样。

快速搜索不太准确,但速度要快得多,因为ffmpeg在搜索过程中实际上不需要解码(大部分)电影,而快速/准确的混合模式是一个很好的折衷方案。阅读wiki页面以了解所有可用选项。

编辑14/06/10

从FFmpeg 2.1开始,当使用FFmpeg进行代码转换(即不进行流复制)时,即使用作输入选项,-ss现在也是准确的。可以使用-noaccurate_seek选项恢复以前的行为。(来源)

因此,对于2.1+,在重新编码时,不应该再需要"混合"搜索来获得准确的结果(保存到.jpeg就是重新编码)。进行通常的快速搜索(-ss ... -i ...)而不是慢速搜索(-i ... -ss ...)就足够了。

在C/C++中直接使用ffmpeg库(正如nmaier所提到的,但没有提供资源):我也遇到了同样的问题,这花了我很多工作,但我现在已经在C++中直接使用ffmpeg库实现了一个帧提取功能(在QT框架中,但它仍然有助于普通C++)。

请参阅我的项目Video simili重复清理器Video.cpp文件中的函数QImage-Video::ffmpegLib_captureAt(const int percent,const int of Duration),它应该是一个不言自明的例子:https://github.com/theophanemayaud/video-simili-duplicate-cleaner/blob/master/QtProject/app/video.cpp