78 lines
2.6 KiB
Bash
78 lines
2.6 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Use this to normalize the volume of a video or audio file using the average loudness, or RMS-based normalization. It does a pretty good job!
|
|
# If you want to modify the volume manually then checkout the analyze-volume and change-volume scripts.
|
|
#
|
|
# This does not re-encode video when given a video file.
|
|
#
|
|
# Inspired by https://superuser.com/a/323127 and https://superuser.com/a/1312885
|
|
|
|
if which tput >/dev/null 2>&1; then
|
|
ncolors=$(tput colors)
|
|
fi
|
|
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
|
|
RED="$(tput setaf 1)"
|
|
GREEN="$(tput setaf 2)"
|
|
YELLOW="$(tput setaf 3)"
|
|
BLUE="$(tput setaf 4)"
|
|
MAGENTA="$(tput setaf 5)"
|
|
CYAN="$(tput setaf 6)"
|
|
BOLD="$(tput bold)"
|
|
NORMAL="$(tput sgr0)"
|
|
else
|
|
RED=""
|
|
GREEN=""
|
|
YELLOW=""
|
|
BLUE=""
|
|
MAGENTA=""
|
|
CYAN=""
|
|
BOLD=""
|
|
NORMAL=""
|
|
fi
|
|
|
|
if [[ $1 == "" ]]; then
|
|
printf "${BOLD}${RED}Usage: normalize-volume <video or audio filename> <optional output name>${NORMAL}\n"
|
|
exit 1
|
|
fi
|
|
|
|
filename=$(basename -- "$1")
|
|
extension="${filename##*.}"
|
|
filename="${filename%.*}"
|
|
|
|
output_name="$2"
|
|
|
|
if [[ $output_name == "" ]]; then
|
|
output="${filename}_normalized_audio.$extension"
|
|
else
|
|
output="${output_name}.$extension"
|
|
fi
|
|
|
|
printf "\n${YELLOW}${BOLD}Normalizing audio in $filename.$extension | output: $output${NORMAL}\n"
|
|
|
|
# This is done in two passes. The first pass will compute the mean loudness and
|
|
# the second pass will normalize the audio using the mean as the target.
|
|
|
|
temp_file="/tmp/_audio_info_$RANDOM"
|
|
|
|
# 1st pass:
|
|
cmd="ffmpeg -i \"$filename.$extension\" -pass 1 -filter:a loudnorm=print_format=json -vn -sn -dn -f null /dev/null 2>&1 | sed -n '/{/,/}/p' > $temp_file"
|
|
printf "\n${BOLD}Running 1st pass:\n$cmd\n\n${NORMAL}"
|
|
eval "$cmd"
|
|
|
|
printf "${BOLD}${GREEN}Done.\n\n${NORMAL}"
|
|
|
|
ii=`grep \"input_i\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
|
|
itp=`grep \"input_tp\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
|
|
ilra=`grep \"input_lra\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
|
|
it=`grep \"input_thresh\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
|
|
to=`grep \"target_offset\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
|
|
|
|
# 2nd pass:
|
|
cmd="ffmpeg -y -stats -loglevel level+error -i \"$filename.$extension\" -c:v copy -pass 2 -filter:a loudnorm=linear=true:I=-16:LRA=11:tp=-1.5:measured_I=$ii:measured_LRA=$ilra:measured_tp=$itp:measured_thresh=$it:offset=$to:print_format=summary \"$output\""
|
|
printf "${BOLD}Re-encoding audio:\n$cmd\n\n${NORMAL}"
|
|
eval "$cmd"
|
|
|
|
printf "\n${GREEN}${BOLD}Done normalizing volume in $filename.$extension | output: $output${NORMAL}\n"
|
|
rm $temp_file
|
|
|