FFMPEG 中级指南/图像序列
FFMPEG 具有强大的功能集,与从图像创建视频或从视频生成图像序列有关。
要从一组图像创建视频
ffmpeg -i image-%03d.png video.webm
要从视频创建一组图像
ffmpeg -i video.webm image-%03d.png
如果没有给出更多参数,将使用一组默认值。例如,帧速率将为 25,编码将从文件名推断得出。
image-%03d.png
部分是一个文件名模式。此特定模式对应于 image-000.png
、image-001.png
、image-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.png
、image-001.png
、image-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 模式放在引号中是必要的,否则 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
编号文件具有明确定义的排序方式。在大多数情况下,人和计算机都一致同意如何对数字进行排序。对于带有前导零的数字尤其如此。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 手册和维基
更具体地说,以下页面
- http://www.ffmpeg.org/ffmpeg.html
- http://www.ffmpeg.org/faq.html#How-do-I-encode-single-pictures-into-movies_003f
- http://www.ffmpeg.org/faq.html#How-do-I-encode-movie-to-single-pictures_003f
- http://www.ffmpeg.org/ffmpeg-formats.html#image2-1
- http://www.ffmpeg.org/ffmpeg-formats.html#image2-2
- https://trac.ffmpeg.org/wiki/Create%20a%20video%20slideshow%20from%20images
- https://trac.ffmpeg.org/wiki/Create%20a%20thumbnail%20image%20every%20X%20seconds%20of%20the%20video