slhck / ffmpeg-normalize

Audio Normalization for Python/ffmpeg
MIT License
1.25k stars 117 forks source link

Question - How to hit these targets #141

Closed thenewguy closed 3 years ago

thenewguy commented 3 years ago

I have been getting the feel for how to use this. Thank you for the awesome script. This is more of a question than an issue.

I started down this path after observing this from HLS validation: "Audio loudness information SHOULD be provided"

I've then dug up Apple's recommendation for the loudness.

we strongly recommend that the audio signals are pre-conditioned in such a way that the overall loudness remains around -16 dB LKFS, with a +/- 1 dB tolerance and that the true-peak value doesn’t exceed -1 dB FS.

I've worked up the command:

ffmpeg-normalize 'file.mp4' --output 'file.mp4' --force --audio-codec flac --extra-output-options '-strict -2' --target-level -16 --true-peak -1 --dual-mono

I used ffmpeg's volumedetect to compare the input with the output.

Input

n_samples: 653440
mean_volume: -23.2 dB
max_volume: -6.6 dB

Output

n_samples: 2617776
mean_volume: -19.7 dB
max_volume: -3.0 dB

Am I doing something wrong? I was expecting a mean volume of -16 dB and the max volume of -1

slhck commented 3 years ago

When you use the volumedetect filter, the output dB are given in dB RMS. This is not the same as dB LKFS (or dB LUFS; it's the same thing).

When you run a normalization with EBU R128, it'll normalize according to Loudness Units, so the output of volumedetect (RMS) is irrelevant.

Check the statistics with ffmpeg-normalize instead:

➜ ffmpeg-normalize ~/Downloads/Wild_Things.mp3 -p -n
[
    {
        "input_file": "/Users/werner/Downloads/Wild_Things.mp3",
        "output_file": "normalized/Wild_Things.mkv",
        "stream_id": 0,
        "ebu": {
            "input_i": "-6.74",
            "input_tp": "0.45",
            "input_lra": "6.30",
            "input_thresh": "-16.98",
            "output_i": "-22.20",
            "output_tp": "-11.27",
            "output_lra": "5.60",
            "output_thresh": "-32.34",
            "normalization_type": "dynamic",
            "target_offset": "-0.80"
        },
        "mean": null,
        "max": null
    }
]

If you then normalize it with a LUFS target of -16, you'll get the correct result:

➜ python3 -m ffmpeg_normalize ~/Downloads/Wild_Things.mp3 --target-level -16
…
➜ python3 -m ffmpeg_normalize ./normalized/Wild_Things.mkv -p -n -f
[
    {
        "input_file": "./normalized/Wild_Things.mkv",
        "output_file": "normalized/Wild_Things.mkv",
        "stream_id": 1,
        "ebu": {
            "input_i": "-16.01",
            "input_tp": "-8.81",
            "input_lra": "6.20",
            "input_thresh": "-26.24",
            "output_i": "-22.20",
            "output_tp": "-11.27",
            "output_lra": "5.60",
            "output_thresh": "-32.34",
            "normalization_type": "dynamic",
            "target_offset": "-0.80"
        },
        "mean": null,
        "max": null
    }
]

It is my understanding that the true peak setting only specifies a maximum that is permitted. If you have a file with low dynamic range, you may very well get a lower true peak than what you specified. In other words, the filter won't change the dynamics just to make your peak sit at -1 dBTP.

thenewguy commented 3 years ago

It is important to be able to verify normalization works so I added this to the examples in PR #142