如何将有效的 ffmpeg 语句应用于 .flacs 文件夹

how to apply a working ffmpeg statement to a folder of .flacs

这是我的精彩工作声明:

ffmpeg -loop 1 -i AlbumCover.png -i AnglersTunnel.flac -c:v libx264 -tune stillimage -c:a aac -strict experimental -b:a 192k -pix_fmt yuv420p -shortest AnglersTunnel.mp4

现在我想在包含大约 200 个不同名称的不同 .flac 文件的文件夹上运行它。需要为生成的每个 mp4 使用相同的 'AlbumCover.png' 图像。我不想手动输入每个不同的 .flac 文件名。我怎么能循环这个?此外,我需要输出的 mp4 文件的名称与转换后的 .flac 文件同名。

for i in *flac; do
    ffmpeg -loop 1 -i AlbumCover.png -i "$i" -c:v libx264 -tune stillimage -c:a aac -strict experimental -b:a 192k -pix_fmt yuv420p -shortest "${i%.flac}.mp4"
done

这是一个简单的for循环和bashparameter expansion

的使用

您可以遍历所有 .flac 文件,将 .flac 后缀替换为 .mp4,如下所示:

for input in *.flac; do
    output=${input%.flac}.mp4
    ffmpeg -loop 1 -i AlbumCover.png -i "$input" -c:v libx264 -tune stillimage -c:a aac -strict experimental -b:a 192k -pix_fmt yuv420p -shortest "$output"
done

${input%.flac} 从文件名末尾删除 .flac

我的方法通常是使用魔法 $'\n' 变量来转义空格:

IFS=$'\n'; 
for i in `find . -iname '*flac'`; do 
  ffmpeg -loop 1 -i AlbumCover.png -i "%" -c:v libx264 -tune \
  stillimage -c:a aac -strict experimental -b:a 192k -pix_fmt yuv420p \
  -shortest "$(echo "$i" | sed s/\.flac$/.mp4/)"
done

查找所有 flac 文件(递归地),然后执行子 shell 将每个文件名中的 .flac 替换为 .mp4。该子 shell 作为 -c 命令的一部分执行。

我有一个模拟 ffmpeg[1] 的 ffmpeg,它似乎验证了 ffmpeg 命令的参数是否正确转义:

["-loop", "1", "-i", "AlbumCover.png", "-i", "%", "-c:v", "libx264", "-tune", "stillimage", "-c:a", "aac", "-strict", "experimental", "-b:a", "192k", "-pix_fmt", "yuv420p", "-shortest", "./File 1.mp4"]

for 循环可能是 bash 中最有用的流程控制语句,但对于这种事情,我会转向 findxargs,它们都支持使用 [=22=] 字符分隔参数,而不是使用讨厌的文件名中可能存在的字符,例如空格、换行符等。

假设所有 flac 都在您的主目录中,那么:

find . -type f -iname '*.flac' -print0 | \
xargs -0 -I % bash -c \
'ffmpeg -loop 1 -i AlbumCover.png -i "%" -c:v libx264 -tune stillimage -c:a aac -strict experimental -b:a 192k -pix_fmt yuv420p -shortest "$(echo "%" | sed s/\.flac$/.mp4/)"'

我们

$ find . -type f -iname '*.flac' -print0 | xargs -0 -I % bash -c 'ffmpeg -loop 1 -i AlbumCover.png -i "%" -c:v libx264 -tune stillimage -c:a aac -strict experimental -b:a 192k -pix_fmt yuv420p -shortest "$(echo "%" | sed s/\.flac$/.mp4/)"'
["-loop", "1", "-i", "AlbumCover.png", "-i", "./File 1.flac", "-c:v", "libx264", "-tune", "stillimage", "-c:a", "aac", "-strict", "experimental", "-b:a", "192k", "-pix_fmt", "yuv420p", "-shortest", "./File 1.mp4"]
["-loop", "1", "-i", "AlbumCover.png", "-i", "./File 10.flac", "-c:v", "libx264", "-tune", "stillimage", "-c:a", "aac", "-strict", "experimental", "-b:a", "192k", "-pix_fmt", "yuv420p", "-shortest", "./File 10.mp4"]
["-loop", "1", "-i", "AlbumCover.png", "-i", "./File 2.flac", "-c:v", "libx264", "-tune", "stillimage", "-c:a", "aac", "-strict", "experimental", "-b:a", "192k", "-pix_fmt", "yuv420p", "-shortest", "./File 2.mp4"]
...

在这种情况下,单引号很好地转义了整个命令。 Bash 被调用是因为我们需要一个子 shell 来 运行 xargs 完成它的替换之后。 find-print0xarg-0 的组合转义了每个有效的文件名。但是,我确实假设文件名不包含任何引号。

[1]

$ cat `which ffmpeg`
#!/usr/bin/ruby
puts ARGV.inspect