FFmpeg の loudnorm フィルタを使うと、放送業界標準の EBU R128 に合わせて音量(ラウドネス)を自動で整えられます。配信や納品で「音が小さい」「大きすぎる」と言われたときに使えます。基準となる音量は配信サービスごとに決まっています。方法は手軽な1パスと、より正確な2パスの2通りで、統合ラウドネス・トゥルーピーク・ラウドネスレンジの目標値を指定できます。

EBU R128ラウドネス正規化とは

EBU R128は欧州放送連合(EBU)が定めたラウドネスの規格で、次の値を定義しています。

指標 単位 EBU R128ターゲット
統合ラウドネス(I) LUFS −23 LUFS
トゥルーピーク(TP) dBTP 最大 −1 dBTP
ラウドネスレンジ(LRA) LU 目標値・上限なし(音量の変動の大きさを見る値)

LUFS(Loudness Units, referenced to Full Scale)は、人の聴覚に基づいて音の大きさを表す尺度です。最大サンプル値だけを見るピーク正規化と違い、音声が実際にどのくらい大きく_聴こえるか_を基準に正規化します。

配信サービスは、それぞれ独自の目標ラウドネスを使っています。測り方は ITU-R BS.1770 で、EBU R128 や米国の放送規格 ATSC A/85 と同じです。

1パス正規化(クイック)

いちばん簡単なのは、1パスでloudnormを適用する方法です。

ffmpeg -i input.mp3 -af loudnorm output.mp3

デフォルトでは統合ラウドネス −24 LUFS、トゥルーピーク −2 dBTP、ラウドネスレンジ 7 LU を目標にします。1パスモードは処理しながら元の音声のラウドネスを推定し、多くの用途ではこれで十分な精度が出ます。1パスは、3 秒未満の短い音声を除いて dynamic モードで処理されます。また1パスでは内部で 192 kHz に変換されるため、出力のサンプルレートが変わることがあります(-ar 48000 などで指定できます)。

ターゲット値のカスタマイズ

ffmpeg -i input.mp3 -af "loudnorm=I=-16:TP=-1.5:LRA=11" output.mp3
パラメータ 説明 デフォルト
I 統合ラウドネスターゲット(LUFS) −24
TP トゥルーピーク上限(dBTP) −2
LRA ラウドネスレンジターゲット(LU) 7

I=-16は、Apple Podcasts が求める音量(約 −16 LKFS。LKFS は LUFS と同じ尺度です)に合う値です。Spotify は曲を −14 LUFS にそろえて再生します。放送(EBU R128)ではI=-23を使ってください。

2パス正規化(精度重視)

より正確に正規化するには、2パス方式を使います。

パス1:元の音声のラウドネスを計測

ffmpeg -i input.mp3 -af "loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json" -f null /dev/null

ファイルは出力せず(-f null /dev/null)、計測値を含むJSONブロックをstderrに表示します。

{
        "input_i" : "-27.06",
        "input_tp" : "-4.28",
        "input_lra" : "7.20",
        "input_thresh" : "-37.06",
        "output_i" : "-16.00",
        "output_tp" : "-1.50",
        "output_lra" : "7.20",
        "output_thresh" : "-26.00",
        "normalization_type" : "dynamic",
        "target_offset" : "0.00"
}

パス2:計測値を使って適用

パス1のinput_i、input_tp、input_lra、input_threshを、loudnormフィルターのmeasured_I、measured_TP、measured_LRA、measured_threshに指定します。

ffmpeg -i input.mp3 -af "loudnorm=I=-16:TP=-1.5:LRA=11:measured_I=-27.06:measured_TP=-4.28:measured_LRA=7.20:measured_thresh=-37.06:linear=true" output.mp3

linear=trueは、計測値に基づいて一定のゲイン(リニアゲイン)だけをかける指定です(ダイナミックコンプレッションなし)。既定値も true です。ただし、4つの計測値のどれかが欠けている場合、上げた後のピークが TP を超える場合、measured_LRA が LRA より大きい場合は、自動で dynamic モードになります。この例の値では +11.06 dB 上げるとピークが +6.78 dBTP になり TP=-1.5 を超えるので、実際には dynamic で処理されます。

動画ファイルへの適用(映像再エンコードなし)

動画ファイルのラウドネスを、映像を再エンコードせずに正規化するコマンドです。

ffmpeg -i input.mp4 -c:v copy -af "loudnorm=I=-16:TP=-1.5:LRA=11" -ar 48000 output.mp4

-c:v copyで映像はそのままコピーし、音声だけを再エンコードします。-ar 48000 で音声を 48 kHz にします。付けないと、このコマンドでは 96 kHz の音声になります。

出力値の読み方

パス1のJSON出力の主なフィールドは次のとおりです。

フィールド 意味
input_i 計測された統合ラウドネス(LUFS)
input_tp 計測されたトゥルーピーク(dBTP)
input_lra 計測されたラウドネスレンジ(LU)
input_thresh ラウドネスゲーティング閾値
normalization_type linear(リニアゲイン)またはdynamic(ダイナミック処理)

パス1では計測値を渡していないため、normalization_type は通常 dynamic になり(3 秒未満の短い音声では linear)、パス2のモードの目安にはなりません。パス2でどちらになったかは、パス2にも print_format=json を付けると確認できます。

よくある問題

出力が期待より大きく/小さく聴こえる

1パスモードではエンコードしながらラウドネスを推定します。ラウドネスが変動するファイルでは推定が不正確になることがあります。正確さが必要な素材では2パスを使ってください。

パス1の出力に問題がある

パス1(-f null /dev/null)は計測だけを行い、出力ファイルは作りません。精度が必要な場合は、パス1を省略しないでください。

トゥルーピークのクリッピング

元の音声のピークが0 dBFSに非常に近いと、ゲインを上げただけでサンプルが0を超えることがあります。TPパラメータで出力のトゥルーピークを制限すれば防げます。TP=-1以下に設定してください。

関連記事

よくある質問

ラウドネス正規化と通常の音量正規化の違いは?

通常の音量正規化は、ピーク値(一番大きい瞬間)を基準に揃えます。ラウドネス正規化は、人の聴感(LUFS)を基準に「全体として聞こえる音量」を揃えます。配信サービス(YouTube / Spotify)の基準と一致するため、現在はこちらが一般的です。

配信サービスの目標ラウドネスは?

Spotify は -14 LUFS に合わせて音量を調整し、Apple Podcasts は -16 LUFS(±1 dB)を求めています。YouTube と Apple Music の数値は、公式のヘルプには載っていません。

loudnorm は 1-pass と 2-pass どっち?

2-pass をおすすめします。1-pass は近似値で、2-pass は元の音声を解析してから正確に正規化します。-af loudnorm=print_format=json で 1 回目を実行し、出力値を 2 回目の measured_I/TP/LRA/thresh の 4 つに渡します(1 つでも欠けると linear モードになりません)。

正規化後にコンプレッションがかかったような音になる

loudnorm はデフォルトで true peak limiter を含みます。動的レンジを保ちたい場合は、2パスで計測値を 4 つとも渡して linear モードにするか(条件はパス2の説明を参照)、計測した音量と目標の差だけ volume フィルタで全体を上げ下げします(上げすぎるとピークが割れるので、上げ幅はピークの余裕まで)。dynamic というオプションはなく、指定するとエラーになります。

複数ファイルを同じ音量に揃えたい

バッチスクリプトで、各ファイルに同じ目標 LUFS(-14 など)を適用します。例: for f in *.mp4; do ffmpeg -i "$f" -c:v copy -af loudnorm=I=-14:TP=-1:LRA=11 -ar 48000 "out_$f"; done