How to change default audio track using FFmpeg?

Solution 1:

The ordering of the audio streams can be accomplished using FFmpeg's map and disposition options. Best syntax for this is arguably:

ffmpeg -i input.mkv -map 0:v:0 \
       -map 0:a:2 -map 0:a:0 -map 0:a:1 -map 0:a:3 \
       -map 0:s -c copy \
       -disposition:a:0 default \
       reordered.mkv

To unpack this a little:

  • -map 0:v:0: The first (and only) video stream is selected
  • -map 0:a:1 -map 0:a:0 -map 0:a:2 -map 0:a:3: The audio streams are individually placed. The final digit of each 'set' selects from the 4 audio streams with '0' being the first stream and '3' being the final audio stream. English is of course specified first and is stream 2.
  • -map 0:s: Select all of the subtitle files
  • -c copy: Copy the video, audio and subtitle streams with no re-encoding.
  • -disposition:a:0 default: This sets our required audio stream (English) as the default. Useful if this has been set on another, input audio stream.

This worked well on a test file produced on my system and should work well on yours as well...

Notes...

  • Selecting streams with the -map option: Beautifully written FFmpeg trac guide to using FFmpeg's map options
  • FFmpeg's Main Options: Scroll down from this link to see the usage and options available for FFmpeg's disposition options.

Solution 2:

I found this thread by asking Google a highly related but slightly different question - which I now have the answer to. So could be someone else with the same issue as mine will also end up here and this might help out someone else at some time.

Our 'Smart' TV has an integrated Mp4 player, and it will play MP3 or AAC sound tracks. I have a load (80 or so) of files which have an AAC soundtrack - but these play at painfully low audio volume (TV volume set at 100% is nowhere near loud enough to hear a lot of the dialog). With oldies in the house with hearing problems and no embedded subs, this makes said videos unwatchable.

So, I wanted a way to use ffmpeg to:

  1. Preserve the original AAC but also add an MP3 sound track, derived from the AAC, but with loudness processing so that it's suitable for TV watching.

  2. Demote the AAC sound track to be the second audio stream, while making the new MP3 audio the default. During the process of experimentation I found that this particular TV player (Panasonic) always defaults to the first audio stream - no matter which is flagged as the default.

  3. As the icing on this cake, I wanted to give each audio stream a proper metadata title.

I could have just demuxed the existing streams and then created the new processed audio and then muxed them all up again, but I was convinced that ffmpeg could do this as one command line - which makes for far neater and faster progress when you have 80 files to do. ffmpeg didn't let me down.

With help from the answers above and other stuff I found, this is the command line I ended up with - works a treat.

ffmpeg -i intest.mp4 -map 0 -disposition:a:0 0 -c:v copy -c:a:0 libmp3lame -metadata:s:a:0 title="MP3-LoudnessProcessed" -metadata:s:a:1 title="OriginalAAC" -filter:a loudnorm -disposition:a:0 default -map 0:a:0 -disposition:a:1 0 outtest.mp4 

In this command:

  • -map 0 means select all streams

  • -disposition:a:0 0 means, forget that the 1st audio stream is the default audio stream

  • -c:v copy – means transfer the video stream as-is

  • -c:a:0 libmp3lame -metadata:s:a:0 title="mp3-LoudnessProcessed" -filter:a loudnorm -disposition:a:0 default means make a new MP3 audio stream as stream 0 and title it “Mp3” also do a loudness normalisation on that stream and make it the default audio

  • -map 0:a:0 means map the first existing AAC audio stream from the input file. Because this happens last of all, it ends up as the 2nd audio stream (stream 1). Some players always default to the first audio stream (stream 0) – no matter which one is flagged as the default audio, so I needed to be sure the AAC stream was last.

  • -disposition:a:1 0 - means forget that the existing audio stream (now audio stream 1) was ever the default. This is likely not actually be needed(??) but does no harm.

ffmpeg never fails to impress - always a way to do what you want. HTH someone else sometime.