如何规范化mp3文件中的声音

我正在寻找一种方法来规范我的MP3文件中的声音。 有些声音很低,而有些声音较大,所以我必须根据歌曲调高或调低音量。 有什么方法可以为所有文件执行此操作。 我特别想通过终端来做,但也接受GUI方式。

大胆 安装大胆

使用Audacity,我们可以轻松地批处理文件,以将转换或效果应用于列表中的许多文件。 为此,我们首先要定义一个包含我们想要应用的效果的“链”

这是通过“文件 – >编辑链……”完成的 。 在现在打开的窗口中,按左下角的“ 添加”按钮插入一个新链(给它一个合理的名称):

在此处输入图像描述

然后选择效果及其参数以插入链(此处显示默认值和标准化效果)。

重要提示:我们总是需要添加效果“导出MP3” (或任何其他导出格式),以便将生成的转换保存到磁盘。

完成后, 单击确定退出此窗口以打开“文件 – >应用链…” 。 选择我们刚刚创建的Chain,并使用“Apply to files …”加载所需的所有文件。 可以从打开的文件选择器中选择多个文件。

在此处输入图像描述

已处理的文件将保存在原始路径中“已清理”的新子目录中。


短袜 安装sox

从版本> 14.3开始,我们可以使用soxfilter--norm来在命令行上规范化音频或进行批处理:

 sox --norm infile outfile 

使用libsox-fmt-all将So- MP3添加到MP3中 安装libsox-fmt-all

看看@ 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()