将单个图像的文件名刻录到 FFmpeg 输出视频中

将单个图像的文件名刻录到 FFmpeg 输出视频中

我正在使用 FFmpeg 读取一系列单幅图像并将其输出为视频。
结果是以 1 分钟为间隔的网站截图延时视频。

现在我想使用 drawtext 命令将每幅图像的原始捕获时间刻录到生成的视频中。捕获时间在每个图像的文件名中。但我找不到 drawtext 访问输入图像文件名的选项。

另一种方法是从 drawtext 中访问每个图像的创建日期(我也找不到这样做的方法)。但我绝对更喜欢访问文件名,因为这会给我更多格式化文本的选项。

有办法吗?
如果任何建议的解决方案也适用于 Windows,那就太好了。

答案1

旧版本的 ffmpeg 无法在一行中完成此操作,因为ffmpeg它的 drawtext 过滤器不够先进。

您需要提前使用一些脚本对图像进行预处理。

类似于简单的 bash 脚本:

for i in *.png; do 
    time=$(echo $i | cut -d . -f 1)
    ffmpeg -i $i -vf "drawtext=text=$time" mod-$time.png
done

然后您可以使用 mod*.png 文件来创建视频。

答案2

看起来自从上一次回答以来,ffmpeg 已经获得了使用来自 image2 解码器的元数据自行执行此操作的能力:

ffmpeg \
    -f image2 \
    -pattern_type glob \
    -export_path_metadata 1 \
    -i '*' \
    -vf "drawtext=text='%{metadata\:lavf.image2dec.source_basename\:NA}'" \
    -y ../output.mkv

文件名不需要任何扩展名,ffmpeg 无论如何都会检测图像格式。因此可以根据需要重命名文件。由于输入是“*”,因此输出将发送到父目录,以防止混淆。

答案3

Znuff 的答案很棒(被接受和赞成),并为我自己的解决方案铺平了道路。由于它是特定于 Unix 的,而我必须在 Win 上工作,因此这是我针对 Windows 7 及更高版本的解决方案:

我使用了两个批处理文件(Master.cmd 和 Slave.cmd)循环遍历所有图像并将文件名刻录到其中。

主程序.cmd:

forfiles /p "MyImagesSubPath" /m "2014-02-15*.png" /c "cmd /c ..\Slave.cmd @file @fname

从属.cmd:

ffmpeg -i "%~1" -vf "crop=1072:1192:24:101, drawtext=text=%~2: fontcolor=white: fontsize=60: box=1: [email protected]: x=50:y=50: fontfile=c\\:\\\\Windows\\\\Fonts\\\\myfont.ttf" "mod_%~1"

解释:

需要使用两个批处理的原因有很多:
1. forfiles 的 /c 参数仅接受有限长度(253 个字符)的命令行
2. 将 FFmpeg 命令嵌套到 forfiles /c 参数中需要进行大量字符转义。

Master.cmd 中的文件名过滤器“2014-....png”用于防止循环无限循环地重新处理其自己的输出(名为“mod_....png”)。您必须调整该过滤器字符串以匹配您的源图像。

Slave 批处理从批处理目录下的子目录“MyImagesSubPath”中执行(这是您必须放置源图像的地方)。Slave.cmd 接收带和不带扩展名 (.png) 的文件名作为其两个参数。

不带扩展名的文件名参数用作要刻录到图像中的文本。生成的图像以前缀“mod_”存储在与原始图像相同的路径中。文件名可以包含空格。

相关内容