ffmpeg loudnorm 2pass in single line

TL;DR an example of loudnorm 2pass in single line using ffpmpeg (ffmpeg-normalize is single thread/process and I can't combine other ffmpeg options to it)

Not really much examples on loudnorm since it's relatively new to ffmpeg, I've been using ffmpeg for 10 or so years. I am new to loudnorm however

I've read:

How can I normalize audio using ffmpeg?

which are helpful. however I'm trying to consolidate multiple ffmpeg entries into 1. using ffmpeg-normalize (the python) library limits you to a single thread/process as well. which is slow

for 2 pass of ffmpeg x264 you can simply do:

ffmpeg -y -i $FILE -c:v libx264 -b:v 4000k -pass 1 -c:a aac -b:a 256k -f mkv /dev/null && \
ffmpeg -i $FILE -c:v libx264 -b:v 4000k -pass 2 -c:a aac -b:a 256k $FILE.mkv

doesn't seem to exist for loudnorm though. I don't see a way to do it at all with a single and 2 pass?

currently I'm encoding video,then normalizing audio, and finally stripping metadata and chapter data from files if it exists (regardless if it exists or not)

this creates 3 throw-away files (including the original)

being able to do loudnorm in a single line would help me add other stuff to it also is it possible to do a 2pass of x264 and a 2pass of loudnorm simultaneously? as in have it process the two and then combine them in the second pass.

If possible I'd like examples of these and not links to things. I can google links on my own and have for several weeks. Thanks

1

2 Answers

There's no way to run a two-pass loudnorm filter automatically with just ffmpeg, but you can use the ffmpeg-normalize program to do it for you. I know you've mentioned it, but if you want to encode video at the same time – particularly with two passes – then you will however have to work with one intermediate file, that is:

  • First run: ffmpeg-normalize on the original video, copying the original video stream.
  • Second run: x264-encoding (multithreaded) of the normalized audio file or the original file's video streams.

What you want to achieve simply cannot be done by ffmpeg alone. You need to program your own solution, especially if you want to handle several files in parallel. This would certainly speed up the process, even if a single ffmpeg run is only using one thread.

As a starting point, there's also a simpler Ruby script in the FFmpeg repository. It performs two loudnorm passes, reading the statistics of the first run. You may be able to modify it to additionaly run the two-pass x264 encoding with multithreading, that is, run the first x264 pass in the first run, the second in the second run:

First pass:

ffmpeg -y -i $FILE -c:v libx264 -b:v 4000k -pass 1 -filter:a loudnorm=print_format=json -f mkv /dev/null

Read the JSON statistics from the loudnorm output (e.g., using Python's JSON parser, or any other tool like grep or awk), then run the second pass:

ffmpeg -i $FILE -c:v libx264 -b:v 4000k -pass 2 -filter:a loudnorm=linear=true:measured_I=$input_i:measured_LRA=$input_lra:measured_tp=$input_tp:measured_thresh=$input_thresh -c:a aac -b:a 256k $FILE.mkv

Where $input_i, $input_lra, $input_tp, $input_thresh are the values read from the first pass.

3

There is no need for another program. This actually CAN be done with ffmpeg alone. I actually created a bat file that will do this.

cls
echo off
ffmpeg -i %1 -filter_complex "[0:a]loudnorm=I=-16:TP=-1.5:LRA=11:print_format=summary" -f null x 2>%1.txt
@for /f "tokens=3" %%a in ('findstr /C:"Input Integrated" %1.txt') do (set II=%%a)
echo %II% is the Input Integrated
@for /f "tokens=4" %%a in ('findstr /C:"Input True Peak" %1.txt') do (set ITP=%%a)
echo %ITP% is the Input True Peak
@for /f "tokens=3" %%a in ('findstr /C:"Input LRA" %1.txt') do (set ILRA=%%a)
echo %ILRA% is the Input LRA
@for /f "tokens=3" %%a in ('findstr /C:"Input Threshold" %1.txt') do (set IT=%%a)
echo %IT% is the Input Threshold
@for /f "tokens=3" %%a in ('findstr /C:"Output Integrated" %1.txt') do (set OI=%%a)
echo %OI% is the Output Integrated
@for /f "tokens=4" %%a in ('findstr /C:"Output True Peak" %1.txt') do (set OTP=%%a)
echo %OTP% is the Output True Peak
@for /f "tokens=3" %%a in ('findstr /C:"Output LRA" %1.txt') do (set OLRA=%%a)
echo %OLRA% is the Output LRA
@for /f "tokens=3" %%a in ('findstr /C:"Output Threshold" %1.txt') do (set OT=%%a)
echo %OT% is the Output Threshold
@for /f "tokens=3" %%a in ('findstr /C:"Target Offset" %1.txt') do (set TO=%%a)
echo %TO% is the Target Offset
ffmpeg -i %1 -af 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 loudnorm.wav

What this does is it first analyzes the audio and saves the results to a text file. It then reads the results from the text file and stores them as variables for each required measurement field. All you have to do it adjust the I= and TP= to your liking in the file.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like