![将单个图像的文件名刻录到 FFmpeg 输出视频中](https://linux22.com/image/1397840/%E5%B0%86%E5%8D%95%E4%B8%AA%E5%9B%BE%E5%83%8F%E7%9A%84%E6%96%87%E4%BB%B6%E5%90%8D%E5%88%BB%E5%BD%95%E5%88%B0%20FFmpeg%20%E8%BE%93%E5%87%BA%E8%A7%86%E9%A2%91%E4%B8%AD.png)
我正在使用 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_”存储在与原始图像相同的路径中。文件名可以包含空格。