MKV to MP4 with avconv/ffmpeg

Basic Conversion

Some clients don't like MKVs. An example is the plex client on an Amazon Fire TV that will request a transcode unless you force it to use Direct Play. However, converting is easy. If you do have subtitles in your file, you'll want to get those into SRT format as mp4 doesn't fully support embedded subtitles. We've also dropped any metadata, as embedded messages are usually annoying to see in your media player.

# Convert mkv to mp4, leaving out subtitles and deleting any embedded metadata
avconv -i <input.mkv> -c copy -sn -map_metadata -1 <ouput.mp4>

# See if there are subtitles
avprobe input.mkv

# Rip them to srt
avconv -i <input.mkv> <>

Selecting Streams

The default assumes you want 'the best' video and audio stream and the utility will attempt to pick for you. You can specify which streams you want if you need more granularity. See the ffmpeg link for details on how to map and convert streams if you want more background

avprobe someFile.mkv

    Stream #0.0(eng): Video: h264 ...
    Stream #0.1(eng): Audio: ac3, 48000 Hz, 5.1, fltp, 448 kb/s (default)
    Stream #0.2(ger): Audio: ac3, 48000 Hz, 5.1, fltp, 448 kb/s (default)
    Stream #0.3(eng): Subtitle: [0][0][0][0] / 0x0000 (default)

avconv -i someFile.mkv -map 0:0 -map 0:1 -c copy -sn -map_metadata -1 someFile.mp4

Down-mixing Streams

You'll sometimes get a 5.1 channel audio track like above. Most players don't support that so you'll want to down-mix to stereo

avconv -i someFile.mkv -c:v copy -ac 2 -sn -map-metadata -1 someFile.mp4

If you compiled avconv yourself, you'll want to use the FDK library for better sound

avconv -i someFile.mkv -c:v copy -c:a libfdk_aac -ac 2 -sn -map_metadata -1 someFile.mp4

Web Optimize

avconv -i test.mkv -flags +global_header -movflags faststart -codec copy test.mp4

Batch Runs

# Downmix to stereo 
for X in `ls *.mkv`; do Y=`echo $X | sed 's/mkv/mp4/'`;ffmpeg -i "$X" -flags +global_header -movflags faststart -c:v copy -c:a libfdk_aac -ac 2 "$Y";done


Cant drop subtitles

Certain builds of avconv and ffmpeg won't drop subs because they appear in the list of streams as other than expected. You'll see this if you avprobe the resultant MP4 and still see the subtitle. Even if you explicitly map streams, they're still there. It seems to happen when one of your streams is being copied.

avconv -i someFile.mkv -map 0:0 -map 0:1 -codec copy someFile.mp4
avprove someFile.mp4
    Stream #0:2(eng): Subtitle: text / 0x74786574
      handler_name    : SubtitleHandler
Unsupported codec with id 94213 for input stream 2

The only solution is to take apart the MKV and remux it with a different tool. It used to be that ffmpeg was affected and avconv was not, but both recent builds seem to have this issue now.

Codec for stream 0 does not use global headers but container format requires global headers

This _seems_ to be a bug that you can safely ignore. If you don't like the message, you can add global headers explicitly, but only removes the message for some builds. If your resulting file shows a possible desync issue, like below. You'll have to demux as above

avconv -i someFile.mkv -flags +global_header -codec copy someFile.mp4

avprobe someFile.mkv

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x20108c0] multiple edit list entries, a/v desync might occur, patch welcome

This seems to happen from an issue converting. Once again, you'll have to demux

[aac @ 0x3710f80] element type mismatch 3 != 0

This can happen with different version of the tools. You can try to build the latest source and try each.