Sharing some ffmpeg scripts I made to down convert audio in batch as well a 'night mode / DRC'

EDIT: Updated the scripts slightly to add language metadata, add SL & SR to the night mode script (sometimes channels are called BL BR or SL SR) (thanks @leelynds). Corrected the bitrate on both scripts. The .bat files have been updated too.

EDIT 2: Added FLC (front left centre) & FRC (Front right centre) channels to the Nightmode mix-down. This means all channels are there for a 7.1 mix-down now. Also, I’ve added 2 more scripts which are the exact same as the first 2, but also includes the ‘loudnorm’ filter, which normalizes the new mix-down track to EBU R128 (industry standard). Note that the ‘LoudNorm’ scripts are slower than the others because it adds another process.

EDIT 3: As an alternate to the ‘NightMode’ scripts I have added one more script which adds actual DRC (Dynamic Range Compression) to the mixdown instead of just mixing the FL, FR, BL(SL), BR(SR), FLC, FRC, FC, LFE channels at different volumes (thanks @OttoKerner) . This is most similar to what a soundbar might do in order to reduce the loud & increase the quiet parts of a movie. Try out both to see which works best for you, and be sure to dig into the settings to find the sweet spot for your setup :slight_smile:

Hey all, I was looking for a simple solution to a few issues I was having:

  1. AAC 5.1 doesn’t work too well on Apple TV.
  2. Like many others, I get annoyed when a movie is too loud during action scenes, but too quiet during dialogue. Especially at night.

I started looking into this after I watched ‘Rumble in the Bronx’ (Classic JC, amirite?) and got really annoyed at how loud the sound effects were while the dialogue was really quiet. Suffice to say, after searching for a solution, it turns out that movie just has a really bad sound mix (who’d have thought huh?!) so my search for a solution to fix the problem was all for naught, but I came across the Apple TV AAC 5.1 issue around the same time, so I figured I’d keep looking for a solution & just share them with you guys anyway.

I wanted something that was quick & that could be done in batches so I don’t have to manually edit each file.

BOTH THESE SCRIPTS ARE VERY SIMILAR, BUT ARE DESIGNED FOR DIFFERENT USES.

NOTE: I’m not a coder, I’ve just pieced this together by scouring the internet for related problems & piecing together. Although, I do feel like I have a slightly better grasp on ffmpeg now, and boy is it powerful!

HOW FAST IS IT AT PROCESSING FILES?

In my testing, the scripts achieved the follow speeds (ymmv depending on setup):

  • Downmix_Stereo.bat = 47x
  • Nighmode_Stereo.bat = 47x
  • Downmix_Stereo_LoudNorm = 7x
  • Nightmode_Stereo_LoudNorm = 18x
  • Downmix_Stereo_DRC+LoudNorm = 6.6x

HOW TO USE THESE SCRIPTS?

Since the scripts are ffmpeg, they should work on most systems, however (and remember I’m no coder) there are some parts of the scripts that probably wont work unless you’re on Windows. I’ll try and point out these parts of the scripts at the end.

You need to install ffmpeg. I set it up as an environment variable so I could just reference ‘ffmpeg’ in cmd & I don’t have to keep pointing to where its located each time, the article I linked to shows how to do that.

These scripts are designed to work with .mkv files. Though you can easily mod this work with .mp4 if you’d like instead.

To run a script:

  1. save it as a .bat file (I’ll include links to those below too for simplicity)
  2. Paste the .bat into the folder with all the videos you want to run through the script
  3. Double click it & watch it do its thing :slight_smile:

SCRIPT 01 - 5.1/7.1 to Stereo Mixdown

What does it do?

  • Keeps all existing video, audio (up to 6 tracks), subtitles & chapters.
  • Creates a stereo mixdown of the first audio track (which is assumed to be a 5.1 track, not much use using this on a video which is already stereo).
  • Names the new track ‘Eng 2.0 Stereo’
  • Inserts the new track as the second track in the audio stream. So if you have multiple tracks (such as commentary etc), those tracks will be moved below the new track.

Example

Lets say the input file looks like the following:

Name: input.mkv

  1. Video Stream
  2. 5.1 Audio Track
  3. Commentary Audio Track
  4. Subtitle (eng)
  5. Subtitle (fr)

The output, after being run through this script will look like the following:

(note: A sub-folder called ‘ffmpegOut’ will be created in whatever folder you run this script in, this is where the output file will be saved, so there is no overwriting files ****)

Name: input_Stereo.mkv (file name now has ‘_Stereo’ appended to it)

  1. Video Stream
  2. 5.1 Audio Track
  3. Stereo Audio Track (downmix of the 5.1 track)
  4. Commentary Audio Track
  5. Subtitle (eng)
  6. Subtitle (fr)

The Script

if not exist "ffmpegOut\" MD "ffmpegOut"

for %%A IN ("*.mkv") Do ffmpeg -y -i "%%A" -map 0:v -c:v copy -map 0:a:0? -c:a:0 copy -map 0:a:0? -c:a:1 aac -b:a:1 192k -ac 2 -metadata:s:a:1 title="Eng 2.0 Stereo" -map 0:a:1? -c:a:2 copy -map 0:a:2? -c:a:3 copy -map 0:a:3? -c:a:4 copy -map 0:a:4? -c:a:5 copy -map 0:a:5? -c:a:6 copy -map 0:a:6? -c:a:7 copy -map 0:s? -c:s copy "ffmpegOut/%%~nA_Stereo.mkv"

pause

SCRIPT 02 - 5.1/7.1 to NIGHTMODE Stereo Mixdown

What does it do?

  • Keeps all existing video, audio (up to 6 tracks), subtitles & chapters.
  • Creates a ‘nightmode’ stereo mixdown of the first audio track (which is assumed to be a 5.1 track, not much use using this on a video which is already stereo).
  • Names the new track ‘Eng NightMode’
  • Inserts the new track as the second track in the audio stream. So if you have multiple tracks (such as commentary etc), those tracks will be moved below the new track.

Example

Lets say the input file looks like the following:

Name: input.mkv

  1. Video Stream
  2. 5.1 Audio Track
  3. Commentary Audio Track
  4. Subtitle (eng)
  5. Subtitle (fr)

The output, after being run through this script will look like the following:

(note: A sub-folder called ‘ffmpegOut’ will be created in whatever folder you run this script in, this is where the output file will be saved, so there is no overwriting files ****)

Name: input_Stereo.mkv (file name now has ‘_Stereo’ appended to it)

  1. Video Stream
  2. 5.1 Audio Track
  3. NightMode Audio Track (downmix of the 5.1 track)
  4. Commentary Audio Track
  5. Subtitle (eng)
  6. Subtitle (fr)

What is ‘NightMode’?

People with ‘cheaper’ 2.1 audio setups often find that 7.1/5.1 audio tends to have LOUD music/sound effects but QUIETdialogue. ‘NightMode’ attempts to fix this (while keeping the original track of course!) by re-mapping the audio channels of the 7.1/5.1 track to favor the centre channel (where the dialogue comes from mostly).

Here’s what it is doing:

In each (Left or Right) Channel it is putting:

  • 100% of the Front Centre Channel
  • 30% of the Front L/R & Back L/R Channel
  • 30% of the Front L/R Centre Channels
  • 60% of the LFE Channel

Some of you may find the default settings too aggressive so feel free to tweak them to your liking by tweaking the following section of the script (maybe try 0.60 instead?): FL=FC+0.30*FL+0.30*FLC+0.30*BL+0.30*SL+0.60*LFE|FR=FC+0.30*FR+0.30*FRC+0.30*BR+0.30*SR+0.60*LFE

FC = Front Centre

FLC = Front Left Centre

FL = Front Left

BL = Back Left

SL = Side Left (same as Back Left)

FR = Front Right

FRC = Front Right Centre

BR = Back Right

SR = Side Right (same as Back Right)

LFE = Low Frequency Effects

Just play with the multipliers on each of those settings until you get something that suits your needs.

Notes

Because of the way these scripts are set up, they are able to copy up to 6 audio tracks. If there are more tracks in the video file than that and you want to keep them all, you’ll have to mod the script slightly. I’ll give a breakdown of what each component of the script does at the end, so you can mod it however you like.

The Script

if not exist "ffmpegOut\" MD "ffmpegOut"

for %%A IN ("*.mkv") Do ffmpeg -y -i "%%A" -map 0:v -c:v copy -map 0:a:0? -c:a:0 copy -map 0:a:0? -c:a:1 aac -b:a:1 192k -ac 2 -filter:a:1 "pan=stereo|FL=FC+0.30*FL+0.30*FLC+0.30*BL+0.30*SL+0.60*LFE|FR=FC+0.30*FR+0.30*FRC+0.30*BR+0.30*SR+0.60*LFE" -metadata:s:a:1 title="Eng NightMode" -metadata:s:a:1 language=eng -map 0:a:1? -c:a:2 copy -map 0:a:2? -c:a:3 copy -map 0:a:3? -c:a:4 copy -map 0:a:4? -c:a:5 copy -map 0:a:5? -c:a:6 copy -map 0:a:6? -c:a:7 copy -map 0:s? -c:s copy "ffmpegOut/%%~nA_NightMode.mkv"

pause

SCRIPT 03/04 - 5.1/7.1 to Stereo Mixdown (LoudNorm) / NIGHTMODE Stereo Mixdown (LoudNorm)

These are the exact same as the first 2, but also includes the ‘loudnorm’ filter, which normalizes the new mix-down track to EBU R128 (industry standard).

Note

The ‘LoudNorm’ scripts are significantly slower (tough still fast!) than the others because it adds another process.

Script 03

if not exist "ffmpegOut\" MD "ffmpegOut"

for %%A IN ("*.mkv") Do ffmpeg -y -i "%%A" -map 0:v -c:v copy -map 0:a:0? -c:a:0 copy -map 0:a:0? -c:a:1 aac -ac 2 -filter:a:1 "loudnorm" -ar:a:1 48000 -b:a:1 192k -metadata:s:a:1 title="Eng 2.0 Stereo" -metadata:s:a:1 language=eng -map 0:a:1? -c:a:2 copy -map 0:a:2? -c:a:3 copy -map 0:a:3? -c:a:4 copy -map 0:a:4? -c:a:5 copy -map 0:a:5? -c:a:6 copy -map 0:a:6? -c:a:7 copy -map 0:s? -c:s copy "ffmpegOut/%%~nA_Stereo_LoudNorm.mkv"

pause

Script 04

if not exist "ffmpegOut\" MD "ffmpegOut"

for %%A IN ("*.mkv") Do ffmpeg -y -i "%%A" -map 0:v -c:v copy -map 0:a:0? -c:a:0 copy -map 0:a:0? -c:a:1 aac -ac 2 -filter:a:1 "pan=stereo|FL=FC+0.30*FL+0.30*FLC+0.30*BL+0.30*SL+0.60*LFE|FR=FC+0.30*FR+0.30*FRC+0.30*BR+0.30*SR+0.60*LFE,loudnorm" -ar:a:1 48000 -b:a:1 192k -metadata:s:a:1 title="Eng NightMode" -metadata:s:a:1 language=eng -map 0:a:1? -c:a:2 copy -map 0:a:2? -c:a:3 copy -map 0:a:3? -c:a:4 copy -map 0:a:4? -c:a:5 copy -map 0:a:5? -c:a:6 copy -map 0:a:6? -c:a:7 copy -map 0:s? -c:s copy "ffmpegOut/%%~nA_NightMode_LoudNorm.mkv"

pause

SCRIPT 05 - 5.1/7.1 to Stereo Mixdown with DRC + LoudNorm

What does it do?

  • Keeps all existing video, audio (up to 6 tracks), subtitles & chapters.
  • Creates a ‘DRC’ stereo mixdown of the first audio track (which is assumed to be a 7.1 or 5.1 track, not much use using this on a video which is already stereo).
  • Names the new track ‘Eng 2.0 Stereo DRC’
  • Inserts the new track as the second track in the audio stream. So if you have multiple tracks (such as commentary etc), those tracks will be moved below the new track.

What is ‘DRC’?

Similar to ‘NightMode’, DRC (Dynamic Range Compression) is another way of reducing the loudest parts of a movie. DRC is the ‘proper’ way of doing this as it actually compresses the ‘Dynamic Range’ of the audio. A good AV Receiver includes similar DRC controls.

The Script

if not exist "ffmpegOut\" MD "ffmpegOut"

for %%A IN ("*.mkv") Do ffmpeg -y -i "%%A" -map 0:v -c:v copy -map 0:a:0? -c:a:0 copy -map 0:a:0? -c:a:1 aac -ac 2 -filter:a:1 "acompressor=ratio=4,loudnorm" -ar:a:1 48000 -b:a:1 192k -metadata:s:a:1 title="Eng 2.0 Stereo DRC" -metadata:s:a:1 language=eng -map 0:a:1? -c:a:2 copy -map 0:a:2? -c:a:3 copy -map 0:a:3? -c:a:4 copy -map 0:a:4? -c:a:5 copy -map 0:a:5? -c:a:6 copy -map 0:a:6? -c:a:7 copy -map 0:s? -c:s copy "ffmpegOut/%%~nA_Stereo_DRC.mkv"

pause

BREAKDOWN OF THE SCRIPTS

if not exist "ffmpegOut\" MD "ffmpegOut"

This is the windows command to create a folder (within the folder you loaded the script) called “ffmpegOut”. If the folder already exists, it will not make the folder. Just replace “ffmpegOut” if you want to call the folder something else.

for %%A IN ("*.mkv") Do ffmpeg -y -i "%%A"

for %%A IN ("*.mkv") This is telling the script to find any .mkv file within the folder you run the script in. The %%A is a stand in for your mkv’s file name. *.mkv means it will only run .mkv files through the script. If you need it to work with mp4’s, just replace ‘mkv’ with ‘mp4’.

Do ffmpeg -y -i "%%A" This is just telling the script to open ffmpeg & input your file (note the %%A is there again)

-map 0:v -c:v copy This is telling the script to copy the video track (no re-encoding). v = Video

-map 0:a:0? -c:a:0 copy This is copying the first audio track & keeping it assigned as the first track. a = Audio

-map 0:a:0? -c:a:1 aac -b:a:1 192k -ac 2 -metadata:s:a:1 title="Eng 2.0 Stereo" This is taking the first audio track again, converting it to ‘AAC’ with a bitrate of 192k & 2 audio channels (stereo), and assigning it as the second audio track. It is then giving the track a title of “Eng 2.0 Stereo”

-map 0:a:1? -c:a:2 copy -map 0:a:2? -c:a:3 copy -map 0:a:3? -c:a:4 copy -map 0:a:4? -c:a:5 copy -map 0:a:5? -c:a:6 copy -map 0:a:6? -c:a:7 copy This is copying all other audio track that may be in the video file ( ? essentially means, “if it exists, do this. If it doesn’t, don’t worry about it”), and also moving each of them down one slot in the audio track order (so that the newly created track can be the second track). If, you have a video file that has even more tracks than this that you’d like to copy, just add extra -map 0:a:6? -c:a:7 copy sections, but increment the numbers each time. Eg: -map 0:a:7? -c:a:7 copy -map 0:a:8? -c:a:9 copy etc.

-map 0:s? -c:s copy This copies all subtitles (if they exist). s = Subtitles.

"ffmpegOut/%%~nA_Stereo.mkv" This saves the output file in the ffmpegOut folder & gives it the same name as the original but with ‘Stereo’ at the end. Because the files will be saved in a subfolder, you could remove ‘_Stereo’ so that the output has the exact same name as the input, but I added this as additional protection against overwriting or accidentally deleting the original file.

loudnorm Normalizes the audio to EBU R128 (industry standard). You can read more about this here

-ar:a:1 48000 This sets the new track’s sample rate to 48000. We need to use this when using the loudnorm filter because loudnorm needs to re-sample the audio 192 kHz in order to work, so this ensures it is re-sampled it to 48000 before output.

acompressor=ratio=4 These are the audio compressor settings used on the DRC script. You can read more about this here

ffmpeg_Audio_Scripts.zip (1.9 KB)

4 Likes

nice job and great explanation of the details.

thanks for sharing.

You can zip up your scripts and attach them directly to the post.
Removes the need to keep the cloud drive active.

1 Like

I use ffmpeg to create a stereo track, not for night mode, but so if the devices that people connect with isn’t surround capable,can get audio without the need for my server to transcode on the fly.

All of my users use Rokus, or devices which automatically select the best audio track. So I always make the stereo track as the first, and the surround as the second. The surround audio is auto-selected for surround capable devices, and the stereo audio is auto selected for other devices.

I use a similar method to re-map the surround track, with slightly different settings. It uses the built-in “loudnorm” audio filter of ffmpeg, this is the code for the new stereo track::

-af "pan=stereo|FL=0.707*FC+FL+0.707*SL+0.707*BL|FR=0.707*FC+FR+0.707*SR+0.707*BR,loudnorm" -ar 48000 -b:a 160k

I use the “SL” and “SR” identifiers for the location as well as “BL” and “BR” Some audio tracks have those locations improperly identified, so if you simply include the “Back” designation, the audio from “Side” is completely ignored and not included in the track. :wink: I don’t include the LFE channel, because I’m not convinced it’s necessary in a stereo track, My opinion, though.

You also need to include the audio rate, the -ar 48000 part, or ffmpeg defaults to 96000 with the loudnorm filter, and most devices don’t know how to deal with that rate… The process takes a little longer than your script, because of the loudnorm filter, but I think it has some pretty good results.

I also always include a language tag as well as title tag that looks like this
-metadata:s:a:0 language=eng -metadata:s:a:0 title="Stereo (AAC)"
so that Plex can identify the language properly in the apps.

Give the code I use a try. I’ve used that for about 2 years on everything and seems to work great.

2 Likes

ffmpeg has a ‘compressor’ filter as well. So additionally to (or instead of) changing the mixdown formula, you could apply real DRC, which is better suited to even out the louder and the quieter passages.
https://ffmpeg.org/ffmpeg-filters.html#acompressor

I am making use of this in Plex Media Player (which also has ffmpeg baked-in) with this custom remote control command:

2 Likes

Thanks for the help leelynds, I’ve incorporated some of that in my scripts now. I’m going to make 2 separate ones for loudness normalization, for those that want to use it.

Also, looking further, some through MPC-HC I’ve noticed that some of the channels are mapped like this: C L R Ls Rs LFE. Does that mean we also need to include ‘L’, ‘R’ as well as FL, FR? And the same for ‘Ls’ & ‘Rs’ since we’re only referencing either BL/RL or SL/SR? or does ffmpeg just read L, R, Ls, Rs as FL, FR, SL, SR?

Thanks again!

Thanks OttoKerner, I’ll look at using this too! Is there much of a difference between acompressor & compand?

As far as I understand it, there is only a difference in how you formulate the parameters.
With acompressor you have actual ratio, gain, makeup, attack, decay and so on parameters.
With compand you kinda describe an ‘amplification/gain characteristic’ in a ‘graphical’ way. Which makes it more powerful - but probably also harder to understand.

Which one is easier to use, depends on which technical background a user has, I assume.
I for one am more comfortable with the classical parameters.
And the default parameters of acompressor are a relly good starting point. All the timing-related default values are working really well with spoken language - which is what most movies and tv shows are about.

1 Like

I see! Do you have a preferred set of settings for your DRC?

I ended up using the parameters in the above linked thread when I needed them.
acompressor=ratio=4:makeup=2 the rest are the default values.

You can even already get a subtle compression by using all-default values. But these turned out to be ‘too soft’ for many sources, so I cranked it up a bit.

1 Like

I think MPC-HC is probably identifying the audio properly - that is a surround audio track with “side” channels. not “back” channels. “Back” channels are probably more common in 7.1 audio.

Actually, what I was saying was that by using “BL” and “BR” in your code, you are adding the audio from a track that doesn’t exist in most 5.1 audio tracks. You can prove that yourself with this code, assuming the first audio track is standard 5.1 surround.:

ffmpeg -i "my SurroundVideo.mkv" -vn -af "pan=stereo|FL=BL|FR=BR" "MyBackChannels.aac"

Then using the same file, try

ffmpeg -i "my SurroundVideo.mkv" -vn -af "pan=stereo|FL=SL|FR=SR" "MySideChannels.aac"

What you will end up with is a silent (no audio) stereo track in “MyBackChannels.aac” and only the side (or surround) audio in “MySideChannels.aac”

So, going back to your code, you are (probably) not including any of the “surround” effects in you night-mode audio. If your intention was to include the audio from the surround tracks in the new stereo track, I believe your code would benefit in most cases if you replaced the BL and BR with SL and SR. . I think your code would only include the three front channels (and the LFE) because you have specified back channels that probably don’t exist and therefore cannot be included, and excluded the side channels, which probably do exist. LOL - I hope that makes sense.

Surround audio has many formats, and most people think of surround audio as 5.1. Technically, that is Front Left (FL), Front Center (FC), Front Right (FR), Side Left (SL), Side Right (SR) and Low Frequency Effects (LFE). In the real world, people often have the “side” channel speakers placed behind them, so they consider it back speakers.

Have a look here to see a list of surround formats ffmpeg can deal with, and how they are named and laid out usually:
https://trac.ffmpeg.org/wiki/AudioChannelManipulation#Layouts

As an aside, I recently re-ripped my blu-ray copy of the Fly from 1958. It has 4.0 surround DTS audio, which I remapped to 5.1 (side) AC3 and a stereo track for streaming with a little creative custom channel manipulation.

Ahh, I see! Well I’ve left BL & BR in my script anyway, as it is referenced as a potential layout in the ffmpeg wiki. As long as their levels are kept the same as the SL & SR it shouldn’t be a problem I don’t think? Since if BL/BR don’t exist it wont use them. I guess it’s a ‘just in case’ setup.

You can actually try and use the Plex transcoder executable, which is a version of ffmpeg.

I didn’t realize until after I posted that you had modified your scripts. I actually include the BL/BR references in the bat file I have been using (similar to your new ones), and as far as I can tell ffmpeg does just that - ignores references to channel mapping that doesn’t exist in the file. By the way, nice job on the scripts. I might use them to fix up some old stuff that I have, with only one surround audio track.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.