如何将子目录中的所有 .wav 文件转换为 .flac?

如何将子目录中的所有 .wav 文件转换为 .flac?

我有一些 wav 格式的歌曲。我想将它们转换为 flac (也是无损的,但有压缩)。

该解决方案需要递归通过子目录来查找 .wav 或 .WAV 文件(最好不区分大小写),将它们转换为 .flac 并将 .flac 文件输出到不同的目录树。原始的 wav 文件位于 ~/Music 中,输出的 flac 文件可以放入 ~/Music_Flac 中。

我使用的是 Arch Linux x86_64,并且我有 ffmpeg,如下所示:

ffmpeg version 3.4.2 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 7.3.0 (GCC)
configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-avisynth --enable-avresample --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libass --enable-libbluray --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-shared --enable-version3 --enable-omx
libavutil      55. 78.100 / 55. 78.100
libavcodec     57.107.100 / 57.107.100
libavformat    57. 83.100 / 57. 83.100
libavdevice    57. 10.100 / 57. 10.100
libavfilter     6.107.100 /  6.107.100
libavresample   3.  7.  0 /  3.  7.  0
libswscale      4.  8.100 /  4.  8.100
libswresample   2.  9.100 /  2.  9.100
libpostproc    54.  7.100 / 54.  7.100

答案1

如果你想代替wav我发现最简单的方法flac是使用flac二进制文件:

find . -name '*.wav' -exec flac --best {} --delete-input-file \;

以下是该命令不同部分的细分:

  • find .:该命令搜索当前目录及其所有子目录(以 表示.)中的文件。

  • -name '*.wav':该标志指定我们正在寻找具有.wav扩展名的文件。是*匹配任何字符或字符组的通配符,因此该标志将匹配任何以.wav.

  • -exec:此标志告诉find命令对匹配搜索条件的文件执行命令。

  • flac --best {} --delete-input-file:这是对匹配文件执行的命令。是{}一个占位符,表示命令正在处理的文件find。该flac命令使用标志指定的最高压缩级别将文件转换为 FLAC 格式--best。该--delete-input-file标志告诉命令在成功转换为 FLAC 格式后flac删除原始文件。.wav

  • \;:这是命令结束信号所必需的,flac以便-exec选项正常运行。

答案2

find+ffmpeg解决方案:

find ~/Music -type f -iname "*.wav" -exec sh -c \
'bn=${1##*/}; bn=${bn%.*}; ffmpeg -loglevel 16 -i "$1" "${0}${bn}.flac"' ~/Music_Flac/ {} \;
  • $0- 作为目标目录传递到 shell 命令中~/Music_Flac/
  • $1- 作为文件路径传递到 shell 命令中{}
  • bn=${1##*/}- 不带目录路径的文件基名
  • bn=${bn%.*}- 扩展名被截断的文件基名
  • -loglevel 1616- 设置使用的日志记录级别ffmpeg

答案3

另一种选择是使用 bash 的 globbing 来查找 wav 文件,然后使用 shell 参数扩展功能来更改目录结构和文件名:

shopt -s globstar nocaseglob
for input in Music/**/*.wav
do
  indir=$(dirname "$input")
  outdir=${indir/#Music/Music_Flac}
  [ ! -d "$outdir" ] && mkdir -p "$outdir"
  infile=$(basename "$input")
  outfile=${infile%.???}.flac
  echo ffmpeg -i "$input" "${outdir}/${outfile}"
done

如果文件只有*.wav*.WAV,您可以跳过shopt nocaseglob并改用for input in Music/**/*.wav Music/**/*.WAV

我不知道您想对 ffmpeg 使用哪些选项,但我提供了echo您可以构建的输入和输出文件路径的示例。

在此示例目录树上:

$ tree Music
Music
├── a.wav
├── b.WAV
├── c d.wav
└── subdir1
    ├── a.wav
    ├── b.WAV
    ├── c d.wav
    └── subdir2
        ├── a.wav
        ├── b.WAV
        └── c d.wav

示例命令输出为:

ffmpeg -i Music/a.wav Music_Flac/a.flac
ffmpeg -i Music/b.WAV Music_Flac/b.flac
ffmpeg -i Music/c d.wav Music_Flac/c d.flac
ffmpeg -i Music/subdir1/a.wav Music_Flac/subdir1/a.flac
ffmpeg -i Music/subdir1/b.WAV Music_Flac/subdir1/b.flac
ffmpeg -i Music/subdir1/c d.wav Music_Flac/subdir1/c d.flac
ffmpeg -i Music/subdir1/subdir2/a.wav Music_Flac/subdir1/subdir2/a.flac
ffmpeg -i Music/subdir1/subdir2/b.WAV Music_Flac/subdir1/subdir2/b.flac
ffmpeg -i Music/subdir1/subdir2/c d.wav Music_Flac/subdir1/subdir2/c d.flac

...以及mkdir一路上所需的命令。

答案4

除了我选择的 @RomanPerekhrest 的答案作为问题的正确答案之外,还有一个效果很好的 GUI 解决方案:

soundkonverter,soundKonverter 处于维护模式,欢迎 PR,下载soundkonverter的源码_GitHub_酷徒

它也在 Arch 仓库中:

Arch Linux - soundkonverter 3.0.1-1 (x86_64)

相关内容