Skip to content

Instantly share code, notes, and snippets.

@pjobson
Last active January 31, 2023 13:06
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save pjobson/46cf627e7aa42f49c7727533265919a8 to your computer and use it in GitHub Desktop.
Save pjobson/46cf627e7aa42f49c7727533265919a8 to your computer and use it in GitHub Desktop.
Notes for creating, editing, and extracting MKV files.

MKVToolNix Notes

Various notes for using MKVToolNix.

Probe a Video

mkvinfo lists all elements contained in an MKV container file.

mkvinfo container.mkv

Returns information about the files in the MKV container.

The Segment tracks section is particularly useful. This lists the individual tracks and properties for each track.

Split Up an MKV File

Before splitting up an MKV file you'll need to use mkvinfo to see what kind of tracks are available.

This is an example from an MKV container with a video track, a Japanese audio track, an English audio track, and an English subtitle.

You can see here the Segment tracks part of the info output. You will want to take note of each Track number, note the track ID for mkvmerge & mkvextract, Track type, and Codec ID.

|+ Segment tracks
| + A track
|  + Track number: 1 (track ID for mkvmerge & mkvextract: 0)
|  + Track UID: 1
|  + Track type: video
|  + Lacing flag: 0
|  + MinCache: 1
|  + Codec ID: V_MPEG4/ISO/AVC
|  + CodecPrivate, length 46 (h.264 profile: High @L4.1)
|  + Default duration: 41.708ms (23.976 frames/fields per second for a video track)
|  + Language: jpn
|  + Video track
|   + Pixel width: 1280
|   + Pixel height: 692
|   + Display width: 1280
|   + Display height: 692
| + A track
|  + Track number: 2 (track ID for mkvmerge & mkvextract: 1)
|  + Track UID: 6043920465630136738
|  + Track type: audio
|  + Codec ID: A_AC3
|  + Default duration: 32.000ms (31.250 frames/fields per second for a video track)
|  + Language: jpn
|  + Audio track
|   + Sampling frequency: 48000
|   + Channels: 2
| + A track
|  + Track number: 3 (track ID for mkvmerge & mkvextract: 2)
|  + Track UID: 12782137182802743458
|  + Track type: audio
|  + Default flag: 0
|  + Codec ID: A_AC3
|  + Default duration: 32.000ms (31.250 frames/fields per second for a video track)
|  + Audio track
|   + Sampling frequency: 48000
|   + Channels: 2
| + A track
|  + Track number: 4 (track ID for mkvmerge & mkvextract: 3)
|  + Track UID: 1740530865744497682
|  + Track type: subtitles
|  + Lacing flag: 0
|  + Codec ID: S_TEXT/UTF8
|  + Name: English Subtitles

I will be extracting the following tracks. Note that the second audio track above does not specify a language, you may have to listen to the track to figure it out.

Track ID 0 - video              - MPEG4/ISO/AVC
Track ID 1 - audio (Japanese)   - AC3
Track ID 2 - audio (English)    - AC3
Track ID 3 - subtitle (English) - TEXT/UTF8

To extract all I will do the following.

mkvextract tracks original_video.mkv \
    0:video.mp4                      \
    1:audio.jpn.ac3                  \
    2:audio.eng.ac3                  \
    3:english.srt

This will output the following:

Extracting track 0 with the CodecID 'V_MPEG4/ISO/AVC' to the file 'video.mp4'. Container format: AVC/h.264 elementary stream
Extracting track 1 with the CodecID 'A_AC3' to the file 'audio.jpn.ac3'. Container format: Dolby Digital (AC-3)
Extracting track 2 with the CodecID 'A_AC3' to the file 'audio.eng.ac3'. Container format: Dolby Digital (AC-3)
Extracting track 3 with the CodecID 'S_TEXT/UTF8' to the file 'english.srt'. Container format: SRT text subtitles
Progress: 0%...100%

Then in your path you should have each of the output files: audio.eng.ac3, audio.jpn.ac3, subtitle.srt, video.mp4, and the initial original_video.mkv.

Merge Various Files to an MKV

You can use mkvmerge to join several audio, video, and subtitle files into one MKV container. Using the files I extracted from above for this example.

mkvmerge -o container.mkv \
  video.mp4               \
  audio.eng.ac3           \
  audio.jpn.ac3           \
  english.srt

This command will output something like this.

mkvmerge v8.8.0 ('Wind at my back') 64bit
'video.mp4': Using the demultiplexer for the format 'AVC/h.264'.
'audio.eng.ac3': Using the demultiplexer for the format 'AC-3'.
'audio.jpn.ac3': Using the demultiplexer for the format 'AC-3'.
'english.srt': Using the demultiplexer for the format 'SRT subtitles'.
'video.mp4' track 0: Using the output module for the format 'AVC/h.264 (unframed)'.
'audio.eng.ac3' track 0: Using the output module for the format 'AC-3'.
'audio.jpn.ac3' track 0: Using the output module for the format 'AC-3'.
'english.srt' track 0: Using the output module for the format 'text subtitles'.
The file 'container.mkv' has been opened for writing.
'video.mp4' track 0: Extracted the aspect ratio information from the MPEG-4 layer 10 (AVC) video data and set the display dimensions to 1280/692.
Progress: 100%
The cue entries (the index) are being written...
Muxing took 24 seconds.

Concatenate Two Similar MKV Containers

You can use mkvmerge to concatenate two similar MKV containers into one MKV container.

mkvmerge -o container.mkv \
  Part1.mkv               \
  +Part2.mkv              \
  +Part3.mkv

If this fails it may be due to slightly dissimilar MKV containers, I have had luck extracting all of the media from the original parts, then rebuilding them.

Editing Properties

After creating the container, all of the properties are empty. mkvinfo container.mkv returns the track info for the merge above. You can see Language is set to und or undefined for each track.

We will use mkvpropedit to modify the languages, here's what we are working with. You will need the Track number and the first letter of the Codec ID.

Track number: 1
Codec ID: V_MPEG4/ISO/AVC

Track number: 2
Codec ID: A_AC3

Track number: 3
Codec ID: A_AC3

Track number: 4
Codec ID: S_TEXT/UTF8

Edit the properties as such.

mkvpropedit container.mkv \
    --edit track:v1 --set language=jpn \
    --edit track:a1 --set language=eng \
    --edit track:a2 --set language=jpn \
    --edit track:s1 --set language=eng

Running mkvinfo container.mkv again will show that each track has the specified language set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment