Improve video audio normalization scripts

This commit is contained in:
Michael Campagnaro 2023-06-22 15:55:57 -04:00
parent 12a11b2435
commit 515a9f479a
6 changed files with 27 additions and 15 deletions

View File

@ -45,6 +45,7 @@ fi
printf "\n${YELLOW}${BOLD}Extracting 16-bit WAV from $input | output: $output_name${NORMAL}\n"
# -ac 1 mixes audio to a single channel.
ffmpeg -i "$input" -ar 16000 -ac 1 -c:a pcm_s16le "$output_name"
printf "${GREEN}${BOLD}Done extracting 16-bit WAV from $input | output: $output_name${NORMAL}\n"

View File

@ -45,7 +45,7 @@ fi
printf "\n${YELLOW}${BOLD}Repairing audio in $filename.$extension | output: $output${NORMAL}\n"
ffmpeg -i "$filename.$extension" -c:v copy -ac 1 "$output"
ffmpeg -i "$filename.$extension" -c:v copy -ac 1 -map 0 "$output"
printf "\n${GREEN}${BOLD}Done repairing audio in $filename.$extension | output: $output${NORMAL}\n\n"

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bash
# Use this to normalize the audio of a video using the average loudness, or RMS-based normalization.
# Use this to normalize the audio of a video using the average loudness, or RMS-based normalization. It does a pretty good job!
# If you want to modify the volume yourself then checkout the analyze-video-volume and change-video-volume scripts.
#
# This does not re-encode the video.
#
# Inspired by https://superuser.com/a/323127 and https://superuser.com/a/1312885
@ -50,21 +52,26 @@ printf "\n${YELLOW}${BOLD}Normalizing audio in $filename.$extension | output: $o
# 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.
# -vn, -sn, and -dn tells ffmpeg to ignore non-audio streams during the analysis. This speeds things up.
ffmpeg -i "$filename.$extension" -af "volumedetect" -vn -sn -dn -f null /dev/null
temp_file="/tmp/_audio_info_$RANDOM"
#ffmpeg -i "$filename.$extension" -c:v copy -ac 1 "$output"
# 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 "\n${GREEN}${BOLD}Done normalizing audio in $filename.$extension | output: $output${NORMAL}\n\n"
printf "\n${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 -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 -map 0 \"$output\""
printf "${BOLD}Re-encoding audio:\n$cmd\n\n${NORMAL}"
eval $cmd
#---------------------------------------
# This seems better. 2 pass using loudnorm filter.
printf "\n${GREEN}${BOLD}Done normalizing volume in $filename.$extension | output: $output${NORMAL}\n"
rm $temp_file
# 1st pass: ffmpeg -i "$filename.$extension" -pass 1 -filter:a loudnorm=print_format=json -vn -sn -dn -f null /dev/null
# 2nd pass: ffmpeg -i "$filename.$extension" -c:v copy -pass 2 -filter:a loudnorm=linear=true:measured_I=$input_i:measured_LRA=$input_lra:measured_tp=$input_tp:measured_thresh=$input_thresh "$output"
# TODO: extract the $input_i, input_lra, etc from the 1st pass output so that this can be automated.
# TODO: stackoverflow said if there are subtitles or multiple vid streams then add "-map 0" before the output name. Test this.
# TODO: disable the log file or just delete it after normalizing.

View File

@ -43,7 +43,7 @@ fi
printf "\n${YELLOW}${BOLD}Removing audio from '$filename.$extension' | output: '$output'${NORMAL}\n"
# -an removes the audio.
ffmpeg -i "$filename.$extension" -c:v copy -an "$output"
ffmpeg -i "$filename.$extension" -c:v copy -an -map 0 "$output"
printf "\n${GREEN}${BOLD}Done removing audio from '$filename.$extension' | output: '$output'${NORMAL}\n\n"

View File

@ -42,6 +42,8 @@ timing_args="-ss $start_time -to $end_time"
printf "\n${YELLOW}${BOLD}Trimming '$filename.$extension' | output: $output | start: $start_time | end: $end_time${NORMAL}\n"
# You might have issues if the file has multiple video streams or embedded subtitles. The -map 0 arg is typically given
# when copying a video stream, but I'm not sure if it's appropriate to use here.
ffmpeg -y -stats -loglevel level+error $timing_args -accurate_seek -i "$filename.$extension" -c:v libx264 -c:a copy "$output"
printf "\n${GREEN}${BOLD}Finished trimming${NORMAL}\n\n"

View File

@ -40,6 +40,8 @@ timing_args="-ss $start_time -to $end_time"
printf "\n${YELLOW}${BOLD}Trimming '$filename.$extension' | output: $output | start: $start_time | end: $end_time${NORMAL}\n"
# You might have issues if the file has multiple video streams or embedded subtitles. The -map 0 arg is typically given
# when copying a video stream, but I'm not sure if it's appropriate to use here.
ffmpeg -y -stats -loglevel level+error $timing_args -i "$filename.$extension" -c copy "$output"
printf "\n${GREEN}${BOLD}Finished trimming${NORMAL}\n\n"