跳转到内容

FFMPEG 中级指南/图像序列

来自维基教科书,开放世界中的开放书籍

FFMPEG 具有强大的功能集,与从图像创建视频或从视频生成图像序列有关。

要从一组图像创建视频

 ffmpeg -i image-%03d.png video.webm

要从视频创建一组图像

 ffmpeg -i video.webm image-%03d.png

如果没有给出更多参数,将使用一组默认值。例如,帧速率将为 25,编码将从文件名推断得出。

image-%03d.png 部分是一个文件名模式。此特定模式对应于 image-000.pngimage-001.pngimage-002.png,一直到 image-999.png。“%03d”表示三个零填充的十进制数字的序列。关于文件名模式还有更多内容将在后面的部分中解释。

使用图像序列工作的规范形式是使用 -f image2 参数,如下所示

 ffmpeg -f image2 -i image-%03d.png video.webm

 ffmpeg -i video.webm -f image2 image-%03d.png

但是 ffmpeg 在推断这些信息方面非常出色,因此本章将在所有示例中省略该参数,除非绝对必要。


从图像序列制作视频

[编辑 | 编辑源代码]
 ffmpeg -i image-%03d.png video.webm

这将创建一个名为 video.webm 的视频,它来自名为 image-000.png、image-001.png、image-002.png 的图像文件,一直到最后一个按顺序编号的三位数图像文件。

图像和视频的编码是从扩展名推断出的。默认帧速率为 25 fps。视频宽度和高度取自图像。图像必须都具有相同的尺寸。

文件名编号

[编辑 | 编辑源代码]

Ffmpeg 预计编号从 0(在本例中为 000)开始。如果您的文件没有从 000 开始,请使用参数 -start_number 告诉 ffmpeg 您的文件的第一个数字

 ffmpeg -start_number 100 -i image-%03d.png video.webm

同一个参数可以用来跳过一定数量的文件并从某个数字开始。

编号必须是连续的。Ffmpeg 将在最后一个连续编号的文件名处停止。

例如,如果您有以下文件

 image-000.png
 image-001.png
 image-002.png
 image-005.png

那么 ffmpeg 只会处理前三个文件,忽略最后一个文件。如果您有缺失的编号,您可以使用 glob 模式 或将所有剩余文件重命名以填补空白。

帧速率

[编辑 | 编辑源代码]

默认帧速率为 25 fps。这意味着每张图片显示 1/25 秒。对于大多数人类的眼睛来说,这是一种速度,可以创造出流畅动画的错觉。如果您仍然希望每秒有更多帧,请使用 -framerate 参数

 ffmpeg -framerate 60 -i image-%03d.png video.webm

如果您想制作幻灯片,则必须降低输入帧速率。以下命令将显示每张图片 5 秒长

 ffmpeg -framerate 1/5 -i image-%03d.png video.webm

可能需要强制提高视频帧速率

 ffmpeg -framerate 1/5 -i image-%03d.png -r 30 video.webm

具有不同持续时间的幻灯片

[编辑 | 编辑源代码]

您可以使用 zoompan 过滤器制作每张图片持续时间不同的幻灯片。在下面的示例中,每张图片显示 1 秒(25 帧),除了第 4 张图片(枚举从 0 开始)显示 3 秒(25+50 帧),第 6 张图片显示 5 秒(25+100 帧)。

 ffmpeg -i image-%3d.jpg -vf "zoompan=d=25+'50*eq(in,3)'+'100*eq(in,5)'" test.mp4

图像之间交叉淡入淡出的幻灯片

[编辑 | 编辑源代码]

您可以使用 zoompan 和 framerate 过滤器的组合来制作图像之间交叉淡入淡出的幻灯片。“A”是每张图片显示多长时间(不包括交叉淡入淡出持续时间)的持续时间(以秒为单位),“B”是交叉淡入淡出持续时间(以秒为单位)。

*此示例完全错误,只包含前 3 张图片*

ffmpeg -i IMG_%3d.jpg -vf zoompan=d=(A+B)/B:fps=1/B,framerate=25:interp_start=0:interp_end=255:scene=100 -c:v mpeg4 -maxrate 5M -q:v 2 out.mp4


创建 mp4[1]

ffmpeg -framerate 60 -r 60 -i image%06d.png -pix_fmt yuv420p -profile:v high -level:v 4.1 -crf:v 20 -movflags +faststart output.mp4
  • 对于 60 fps 以外的情况,更改帧速率和 r
  • 输入为 image000001.png、image000002.png、...、%06d 表示一个带有六位数字的零填充数字,如果您的输入图像命名方式不同,请更改
  • -pix_fmt yuv420p 是大多数播放器兼容所需的(默认值为 yuv444 甚至 rgb,大多数播放器根本无法很好地处理)
  • -profile:v、-level:v 也会控制兼容性设置,4k 可能需要更高的级别设置
  • -crf:v 是质量与大小的控制,数字越小,质量越高,文件大小越大,数字越大,质量越低,文件大小越小,crf 20 的质量非常高,据我所知,每改变 6 个数字就会使文件大小改变 2 倍
  • -movflags +faststart 是流式传输所需的(否则,整个文件必须下载才能开始播放)
  • 如果您需要,ffmpeg 还可以添加/编码音频轨

从视频制作图像序列

[编辑 | 编辑源代码]
 ffmpeg -i video.webm image-%03d.png

这将从 video.webm 文件中每秒提取 25 张图片,并将其保存为 image-000.pngimage-001.pngimage-002.png,一直到 image-999.png。如果帧数超过 1000 帧,则最后一帧将被剩余帧覆盖,只保留最后一帧。

图像和视频的编码是从扩展名推断出的。默认帧速率为 25 fps。图像宽度和高度取自视频。

每秒提取一张图片

 ffmpeg -i video.webm -vf fps=1 image-%03d.png

从特定时间提取一张图片

 ffmpeg -i video.webm -ss 00:00:10 -vframes 1 thumbnail.png

文件名模式

[编辑 | 编辑源代码]

通常 ffmpeg 只有一个输入文件和一个输出文件,但是当我们要从一组图像创建视频时,我们就有一组输入文件。同样,当从视频文件提取图像时,也会有一组输出文件。文件名模式是一个伪文件名,用于描述一组文件名。

文件名模式大致有三种类型

模式类型 对应的文件名 描述
image-%03d.png
 image-000.png
 image-001.png
 image-002.png
 ...
 image-999.png
带前导零的编号
image-%d.png
 image-1.png
 image-2.png
 ...
 image-9.png
 image-10.png
 image-11.png
 ...
 image-99.png
 image-100.png
 ...
不带前导零的编号
image-*.png

(需要一个参数来启用)

 image-a.png
 image-b.png
 image-c.png
 ...
 image-foo.png
 image-bar.png
 ...
 image-.png
 ...
未编号或无规律模式

从技术上讲,还有第四种形式:单个图像形式。但这只是一个简单的特殊情况,在本节中将不再讨论。

带前导零的编号

[编辑 | 编辑源代码]

此模式

 image-%03d.png

对应于以下文件名

 image-000.png
 image-001.png
 image-002.png
 ...
 image-999.png

换句话说:字符串 image- 后面跟着三位数字,后面跟着字符串 .png

文件名扩展机制的核心是字符 % 开始并以字符 d 结束的子字符串。% 之前的部分和 d 之后的部分被逐字接收。%d 之间的所有内容都将被替换为一个或多个数字。

一般形式为 %0Nd,其中 N 是一个大于零的数字,用于确定数字的数量。

注意:%0Nd 符号在许多编程语言中很常见。该符号之所以复杂是因为它被设计用来适应许多不同的用例。FFmpeg 开发者借用了这个符号并将其简化为一个用例:数字位数。因此,它可能显得过于复杂。

文件名中的百分号

[编辑 | 编辑源代码]

如果文件名本身包含 % 字符,则存在一个特殊情况。因为 % 字符在模式中具有特殊含义,因此需要小心。模式中的单个 % 字符将被解释为要由数字替换的子字符串的开头。要指定文字 %,必须在模式中将其加倍。这在技术术语中称为“转义”字符。

例如,这个模式

 image-%02d%%.png

对应于以下文件名

 image-00%.png
 image-01%.png
 image-02%.png
 ...
 image-99%.png

不带前导零的编号

[编辑 | 编辑源代码]

如果文件名中的数字没有用前导零填充,则模式为 %d

此模式

 image-%d.png

对应于以下文件名

 image-1.png
 image-2.png
 ...
 image-9.png
 image-10.png
 image-11.png
 ...
 image-99.png
 image-100.png
 ...

未编号或无规律模式

[编辑 | 编辑源代码]

如果文件名没有使用数字编号或没有以其他方式定期格式化,则可以使用 glob 模式。glob 模式必须使用参数 -pattern_type glob 启用。请注意,这在 Windows 上不受支持。

带有 glob 模式启用的示例 ffmpeg 命令

 ffmpeg -pattern_type glob -i "image-*.png" video.webm

此模式

  "image-*.png"

对应于以下文件名

 image-a.png
 image-b.png
 image-c.png

但也适用于以下文件名

 image-foo.png
 image-bar.png

也适用于

 image-.png

以及任何以字符串 image- 开头、后面跟着任何内容、最后以字符串 .png 结尾的文件名。

一般来说,模式 * 对应于任何长度的任何内容,这意味着即使是空字符串也是如此。

还有更多 glob 模式。例如,? 对应于任何单个字符。但我们这里不会深入探讨。感兴趣的读者可以在维基百科关于 glob (编程) 的页面中找到更深入的信息。

引用 glob 模式

[编辑 | 编辑源代码]

将 glob 模式放在引号中是必要的,否则 shell 会在执行命令之前扩展 glob。

例如,此命令中的 glob 模式

 ffmpeg -pattern_type glob -i image-*.png video.webm

将由 shell 扩展为

 ffmpeg -pattern_type glob -i image-foo.png image-bar.png video.webm

然后才执行。请注意,此命令具有不同的含义,因为现在 image-bar.png 是第二个文件名参数,而 video.webm 是第三个文件名参数。

当放在引号中时,shell 不会扩展 glob 模式

 ffmpeg -pattern_type glob -i "image-*.png" video.webm

来自 glob 模式的文件顺序

[编辑 | 编辑源代码]

编号文件具有明确定义的排序方式。在大多数情况下,人和计算机都一致同意如何对数字进行排序。对于带有前导零的数字尤其如此。015 显然比 110 先。没有前导零会变得更加复杂。大多数计算机将 15 排在 110 之后。但这个问题可以通过 %d 符号解决。

当文件不再使用数字编号或没有定期编号时,事情会变得非常奇怪。例如,ae 应该排在 aaa 之前还是之后?计算机是确定性的,并且总是对如何排序事物有一个概念,但这种排序概念对于人类来说不一定有意义。

来自 glob 模式的文件顺序由 glob 系统调用决定。在大多数系统上,可以通过名为 LC_COLLATE 的环境变量来操作 glob 系统调用的排序概念。但这本书不会讨论这一点。

对于少量文件,可以通过让 shell 扩展 glob 来检查 glob 返回的顺序。这是因为大多数 shell 使用与 ffmpeg 相同的 glob 系统调用。

在 shell 中键入此命令

 echo image-*.png

将打印一个文件名列表。相同顺序的相同列表将是 ffmpeg 处理的文件列表,如果给定 glob 模式。

如果顺序不令人满意或数量过大,无法让人类检查,则最好的解决方法是将文件重命名为定期编号,然后使用 %0Nd 模式。

位于以下位置的精美 ffmpeg 手册和维基

更具体地说,以下页面

  1. fractalforums.org : 创建视频
华夏公益教科书