Normalize audio in movies, using FFmpeg and Sox, in Windows

Evereybody has once in a while tried to view a movie, in which the sound is really low!

After some hours of tryouts, using ffmpeg ( http://ffmpeg.org/download.html ) and SoX ( http://sox.sourceforge.net/ -> Sourceforge's File Release System) I created the following batch script for Windows. In order to work, we must have put the ffmpeg.exe file and the sox.exe along with the batch file. Then we just drag'n'drop a movie file on to the batch file, which contaings the following:

echo off

echo Script by http://1024.gr

cd /d %~dp0
 
echo Extracting audio..
ffmpeg.exe -i %1 -ac 2 -y %1_clean.wav
 
echo Extracting video..
ffmpeg.exe -i %1 -map 0:0 -vcodec copy -y %1_clean.avi
 
echo Getting max amplitude..
sox %1_clean.wav -n stat -v 2> %1_apl.txt
Set /P apl_value= < %1_apl.txt
 
echo Normalizing audio.. gain: %apl_value%
sox --show-progress -v %apl_value% %1_clean.wav %1_norm.wav
 
echo Creating new video file..
ffmpeg.exe -i %1_clean.avi -i %1_norm.wav -vcodec copy %1
 
echo Cleaning..
del %1_clean.wav
del %1_clean.avi
del %1_norm.wav
del %1_apl.txt

pause

 

And let's explain:

echo off: From now on, we disable echoing!

cd /d %~dp0: We change current directory to the one containing the batch file, whatever the direcotry of the movie is. This is needed to find the ffmpeg and sox executables. The movie file name  comes with full path!

EDIT: The previous command can be replaced by "pushd %~dp0" and a "popd" has to be added before last command (pause). With this change, we will be able to execute multiple files from a different batch file.

ffmpeg.exe -i %1 -ac 2 -y %1_clean.wav: We extract the audio from the movie (the first one if there are multiple audio streams), and convert it to uncompressed, 2 channel audio stream. This is needed to for SoX to work without eny problems. It is propable that also other encoding may work, however more than 2 channel will fail.

ffmpeg.exe -i %1 -map 0:0 -vcodec copy -y %1_clean.avi: We extract the video part, needed to easilly merge it again with the normalised audio, onto the same movie file. We assume that video stream, is the first stream of the file (0:0) which is the case for almost all videos.

sox %1_clean.wav -n stat -v 2> %1_apl.txt: We execute the SoX onto the clean audio, so as to get the maximum amplitude gain it can get. This is saveed in file ..apl.txt

Set /P apl_value= < %1_apl.txt: We save the previous number to a variable. It is needed for the following steps.

echo Normalizing audio.. gain: %apl_value%: We echo the new gain, because the user may don't want to continue with the normalization. For example, if this number is 1.05, which means that we can gain only 5% of the audio, it is really low and there won't be any difference. If, however, for example we get a number of 1.9 we should definitely continue as the audio will almost double in amplitude!

sox --show-progress -v %apl_value% %1_clean.wav %1_norm.wav: We create the normalised audio

ffmpeg.exe -i %1_clean.avi -i %1_norm.wav -vcodec copy %1: We continue to try to merge the video stream with the normalised audio stream, while encoding it with libmp3 (it is selected automatically because of the video stream). Because we haven't used the -y flag, while trying to write on the original movie file, ffmpeg prompts to continue/overwrite. At this point we can see from the gain, previously mentioned, if we want to continue, by pressing Y, or not, by pressing n.

Then, we delete all temporary files, whatever the desicion is (Y or n).

All temporary files are created with the movie prefix. This gives us the advantage to use the batch normalisation script simultanesly. :)

EDIT: Latest file is saved on GitHub, https://github.com/xtsimpouris/batch-file-ideas/blob/master/normalize.bat

Linked In Profile