私は、ムービークリップの最も大きなピークサウンドを、コーデックが許す範囲でできるだけ大きくし、それから他のすべてのサウンドをそれに応じて増幅させることを望みます。
Ffmpegを使用してこれを達成するための実用的な例は何ですか?
現在のffmpegには、正規化に直接使用できる2つのフィルタがあります - これらはすでにかなり高度なものですが、ピークレベルに達するためにゲインを適用するだけではありません。どうぞ:
loudnorm
:EBU R 128によるラウドネス正規化。統合音量ターゲット、音量範囲ターゲット、または最大真ピークを設定できます。これはオーディオやビデオのパブリッシュに推奨されており、世界中の放送局で使用されています。dynaudnorm
:クリッピングなしの「インテリジェント」ラウドネス正規化。ファイルのウィンドウ部分に正規化を動的に適用します。これは音の特性を変えるかもしれないので、それは慎重に適用されるべきです。また、volume
フィルタを使って簡単な音量調整を行うこともできます。詳しくは Audio Volume Manipulation wikiの項目を見てください。
loudnorm
フィルタは1回のパスでも使用できますが、2回のパスを実行することをお勧めします。これにより、より正確な線形正規化が可能になります。これを自動化するのは少し難しいです。また、0 dBFS(または他のターゲット)への「単純な」RMSベースまたはピーク正規化が必要な場合は、次に進んでください。
ffmpeg-normalize
ツールを使用するメディアファイルを正規化するための Pythonプログラムを作成しました 、 PyPiでも利用できます 。あなたは簡単です:
$PATH
に追加するか、 にそのディレクトリを/usr/local/bin
に追加することによって、ffmpeg
実行可能ファイルを$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、およびpeakをサポートします。他のオプションについてはffmpeg-normalize -h
を見て、いくつかの例については README をチェックしてください。
また、他のエンコーダ(AACやMP3など)での再エンコード、またはオーディオとビデオの自動マージもサポートしています。
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
filter をオーディオファイルに適用します。フィルタを適用すると、オーディオストリームを再エンコードする必要があることになります。オーディオにどのコーデックが必要かは、もちろん元のフォーマットによって異なります。ここではいくつかの例を示します。
普通のオーディオファイル:必要なエンコーダでファイルをエンコードするだけです。
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
を使用してください。
それをするためにそれに基づいて私の醜いbashであるように私は最もよいメッセージについてコメントすることができません
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
これは、.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: $1 should be the name of the directory containing input .m4a files.
# $2 should be the output directory.
INPUTDIR=$1
OUTPUTDIR=$2
<<"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 $2}' | 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 $5}' | 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
# $1 (first param) should be the name of a .m4a input file, with .m4a extension
# $2 should be name of output file, with extension
function normalizeAudioFile {
INPUTFILE=$1
OUTPUTFILE=$2
DBLEVEL=`ffmpeg -i ${INPUTFILE} -af "volumedetect" -f null /dev/null 2>&1 | grep max_volume | awk -F': ' '{print $2}' | 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 $5}' | 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