将 PNG 帧转换为 1 FPS 的视频

将 PNG 帧转换为 1 FPS 的视频

我有 1 FPS 的 PNG 格式的视频帧,我正在尝试使用 ffmpeg 将它们转换为视频。

如果我做这样的事情:

ffmpeg -i data/input-%4d.png data/output.mp4

我得到了一个 25FPS 的视频,这基本上是输入的快进(以 1FPS 捕获)。

如果我尝试:

ffmpeg -i data/input-%4d.png -r 1 data/output.mp4

我得到了 VLC 不想播放的东西:)

现在,如果我拍摄第一个视频(FF 视频)并应用滤镜来减慢速度(例如-filter:v 'setpts=24.0*PTS'),我可以让它像 1 FPS 视频一样播放,但当然代价是文件大小。我猜它会生成一堆重复的帧。

那么,问题是如何创建一个具有 1 FPS 并实际以该速度播放的视频?顺便说一句,输出格式对我来说并不那么重要。

答案1

如果您想要 FFMPEG 的单行代码生成以每秒 1 帧的速度播放的视频,您需要指定输入和输出的帧速率,如下所示:

ffmpeg -r 1 -i 数据/输入-%4d.png -pix_fmt yuv420p -r 10 数据/输出.mp4

-r 1意味着视频将在 1 处播放原始图像每秒。
-r 10意味着视频将以每秒 10 帧的速度播放。

(它-pix_fmt yuv420p只是为了确保与各种播放程序的兼容性。例如,这里需要它才能通过 Windows Media Player 播放视频。)

我测试了许多不同的输出帧速率,10 似乎是您可以使用但仍能生成 VLC 可以播放的视频的最低数字。

当然,上面的命令意味着每个原始图像都被相乘,但这是一种比您提到的“放慢速度”更简单的方法,并且根据编解码器,它可能不会产生比真正的 1-FPS 大得多的视频视频。

为了测试这一点,我刚刚制作了一个真正的 1-FPS 视频,大小为 2.24 kiB。然后,我制作了一个具有相同输入图像但以 24 FPS 输出的视频,结果为 5.76 kiB。这只是两倍多一点,远不到 24 倍。 :)

答案2

同时使用-framerate-r

例如,要获得看起来像 1FPS 的最终视频:

ffmpeg -framerate 1 -pattern_type glob -i '*.png' \
    -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4

这类似于将 PNG 帧转换为 1 FPS 的视频 | Unix 和 Linux 堆栈交换说,但我需要-framerate而不是-r让它发挥作用。

维基百科上提到了这一点:http://trac.ffmpeg.org/wiki/Slideshow#Framerates

它将输出帧速率设置30为 VLC 可以处理的 ,并将每个图像复制 30 次,以便输出视频看起来为 1 FPS。也可以看看:使用 ffmpeg 处理图像中低 fps 视频的 VLC 播放问题 |堆栈溢出

然后VLC就可以正常播放视频了。

在 Ubuntu 16.10、VLC 2.2.4、3.0.5 上测试ffmpeg,在包含 10 个 PNG 的目录中。

也可以看看:https://stackoverflow.com/questions/19267443/vlc-freezes-for-low-1-fps-video-created-from-images-with-ffmpeg

答案3

如果您稍微扩展第二个示例,如下所示:

$ ffmpeg -r 1 -i data/input-%4d.png -c:v libx264 out.mp4

需要-r 1位于 .png 文件之前,而不是之后。

来自FFmpeg 文档:

作为一般规则,选项将应用于下一个指定的文件。因此,顺序很重要,您可以在命令行上多次使用相同的选项。然后,每次出现的情况都会应用于下一个输入或输出文件。

答案4

这是VLC中的一个bug(在3.0.6版本中仍然存在)。经过一些实验我意识到VLC 因 FPS 低于 10 的视频而崩溃。因此,所有 10 FPS 或更高帧率的视频都应该不成问题。因此,目前没有干净的方法来获取可在 VLC 中播放的 1 FPS 视频(不要放弃,继续阅读)。

一种解决方法是 - 如上面的答案所示 - 通过复制图像来伪造 1 FPS 的效果(当我们实际的 FPS 等于 10 或更高时,这对于 VLC 来说是可以的)。

例子:如果你有一个包含 12 个图像的文件夹,并且你想生成一个 1 FPS 的视频(可以在 VLC 中播放),那么你需要将每个图像复制多次(假设 10 次),然后告诉 FFMPEG 生成10 FPS 视频。这样我们就会得到一个总帧数为 120 的视频,其中每个图像将播放 1 秒(因为它重复了 10 次),这简直就是 1 FPS 的假象。

我更喜欢使用fps参数而不是-r(在另一个答案中显示)在某些情况下可能会出现问题(根据官方文档)。

ffmpeg -framerate 1 -i "img (%d).jpg" -c:v libvpx-vp9 -vf "fps=10,format=yuv420p" out.mkv

由于输入-framerate低于输出fps,FFMPEG 将复制帧以达到您所需的输出帧速率(根据上面的命令为 10)。

也是重要的是要注意-framerate和 的顺序-vf fps很重要,因为此配置将应用于下一个提到的视频(输入或输出)。也就是说,根据官方文档:

选项将应用于下一个指定的文件。所以,顺序很重要...

相关内容