我希望影片剪辑中最大的峰值声音能够达到编解码器允许的最大声音,然后将其他所有声音都相应地放大。

使用ffmpeg来实现此目的的实际示例是什么?

评论

您正在寻求使音频“标准化”。我找到了这个线程,那里有很多很好的信息。希望对您有所帮助!

#1 楼

选项1:内置归一化滤波器

当前ffmpeg具有两个可以直接用于归一化的滤波器-尽管它们已经相当先进,所以它们不简单地应用增益来达到峰值。它们是:



loudnorm:响度根据EBU R128进行归一化。您可以设置一个集成的响度目标,响度范围目标或最大真实峰值。建议在发布音频和视频时使用它,全世界的广播公司都使用它。

dynaudnorm:“智能”响度归一化而无需剪切,可对文件的窗口部分动态应用归一化。这可能会改变声音的特性,因此应谨慎使用。

volume滤波器也可用于执行简单的音量调节。有关更多信息,请参见音频音量操作Wiki条目。

loudnorm滤波器可以使用一次,但建议执行两次通过,这样可以实现更精确的线性归一化。这有点难以自动化。另外,如果您希望基于RMS的“简单”或峰值归一化为0 dBFS(或任何其他目标),请继续阅读。


方法2:使用ffmpeg-normalize工具

我创建了一个Python程序来规范媒体文件,该程序也可以在PyPi上使用。您只需:



下载ffmpeg(选择静态版本3.1或更高版本)
通过将其添加到ffmpeg中,将$PATH可执行文件放入其中例如/usr/local/bin,或将其目录添加到$PATH

运行pip install ffmpeg-normalize

使用ffmpeg-normalize


例如:

ffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k


或者,简单地批量标准化多个音频文件并将其作为未压缩的WAV写入输出文件夹:

ffmpeg-normalize *.m4a -of /path/to/outputFolder -ext wav


该工具支持EBU R128(默认),RMS和峰值。请查看ffmpeg-normalize -h了解更多选项,并查看自述文件中的一些示例。

此外,它还支持使用其他编码器(例如AAC或MP3)进行重新编码,或将音频自动合并回视频中。


选项3:使用ffmpeg手动归一化音频


在ffmpeg中,您可以使用volume过滤器更改曲目的音量。请确保下载该程序的最新版本。

本指南用于峰值归一化,这意味着它将使文件中最响的部分位于0 dB而不是更低的位置。还有基于RMS的归一化,它试图使多个文件的平均响度相同。为此,请勿尝试将最大音量推至0 dB,而要将平均音量推至所选的dB级别(例如-26 dB)。

找出要应用的增益

首先,您需要分析音频流的最大音量以查看归一化是否还可以得到回报:

ffmpeg -i video.avi -af "volumedetect" -vn -sn -dn -f null /dev/null


在Windows上将/dev/null替换为NUL
-vn-sn-dn参数指示ffmpeg在此分析期间忽略非音频流。这将大大加快分析速度。

这将输出以下内容:

[Parsed_volumedetect_0 @ 0x7f8ba1c121a0] mean_volume: -16.0 dB
[Parsed_volumedetect_0 @ 0x7f8ba1c121a0] max_volume: -5.0 dB
[Parsed_volumedetect_0 @ 0x7f8ba1c121a0] histogram_0db: 87861


如您所见,我们的最大体积为- 5.0 dB,因此我们可以应用5 dB的增益。如果您获得0 dB的值,则无需标准化音频。

应用音量过滤器:

现在我们将volume过滤器应用于音频文件。请注意,应用过滤器意味着我们将不得不对音频流进行重新编码。当然,您要哪种音频编解码器取决于原始格式。以下是一些示例:



纯音频文件:只需使用所需的编码器对文件进行编码:

ffmpeg -i input.wav -af "volume=5dB" output.mp3


当然,您的选择范围也很广泛。


AVI格式:通常在AVI容器中带有视频的MP3音频:

ffmpeg -i video.avi -af "volume=5dB" -c:v copy -c:a libmp3lame -q:a 2 output.avi


在这里,我们选择质量等级2。值的范围是0–9,而值越低表示越好。有关设置质量的更多信息,请参阅MP3 VBR指南。例如,您还可以使用-b:a 192k设置固定的比特率。


MP4格式:对于MP4容器,通常可以找到AAC音频。我们可以使用ffmpeg的内置AAC编码器。

ffmpeg -i video.mp4 -af "volume=5dB" -c:v copy -c:a aac -b:a 192k output.mp4


这里您还可以使用其他AAC编码器。其中一些也支持VBR。请参阅此答案和AAC编码指南以获取一些提示。


在以上示例中,将使用-c:v copy复制视频流。如果输入文件中有字幕或多个视频流,请在输出文件名之前使用选项-map 0

评论


评论不作进一步讨论;此对话已移至聊天。

–游侠怪胎♦
17年4月14日在3:18

这是不断给予的礼物。 6年后,它仍在更新和维护。做得好!

–乔恩·斯卡佩特格(Jon Skarpeteig)
17年8月7日在21:04

如果我将新音量设置为max_volume为零,选项3是否可以避免剪切?即使用max_volume给定的相反值初始值

– rraallvv
17-10-26在0:38

@rraallvv是的,应该。当您指定0 dB的电平和峰值归一化时,ffmpeg归一化工具也是如此。

–slhck
17-10-27在7:43

要使用Loudnorm(或其他)过滤器:ffmpeg -i input.wav -filter:Loudnorm output.wav

–约书亚
19-10-21在11:20

#2 楼

我无法对最好的消息发表评论,因此这是我基于它执行的丑陋操作

ffmpeg -i sound.mp3 -af volumedetect -f null -y nul &> original.txt
grep "max_volume" original.txt > original1.tmp
sed -i 's|: -|=|' original1.tmp
if [ $? = 0 ]
 then
 sed -i 's| |\r\n|' original.tmp
 sed -i 's| |\r\n|' original.tmp
 sed -i 's| |\r\n|' original.tmp
 sed -i 's| |\r\n|' original.tmp
 grep "max_volume" original1.tmp > original2.tmp
 sed -i 's|max_volume=||' original2.tmp
 yourscriptvar=$(cat "./original2.tmp")dB
 rm result.mp3
 ffmpeg -i sound.mp3 -af "volume=$yourscriptvar" result.mp3
 ffmpeg -i result.mp3 -af volumedetect -f null -y nul &> result.txt
fi


#3 楼

这是一个使.m4a文件的声音电平标准化的脚本。请注意声级是否太低而无法开始。如果在这种情况下使用Audacity之类的声音,最终的声音会更好。

#!/bin/bash

# Purpose: Use ffmpeg to normalize .m4a audio files to bring them up to max volume, if they at first have negative db volume. Doesn't process them if not. Keeps bitrate same as source files.
# Parameters:  should be the name of the directory containing input .m4a files.
#    should be the output directory.

INPUTDIR=
OUTPUTDIR=

<<"COMMENT"

# For ffmpeg arguments http://superuser.com/questions/323119/how-can-i-normalize-audio-using-ffmpeg
# and
# https://kdecherf.com/blog/2012/01/14/ffmpeg-converting-m4a-files-to-mp3-with-the-same-bitrate/
ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null

ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null 2>&1 | grep max_volume
# output: max_volume: -10.3 dB

ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null 2>&1 | grep 'max_volume\|Duration'
# Output:
#  Duration: 00:00:02.14, start: 0.000000, bitrate: 176 kb/s
# [Parsed_volumedetect_0 @ 0x7f8531e011a0] max_volume: -10.3 dB

ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null 2>&1 | grep max_volume | awk -F': ' '{print }' | cut -d' ' -f1
# Output: -10.3

ffmpeg -i test.m4a 2>&1 | grep Audio
# output: Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 170 kb/s (default)

ffmpeg -i test.m4a 2>&1 | grep Audio | awk -F', ' '{print }' | cut -d' ' -f1
# output: 170

# This works, but I get a much smaller output file. The sound levels do appear normalized.
ffmpeg -i test.m4a -af "volume=10.3dB" -c:v copy -c:a aac -strict experimental output.m4a

# Operates quietly.
ffmpeg -i test.m4a -af "volume=10.3dB" -c:v copy -c:a aac -strict experimental -b:a 192k output.m4a -loglevel quiet

COMMENT

#  (first param) should be the name of a .m4a input file, with .m4a extension
#  should be name of output file, with extension
function normalizeAudioFile {
    INPUTFILE=
    OUTPUTFILE=

    DBLEVEL=`ffmpeg -i ${INPUTFILE} -af "volumedetect" -f null /dev/null 2>&1 | grep max_volume | awk -F': ' '{print }' | cut -d' ' -f1`

    # We're only going to increase db level if max volume has negative db level.
    # Bash doesn't do floating comparison directly
    COMPRESULT=`echo ${DBLEVEL}'<'0 | bc -l`
    if [ ${COMPRESULT} -eq 1 ]; then
        DBLEVEL=`echo "-(${DBLEVEL})" | bc -l`
        BITRATE=`ffmpeg -i ${INPUTFILE} 2>&1 | grep Audio | awk -F', ' '{print }' | cut -d' ' -f1`

        # echo $DBLEVEL
        # echo $BITRATE

        ffmpeg -i ${INPUTFILE} -af "volume=${DBLEVEL}dB" -c:v copy -c:a aac -strict experimental -b:a ${BITRATE}k ${OUTPUTFILE} -loglevel quiet

    else
        echo "Already at max db level:" $DBLEVEL "just copying exact file"
        cp ${INPUTFILE} ${OUTPUTFILE}
    fi
}

for inputFilePath in ${INPUTDIR}/*; do
    inputFile=$(basename $inputFilePath)
    echo "Processing input file: " $inputFile
    outputFilePath=${OUTPUTDIR}/$inputFile
    normalizeAudioFile ${inputFilePath} ${outputFilePath}
done


#4 楼

我使用命令行(根据您的要求进行调整)

mkdir NORMALIZED; for mkv in *.mkv ; do wav=`basename "$mkv" .mkv`.wav; echo "${wav}"; ffmpeg -i "${mkv}" -acodec copy "${wav}" ; normalize-audio "${wav}"; ffmpeg -i "${mkv}"  -i "${wav}" -codec copy NORMALIZED/"${mkv}"; done;


或批处理

[ ! -d work ] && echo "work directory does not ezists" && exit 1

for fn in *.mkv
do
  map=$(ffmpeg -i "$fn" |& grep Stream | grep pcm_s16le) # pcm_dvd ac3 mp3

  if [ "$map" != "" ]
  then
    echo "$fn"
    fb=${fn%.mkv} #; shopt -s extglob; fb=${fb%%+([[:space:]])}
    amap=${map:12:3}
    ffmpeg -y -i "$fn" -map $amap -acodec pcm_s16le work/"$fb".wav 2>/dev/null
    wavegain -y work/"$fb".wav
    ffmpeg -y -i "$fn" -i work/"$fb".wav -c:v copy -c:a copy -map 0:v:0 -map 1:a:0 work/"$fb".mkv 2>/dev/null
    rm -f work/"$fb".wav
    echo
  fi
done

read -p "BAIGTA"


#5 楼

ffmpeg -i image.jpg -i“ input.mp3” -acodec复制tmp.avi

mencoder -ovc复制-oac复制tmp.avi -of rawaudio -af volnorm = 1 -oac mp3lame -lameopts cbr:preset = 192 -srate 48000 -o“ output.mp3”

rm -f tmp.avi

评论


将此与此处的其他答案进行比较,我希望很明显,您的帖子缺少可以使之有用的上下文和解释性信息。什么是“编码器”?它在回答问题时起什么作用?

–music2myear
19年3月21日在20:50

您能否编辑您的答案以解释为什么此代码可以回答问题?不鼓励仅使用代码的答案,因为它们没有教导解决方案。

–DavidPostill♦
19年3月21日在21:04