我正在寻找一种标准化我拥有的许多MP3文件中声音的方法。有些声音较低,而另一些声音较大,所以我必须根据歌曲的大小调高或调低音量。有什么方法可以对所有文件执行此操作。我特别想通过终端执行此操作,但也接受GUI方式。
我正在寻找一种标准化我拥有的许多MP3文件中声音的方法。有些声音较低,而另一些声音较大,所以我必须根据歌曲的大小调高或调低音量。有什么方法可以对所有文件执行此操作。我特别想通过终端执行此操作,但也接受GUI方式。
Answers:
借助Audacity,我们可以轻松地批量处理文件,以将转换或效果应用于列表中的许多文件。为此,我们首先必须定义一个“链”,其中包含我们要应用的效果。
这可以通过“ File-> Edit Chains ...”完成。在现在打开的窗口中,按左下角的“ 添加”按钮以插入新链(给它取一个明智的名称):
然后选择效果及其参数以插入到链中(此处显示默认值和Normalize效果)。
重要说明:我们始终还需要添加效果“导出MP3”(或任何其他导出格式),以将转换结果保存到磁盘。
完成后,单击确定离开此窗口以打开“文件->应用链...”。选择我们刚刚创建的链,并通过“应用于文件...”加载所需的所有文件。可以从打开的文件选择器中选择几个文件。
处理后的文件将保存在原始路径中“清除”的新子目录中。
从版本> 14.3开始,我们可以使用sox过滤器--norm
在命令行上标准化音频或进行批处理:
sox --norm infile outfile
MP3支持通过libsox-fmt-all添加到Sox:
sudo apt install sox libsox-fmt-all
for f in *.mp3; do sox --norm "$f" /tmp/sox.mp3; mv -v /tmp/sox.mp3 "$f"; done
看看@ 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。此外,它还允许您查看任何这些文件类型中的现有Replay Gain信息)。安装后,运行replaygain
。
要从终端安装python-rgain,请运行以下命令
sudo apt-get install python-rgain
或者,.deb
从此处获取14.04(最新)文件。照常安装。之后,您需要运行sudo apt-get -f install
以更正一些依赖项问题。
mkdir mp3gain; cd mp3gain; wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/mp3gain/1.5.2-r2-6/mp3gain_1.5.2-r2.orig.tar.gz; tar -xvzf mp3gain_1.5.2-r2.orig.tar.gz; make; sudo make install
我将使用此项目Normalize,这是用于规范音频文件的命令行工具。看起来正是您所需要的。可以进行批处理,不需要重新采样为中间格式。
这是在包回购的规范化音频,sudo apt-get install normalize-audio
。这是Debian在上游维护的构建,因此它应为LTS或更高版本,并具有mp3兼容性(经过测试)。有一个不错的联机帮助页man normalize-audio
,供您探索这些选项,但命令默认值似乎可以正常工作。对于批处理(跨多个文件规范化卷),normalize-audio -b *.mp3
或指定单个文件名而不使用通配符。
libsox-fmt-mp3
,libavcodec-extra
。-b *.mp3
仅使用一个(随机?)文件执行某些操作。
更快,更容易replaygain
:
该软件包提供了一个Python软件包来计算音频文件的Replay Gain值,并根据这些值标准化这些文件的音量。同时提供了两个利用这些功能的基本脚本。
重播增益是一项提议的标准,旨在解决整个音频文件中音量变化的问题。
安装:sudo apt install python-rgain
。
replaygain --force *.mp3
-f, --force
即使文件已经包含增益信息,也要重新计算Replay Gain。由于仅计算/更改重放增益值,因此速度也更快:对于普通PC(Intel i7-6500U,8GB RAM),速率约为20个文件/分钟。
为此,我将投入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 <directory> <file extenstion(with no leading dot)> <bitrate>
但是,当我以前将音乐库保持为mp3格式时,就像Philippe所建议的那样,我也曾经使用mp3gain。它的简单性很棒,我真的很喜欢它。但是normalize-audio的问题在于它确实解码了文件的重新结束编码,因此声音会有所下降。但是,除非您是发烧友并且您的mp3是以高比特率编码的,否则您不会注意到太大的区别。
我通过mp3gain注意到的事情是,无论我尝试了什么选项,我都无法将收藏集中的所有内容都设为完全相同的db级别,这就是我想要的,这样我就不必将音量从一个音轨调整为下一个。该脚本正是这样做的。很抱歉这么长时间。希望这可以帮助。
我最喜欢Neil的答案,因为它不会在音频文件之间引入相关性:只需选择一个增益水平并将其调整为所有增益水平即可。
但是我在解析normalize-ogg
某些文件的输出时遇到了一些问题。还有一个令人讨厌的问题bc
:它不进行真正的舍入,它只会截断。
所以最终我放弃了shell脚本,转而使用python。
注意1: exiftool部分可能过大,但我想100%确保保留原始比特率。
注意2:这将覆盖原始文件,如果要保留原始文件,请在最后一次调用normalize-ogg时使用--backup。但是我发现将副本保存在单独的,更安全的目录中更为实用。
注意3:此解决方案处理ogg文件,但是将其适应mp3并不容易,只需将出现的“ ogg”替换为“ mp3”即可。
这是我对这个问题的看法。最新版本可以在这里找到: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 <http://www.gnu.org/licenses/>.
'
# 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()