如何规范化mp3文件中的声音
我正在寻找一种方法来规范我的MP3文件中的声音。 有些声音很低,而有些声音较大,所以我必须根据歌曲调高或调低音量。 有什么方法可以为所有文件执行此操作。 我特别想通过终端来做,但也接受GUI方式。
大胆
使用Audacity,我们可以轻松地批处理文件,以将转换或效果应用于列表中的许多文件。 为此,我们首先要定义一个包含我们想要应用的效果的“链” 。
这是通过“文件 – >编辑链……”完成的 。 在现在打开的窗口中,按左下角的“ 添加”按钮插入一个新链(给它一个合理的名称):
然后选择效果及其参数以插入链(此处显示默认值和标准化效果)。
重要提示:我们总是需要添加效果“导出MP3” (或任何其他导出格式),以便将生成的转换保存到磁盘。
完成后, 单击确定退出此窗口以打开“文件 – >应用链…” 。 选择我们刚刚创建的Chain,并使用“Apply to files …”加载所需的所有文件。 可以从打开的文件选择器中选择多个文件。
已处理的文件将保存在原始路径中“已清理”的新子目录中。
短袜
从版本> 14.3开始,我们可以使用soxfilter--norm
来在命令行上规范化音频或进行批处理:
sox --norm infile outfile
使用libsox-fmt-all将So- MP3添加到MP3中 。
看看@ mp3gain对我来说甚至比normalize-audio更好
mp3gain -r *.mp3
另一个有用的版本可能是-c,它阻止询问你是否要对许多文件进行更改:
mp3gain -c -r *.mp3
如手册页中所述:
mp3gain不只是像许多规范化器那样进行峰值归一化。 相反,它会进行一些统计分析,以确定文件实际对人耳发出的声音大小。 此外,mp3gain的变化是完全无损的。 更改中没有质量丢失,因为程序直接调整mp3文件,无需解码和重新编码。
注意 :该软件包是在ubuntu 15.04上故意删除的 。
Debian建议将python-rgain
包作为替换(优点是’replaygain’支持多种文件格式,即Ogg Vorbis,Flac,WavPack和MP3。此外,它允许您查看任何这些文件类型中的现有重播增益信息) 。 安装后,运行replaygain
。
要从终端安装python-rgain,请运行该命令
sudo apt-get install python-rgain
或者,从此处获取14.04(最新)的.deb
文件。 像往常一样安装。 之后,您需要运行sudo apt-get -f install
来纠正一些依赖项问题。
我会使用这个项目Normalize ,它是一个用于规范化音频文件的命令行工具。 看起来正是您所需要的。 可以进行批处理,也不需要重新采样到中间格式。
它在包repos中作为normalize-audio, sudo apt-get install normalize-audio
。 这是Debian上游维护的构建,因此它应该是LTS或更新版本,并且具有mp3兼容性(经过测试)。 有一个好的manpage man normalize-audio
来探索选项但是命令默认看起来效果很好。 对于批处理(规范化多个文件的卷), normalize-audio -b *.mp3
或指定单个文件名而不是使用通配符。
为了它,我将投入2美分。我一直在寻找完全相同的东西(仅适用于ogg文件)并在Crunchbang论坛上开始了一个主题。 你可以在这里查看: Normalize-audio找不到mp3解码器
基本上我的解决方案是#8后的脚本。 它适用于mp3,flac和ogg输入文件,可能是其他文件,但绝对不是wav。
只需创建一个文件(将其命名为我想要的名称,我称之为db_adjust_mp3),chmod + x,并将其粘贴到〜/ bin文件夹中。 它还填写任何丢失的编解码器数据。 例:
原始文件: 16._This_Protector.mp3: Audio file with ID3 version 2.3.0, contains:
与
规范化文件: 16._This_Protector.mp3: Audio file with ID3 version 2.3.0, contains: MPEG ADTS, layer III, v1, 192 kbps, 44.1 kHz, JntStereo
我已修改脚本以在此使用normalize-mp3,因此您可以根据需要使用它:
#!/bin/bash find "$1" -iname "*.""$2" > $HOME/file_list cat $HOME/file_list | while read line; do # echo "$line" orig_gain="$(normalize-mp3 -n "$line" | cut -d 'd' -f1)" larger=$(echo "$orig_gain"'>'-12 | bc) if [[ larger ]] then gain_difference=$(echo "$orig_gain"*-1-12 | bc) else gain_difference=$(echo "$orig_gain"-12 | bc) fi echo "Gain Difference will be: $gain_difference""db" normalize-ogg --mp3 --bitrate "$3" -g "$gain_difference""db" -v "$line" done
此脚本计算当前数据库级别和-12db之间的差异,然后应用增益调整将增益精确地放在-12db,这是我发现最适合我的。 它也是递归的,这使得它非常适合在许多子文件夹中完成整个音乐集合或文件。 如果您希望设置不同的数据库级别,只需将数字“12”的两个实例更改为您要使用的任何数据库级别。 当我在我的Crunchbang线程中发布时,用法如下:
normalize-mp3
然而,当我以前用mp3格式保存我的音乐库时,我也习惯使用mp3gain,就像Philippe建议的那样。 它的死亡简单很棒,我真的很喜欢它。 normalize-audio的问题在于它确实解码了文件的重新编码,因此存在一些声音降级。 但除非你是一个发烧友并且你的mp3以高比特率编码,否则你不应该注意到很多不同。
我用mp3gain注意到的事情是,无论我尝试什么选项,我都无法让我的collections中的所有内容都完全相同的数据库级别,这就是我想要的,所以我从来没有必要调整音量从一个轨道到下一个。 这个脚本就是这样做的。 很抱歉这么久了。 希望这可以帮助。
播放增益
在Ubuntu 16.04上,我遇到了其他CLI替代方案的问题。 然后我找到了replaygain
:
该软件包提供了一个Python包来计算音频文件的Replay Gain值,并根据值标准化这些文件的音量。 还提供了两个利用这些function的基本脚本。
重播增益是一种建议的标准,旨在解决音频文件中音量变化的问题。
安装: sudo apt install python-rgain
。
replaygain --force *.mp3
-
-f, --force
重新计算重播增益即使文件已包含增益信息。
由于只计算/改变replaygain值,也更快:平均PC(Intel i7-6500U,8GB RAM):~20个文件/分钟。
参考
- 维基百科上的ReplayGain文章
- 在Launchpad上的python-rgain
我最喜欢Neil的答案,因为它没有引入音频文件之间的相关性:只需选择一个增益级别并调整所有内容即可。
但是我在使用一些文件解析normalize-ogg
的输出时遇到了一些问题。 bc
还有一个令人讨厌的问题:它没有做真正的舍入,它只是截断。
所以最终我放弃了shell脚本并转移到了python。
注1: exiftool部分可能有点矫枉过正,但我想100%确定保留原始比特率。
注意2:这将覆盖原件,如果要保留它们,请在最后一次调用normalize-ogg时使用–backup。 但我发现将副本保存在一个单独的,更安全的目录中更加实用。
注3:这个解决方案处理ogg文件,但是将它改编为mp3很简单,只需用“mp3”替换“ogg”的出现即可。
这是我对这个问题的看法。 最新版本可以在这里找到: regain.py
#!/usr/bin/python3 """ Parallel normalize gains """ ' This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ' # Absolute value, in dB for the desired gain of each file TARGET_GAIN = -12 # MAX_THREADS = 2 from subprocess import Popen, PIPE from multiprocessing.dummy import Pool as ThreadPool from os import listdir import logging def initlogger(logfile="log.log", mainlevel=logging.DEBUG, filelevel=logging.DEBUG, consolelevel=logging.DEBUG): '''initlogger''' # create logger logger = logging.getLogger() logger.setLevel(mainlevel) # create file handler which logs even debug messages fh = logging.FileHandler(logfile) fh.setLevel(filelevel) # create console handler also logging at DEBUG level ch = logging.StreamHandler() ch.setLevel(consolelevel) # create formatter and add it to the handlers formatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s") fh.setFormatter(formatter) ch.setFormatter(formatter) # add the handlers to the logger logger.addHandler(fh) logger.addHandler(ch) def logcommand(command=[]): '''logcommand''' if not isinstance(command, list): return "", "", -1 logging.info("Command:\n" + " ".join(command) + "\n") proc = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE) output, err = proc.communicate() output = output.decode("utf-8") err = err.decode("utf-8") logging.info("Output:\n" + output + "\n") logging.info("Error:\n" + err + "\n") logging.info("Return Code:\n" + str(proc.returncode) + "\n") return output, err, proc.returncode def regain(target): '''regain''' logging.info("============================ Start File ============================") logging.warning(target["name"]) logging.info("Extracting gain info.\n") commandgetlevels = ['normalize-ogg', '-n', target["name"]] output, err, retcode = logcommand(commandgetlevels) level = output.split()[0] logging.debug("Level: " + level) if "dBFS" in level: level = level.split("dBFS")[0] level = level.replace(',', '.') level = int(round(float(level))) delta = target["gain"] - level logging.info("Required adjustment: " + str(delta) + "\n") if delta is 0: logging.warning(target["name"] + " is already at the correct level") return 0 logging.info("Extracting average bitrate.\n") commandgetinfo = ['exiftool', target["name"]] output, err, retcode = logcommand(commandgetinfo) bitrate = '0' for line in output.split('\n'): if 'Nominal Bitrate' in line: bitrate = line.split(':')[1].split()[0] break logging.info("Average bitrate is: " + str(bitrate) + "\n") if bitrate is '0': logging.error("No valid bitrate found, aborting conversion.\n") exit(-1) logging.info("Re-normalizing.\n") commandrenormalize = ['normalize-ogg', '--ogg', '--bitrate', bitrate, '-g', str(delta) + 'db', target["name"]] output, err, retcode = logcommand(commandrenormalize) if retcode is not 0: log.error("Output:\n" + output) log.error("err:\n" + err) exit(retcode) return retcode # function to be mapped over def parallelregain(gain=TARGET_GAIN, threads=MAX_THREADS): '''parallelregain''' logging.info("Creating thread pool with " + str(threads) + " elements.\n") pool = ThreadPool(threads) targets = [] files_list = listdir(".") files_list.sort() counter = 0 for filename in files_list: if filename.endswith("ogg"): target = { "name":filename, "gain":gain, } targets.append(target) counter = counter + 1 pool.map(regain, targets) pool.close() pool.join() if __name__ == "__main__": initlogger(logfile="normalize.log", consolelevel=logging.WARNING) parallelregain()