批量处理音频格式转换

之前,由于需要批量对不少音频文件做格式转换,以及批量对文件进行重命名等,所以在网上找了不少教程,最后汇总成了这边文章。

针对以上需求,主要包括两方面的操作:

  1. 使用 FFmpeg 这个强大的命令行工具,来实现音视频文件的录制和转换。
  2. Windows 平台上针对文件的批处理任务,可以通过命令行的形式,也可以通过编写脚本的形式。

FFmpeg 的简单使用

FFmpeg 功能非常强大,命令也较多,这里先简单以对话体的形式,给出一些常见的基本命令。

  • 如何将 music.wav 音频文件转换为 music.mp3 音频文件?
1
ffmpeg -i music.wav music.mp3
  • 如何将 music.wav 音频文件转换为指定比特率的 music.mp3 音频文件?
1
2
3
4
5
# 转换为 192kbps 的 mp3 格式音频文件
ffmpeg -i music.wav -b:a 192K music.mp3

# 转换为 320kbps 的 mp3 格式音频文件
ffmpeg -i music.wav -b:a 320K music.mp3
  • 如何截取某段多媒体文件的部分片段,比如一段 30 分钟的音频?
1
2
# 截取从 mp3 文件从第 30 秒开始的 1 分钟片段
ffmpeg -i input.mp3 -ss 00:00:30 -t 60 -b:a 320K output.mp3
  • 如何提取某段视频文件内的音频?
1
2
# -vn 表示 disable video
ffmpeg -i input.mp4 -vn audio_only.mp3

Windows 平台的批处理任务

假设现在有一个目录,名字叫做 directory,需要进行处理的文件都放在这个目录内,包含 2 个 .wav 音频文件,2 个 .txt 文本文件,以及一个子目录 subdir,子目录内有一个 .txt 文本文件和一个 .wav 音频文件。目录树结构如下:

1
2
3
4
5
6
7
8
directory
-subdir
-file_in_sub_dir.txt
-song_in_sub_dir.wav
-file01.txt
-file02.txt
-song01.wav
-song02.wav

预备知识,一个完全合格的路径名,在 Windows 系统下包含 4 个部分:盘符、路径、文件名、扩展名。以下面这个文件为例,E:\path\to\file.txt

  • E: 是盘符
  • \path\to\ 是路径
  • file 是文件名
  • .txt 是扩展名

for in 是批处理脚本或者命令行中用来循环的语句,% 开头用来指代一个变量,通常只有一个字母,比如 %i 或者 %fin 后面接 * 或者 *.* 表示匹配任意扩展名的文件,接 .mp3 表示匹配 .mp3 音频文件。
do 后面接的命令表示对循环内的文件的操作。
~ 是一个增强符号,后面跟特定的修饰符,假如 %i 这个变量指代的文件是 file.txt,那么:

  • %~fi 表示将 %i 这个变量指代的文件扩展到一个完全合格的路径名:E:\path\to\file.txt,依次包含盘符、路径、文件名、扩展名。
  • %~di 仅将 %i 扩充到盘符:E:
  • %~pi 仅将 %i 扩充到路径:\path\to\
  • %~ni 仅将 %i 扩充到文件名:file
  • %~xi 仅将 %i 扩充到文件扩展名:.txt
  • %~ti 仅将 %i 扩充到文件的日期和时间:2020\12\11 周五 14:15
  • %~zi 仅将 %i 扩充到文件的大小:38101292,单位是 bit
  • 以上修饰符可以自由组合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 打印目录内任意扩展名的直接子文件名(包含扩展名,不包含路径和盘符,比如这里的 song01.wav),即不包括子目录,也不包括子目录内的文件
for %i in (*) do echo %i

# 打印目录内扩展名为 wav 的直接子文件名(包含扩展名,不包含路径和盘符,比如这里的 song01.wav),即不包括子目录,也不包括子目录内的文件
for %i in (*.wav) do echo %i # song01.wav song02.wav

# 打印目录内扩展名为 wav 的直接子文件的文件名(不包含扩展名)
for %i in (*.wav) do echo %~ni # song01 song02

# 打印目录内扩展名为 wav 的直接子文件的路径和文件名(不包含扩展名)
for %i in (*.wav) do echo %~pni # song01 song02

# %~dpnxi 结合使用,等同于 %~fi
for %i in (*.wav) do echo %~dpnxi
# 与上面的命令效果相同
for %i in (*.wav) do echo %~fi

# 递归地打印目录内扩展名为 txt 的文件名
for /r %i in (*.txt) do echo %i

# 如果写在脚本内,用 %% 代替 % 来指代变量
for %%i in (*) do echo %%i

下面进行模拟实践:

如何将一个目录内的所有 .wav 文件批量转换为比特率为 320kbps 的 .mp3 文件?

1
2
for %i in (*.wav) do ffmpeg -i %i -b:a 320K %~ni.mp3
# song01.wav song02.wav 将转换为 song01.mp3 song02.mp3

如何将一个目录内的所有 .txt 文件批量转换为 .lrc 文件?

1
2
for %i in (*.txt) do ren %~ni.lrc
# file01.txt file02.txt 将转换为 file01.lrc file02.lrc

如何写入脚本,方便以后复用?

1
2
3
for %%i in (*.wav) do (
ffmpeg -i %%i -b:a 320K %%~ni.mp3
)

如何将其他格式的音频文件,比如 flac 转换为 .mp3 文件?

1
2
3
4
5
# %%1 指代运行脚本时输入的第一个参数
# 比如 task.bat flac
for %%i in (*.%%1) do (
ffmpeg -i %%i -b:a 320K %%~ni.mp3
)

如何实现从命令行输入参数,源文件扩展名、转换后文件扩展名、转换后文件比特率,来实现特定格式和比特率的转换?

1
2
3
4
5
# 将 wav 文件转换为 192kbps 比特率的 mp3 文件
# task.bat wav mp3 192K
for %%i in (*.%1) do (
ffmpeg -i %%i -b:a %3 %%~ni.%2
)

如何将目录内的 txt 文件转换为同名的 lrc 文件(文件内容保持不变)?

1
2
3
for %%i in (*.txt) do (
ren %%i %%~ni.lrc
)

参考链接