Skip to content

Instantly share code, notes, and snippets.

@AbeEstrada
Forked from kylophone/loudness.rb
Last active October 14, 2024 15:25
Show Gist options
  • Save AbeEstrada/46d6923f40958bf3f1aaca972aa8ec65 to your computer and use it in GitHub Desktop.
Save AbeEstrada/46d6923f40958bf3f1aaca972aa8ec65 to your computer and use it in GitHub Desktop.
FFmpeg loudnorm filter - dual pass loudness normalization example - http://k.ylo.ph/2016/04/04/loudnorm.html
#!/bin/bash
ffmpeg_bin="ffmpeg" # v7.1
target_il=-16.0
target_lra=11.0
target_tp=-1.0
samplerate="44100"
if [ "$#" -ne 2 ]; then
echo "Usage: $0 input.wav output.wav"
exit 1
fi
input_file="$1"
output_file="$2"
# First pass to get loudness stats
ff_string="$ffmpeg_bin -hide_banner -i $input_file -af loudnorm=I=$target_il:LRA=$target_lra:tp=$target_tp:print_format=json -f null -"
stats=$(eval "$ff_string" 2>&1 | sed -n '/^{/,/^}/p')
if [ $? -ne 0 ]; then
echo "$stats"
exit 1
fi
# Extract required values from the JSON output
measured_I=$(echo "$stats" | jq -r '.input_i')
measured_LRA=$(echo "$stats" | jq -r '.input_lra')
measured_tp=$(echo "$stats" | jq -r '.input_tp')
measured_thresh=$(echo "$stats" | jq -r '.input_thresh')
offset=$(echo "$stats" | jq -r '.target_offset')
# Construct the loudnorm string for the second pass
loudnorm_string="loudnorm=print_format=summary:linear=true:I=$target_il:LRA=$target_lra:tp=$target_tp"
loudnorm_string+=":measured_I=$measured_I:measured_LRA=$measured_LRA:measured_tp=$measured_tp"
loudnorm_string+=":measured_thresh=$measured_thresh:offset=$offset"
# Second pass to apply loudness normalization
ff_string="$ffmpeg_bin -y -hide_banner -i $input_file -af $loudnorm_string -ar $samplerate $output_file"
eval "$ff_string" 2>&1 | tail -n 12
if [ $? -ne 0 ]; then
echo "Error occurred during loudness normalization"
exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment