按正确顺序用图片制作电影

Making a movie out of pictures in correct order

短版

如何将文件 img1000.pngimg5000.pngimg10000.pngimg11000.png 按正确的顺序组合成一部电影?

更长的版本

我正在使用 ffmpeg 将模拟快照制作成电影。例如每秒应该有 5 张图像。名字是:

image0200.png
image0300.png
image0400.png
image0500.png
image1000.png
image1500.png
image2000.png
...
image8500.png
image9000.png
image9500.png
image10000.png
image15000.png

即,它们是连续的,但数字之间存在不规则的间隙。这些数字根据 '%04d' 格式化,但高于 9999。我试过

ffmpeg -y -loglevel debug -nostats \
-r:v 5 -thread_queue_size 1024 -f image2 \
-pattern_type glob -i "*[0-9][0-9][0-9][0-9].png" \
-r:v 30 -preset veryslow -pix_fmt yuv420p -crf 28 \
-an  AMDG.mp4

和许多其他变体,但要么只有两帧最终在电影中可见(即使使用 -debug 时可以找到图像),要么只使用最多 image9500.png 的文件(并且glob 似乎不允许 [0-9]{4,} 作为正则表达式),或者

    ffmpeg -y -loglevel debug -nostats \
    -r:v 5 \
    -thread_queue_size 1024 -f image2 -pattern_type glob \
       -i "image[0-9][0-9][0-9][0-9].png" \
    -r:v 5 \
    -thread_queue_size 1024 -f image2 -pattern_type glob \
       -i "image[1-9][0-9][0-9][0-9][0-9].png" \
    -r:v 30 -preset veryslow -pix_fmt yuv420p -crf 28 \
    -map 0 -map 1 \
    -an  AMDG.mp4

输出影片中显然有两个流,但只有其中一个正在播放。 (我意识到在这个过程中需要 -map 0 -map 1 才能使用两个输入流。)

在我发现的一个选项变体中(现在我已经失去了它到底是什么!)所有图像都包括在内,但顺序不是所需的:image1000.png 在 [=24= 之前显示].显然,较新版本的 ffmpeg(我有 ffmpeg version 3.4.8-0ubuntu0.2)能够像 sort -V 一样排序,因此 image10000 排在 image1000 之后,但重新安装 ffmpeg 通常不是实用的选择。同样重命名文件是不切实际的,并且创建例如具有从 0 开始并以 1 为步长的“%05d”格式的顺序名称的软链接(以便可以使用 -i '%05d')当然不优雅。

使用 -concat 过滤器,如 https://unix.stackexchange.com/questions/77016/ffmpeg-pattern-type-glob-not-loading-files-in-correct-order,即

  ffmpeg -y -loglevel debug -nostats -r:v 5 \
    -thread_queue_size 1024 -f image2 -f concat \
    -safe 0 -i <(find . -maxdepth 1 -regex 'image*.png' \
       -exec echo "file $(pwd)/"{} \; | sort -V) \
    -r:v 30 -codec:v libx264 -preset veryslow -pix_fmt yuv420p -crf 28 \
    -an \
    AMDG.mp4

处理花费了很长时间,使整个系统变得迟缓,同时制作了一个大约 60 kB 的电影,只显示了两个不同的图像。

我的印象是同时出现了几个问题...如果您能提供帮助,谢谢!

最终真正的问题是,尝试不同的事情导致我将源 PNG 图像相互覆盖,导致电影中的图像看起来像和明显不正确的重复。

供参考,将图像按正确顺序排列的工作命令(不直接使用 -filter image2 -pattern_type glob -i "*.png")是:

ffmpeg -y -loglevel warning \
 -r:v 5 -f concat -safe 0 \
  -i <(find . -maxdepth 1 -name '*.png' \
  -exec echo "file $(pwd)/"{} \; | sort -V \
   | sed 's/$/\nduration 1.0/' | tee list.txt) \
  -vf fps=30 -codec:v libx264 -preset veryslow \
  -pix_fmt yuv420p -crf 28 \
  -an AMDG.mp4

其中:

  • -y 不询问就覆盖输出文件;
  • -r:v 5 每秒使用 5 个输入图像;
  • -maxdepth 1部分避免在子目录中查找文件(适应口味);
  • sed 部分用换行符 (\n) 替换 (s) 每一行结尾和换行符 ($),然后是 duration 1.0 (这个数字似乎是任意的)在 find 正在构建的隐式输入文件中的每个 file XXXX 行之后。此列表用于调试保存到 list.txt;删除 | tee list.txt 不要这样做;
  • safe 0 实际上是安全的,允许文件路径包含 find.
  • 返回的 ./

如果您的输入文件名包含空格,您将需要尝试处理重定向部分。