MKV (Matroska) in Practice: EBML Structure, Multiple Tracks, Chapters, and FFmpeg

Key takeaways

Matroska (MKV) stores any number of video, audio and subtitle tracks, chapters and attached fonts in an EBML element tree, and survives an interrupted recording far better than MP4. This guide covers the Segment/Cluster/Cues layout, FFmpeg commands for mapping and extracting tracks, default and forced flags, and what breaks when converting to MP4 for delivery.

Introduction

MKV (Matroska) is an open container format built on EBML (Extensible Binary Meta Language). It can hold practically any codec, any number of audio and subtitle tracks, chapters, tags and attached files (fonts for styled subtitles, cover images) in one file. That flexibility is why it is the usual choice for rips, multilingual lecture recordings, subtitle work and screen recordings.

What MKV does not have is universal playback support. Browsers, TVs and phone galleries are built around MP4, so a common split is MKV for recording, masters and editing, and MP4 (or fragmented MP4 for streaming) for release. The rest of this article explains the structure that makes MKV flexible, the FFmpeg commands for working with its tracks, and what to watch for at the MKV to MP4 boundary.


Where Matroska Came From and What It Supports

History and background

Matroska started in 2002 as a fork of the Multimedia Container Format (MCF) project and moved to EBML, a binary format with an XML-like element tree. The specification is open and now published through the IETF (RFC 9559). The extension is only a hint about content: .mkv for video, .mka for audio only, .mks for subtitles only, and .mk3d for stereoscopic video. Always check what a file actually contains with ffprobe.

Technical characteristics

  • Track model: separate video, audio and subtitle tracks, each with a codec ID, language, name and flags (default, forced, hearing-impaired, commentary).
  • Chapters and tags: editions and chapters for DVD/Blu-ray-style navigation, and tags for metadata such as title, artist and date.
  • Attachments: fonts for ASS/SSA subtitles and cover images, stored inside the file.
  • Codecs: H.264, HEVC, AV1, VP9, FLAC, Opus, AC-3, DTS, TrueHD, SRT, ASS, PGS and many more. The container accepts them; whether a player can decode each one is a separate question.

EBML, Clusters, and Cues Inside an MKV File

EBML and Matroska elements

Every piece of an MKV file is an EBML element: an ID, a size and a payload, where IDs and sizes are variable-length integers, so small values take few bytes. Elements nest: a parent’s payload is a sequence of child elements. A reader that does not recognize an element can skip it using its size, which is how the format stays extensible without breaking old players.

Segment, Cluster, Cues

  • EBML header: identifies the file as Matroska or WebM (DocType).
  • Segment: the single top-level element that holds everything else.
  • SeekHead: a small table of where the other top-level elements are, so a reader can jump to them.
  • Info: duration, the timestamp scale, the writing application.
  • Tracks: one entry per track, with codec ID and codec private data (such as H.264 SPS/PPS).
  • Cluster: a group of frames with a base timestamp. Each SimpleBlock or BlockGroup inside holds one frame for one track, with a timestamp relative to the cluster.
  • Cues: the seek index, mapping timestamps to cluster positions, usually for keyframes of the video track.

Because every cluster carries its own timestamp and every block names its track, a player can start reading at any cluster and make sense of it. This is why MKV is robust as a recording format. If a recording program crashes, the file lacks its final Cues and duration, but the clusters already written remain playable, and tools like mkvmerge or a plain ffmpeg -c copy remux rebuild the index. A regular (non-fragmented) MP4 writes its moov index only when the recording is finalized, so the same crash usually leaves an MP4 that players refuse to open. That difference is why screen-recording tools such as OBS have long recommended MKV for recordings and offer a remux to MP4 afterwards.

The Cues element also explains a streaming detail. FFmpeg writes it at the end of the file by default, since it only knows the keyframe positions after writing them. A player that reads over HTTP must then fetch the end of the file before it can seek. -reserve_index_space reserves room near the start for the index; it matters for web delivery of WebM and hardly at all for local files.

Timestamps

Matroska timestamps are integers multiplied by TimestampScale, which is 1,000,000 ns (one millisecond) by default and in FFmpeg’s output. Millisecond precision is fine for video, but audio frame durations such as 1024 samples at 48 kHz (21.333 ms) are not whole milliseconds, so each block’s timestamp is rounded. Players handle this, and it does not accumulate, since each timestamp is rounded independently, but it is the reason some sample-accurate tools report tiny jitter on MKV audio that the same stream in MP4 does not show.

WebM relationship

WebM is a subset of Matroska limited to VP8/VP9/AV1 video, Vorbis/Opus audio and WebVTT subtitles, with some elements disallowed. Browsers implement WebM, so a few MKV files whose codecs happen to be WebM-compatible will play in some browsers anyway. Do not rely on it: the DocType says matroska, other codecs are rejected, and behavior differs between browsers.

Structure (conceptual)

flowchart TB
  EBMLHdr[EBML header]
  Seg[Segment]
  Info[Info: timecode scale, etc.]
  Tracks[Tracks: video, audio, subs]
  Tags[Tags: metadata]
  Chapters[Chapters]
  ClA[Cluster: time block A]
  ClB[Cluster: time block B]
  EBMLHdr --> Seg
  Seg --> Info
  Seg --> Tracks
  Seg --> Tags
  Seg --> Chapters
  Seg --> ClA
  Seg --> ClB

Inspecting, Remuxing, and Editing MKV Files with FFmpeg and MKVToolNix

Inspect tracks and chapters

ffprobe -hide_banner -show_format -show_streams -show_entries chapter=metadata input.mkv

For a quick overview, ffprobe -hide_banner input.mkv alone prints one line per stream with its index, language, codec and flags such as (default) and (forced). mkvinfo and mkvmerge -i from MKVToolNix show the Matroska-level view, including attachments and track UIDs, which FFmpeg hides.

Lossless remux

ffmpeg -i input.mkv -c copy remuxed.mkv

-c copy rewrites the container without decoding or re-encoding, so it takes seconds and changes no pixels or samples. Two caveats: without any -map option FFmpeg picks only one stream per type (the “best” video, audio and subtitle), so a file with three audio tracks silently comes out with one. Add -map 0 to keep everything. And attachments (fonts) are kept only when mapped too; -map 0 includes them.

Merge from multiple inputs (multi-audio + subtitle)

ffmpeg -i video.mp4 -i commentary.m4a -i subs.ass \
  -map 0:v:0 -map 0:a:0 -map 1:a:0 -map 2:s:0 \
  -c:v copy -c:a copy -c:s copy \
  -metadata:s:a:1 title="Director commentary" -metadata:s:s:0 language=kor package.mkv

The -map options pick streams by input index and type: 1:a:0 is the first audio stream of the second input. Output streams are numbered in the order of the -map options, which is what s:a:1 (the second audio stream of the output) refers to. Matroska language tags use ISO 639-2 codes such as eng, kor or jpn; newer Matroska writers can also store BCP 47 tags like pt-BR.

Set the track flags at the same time, because players use them to choose what to play:

ffmpeg -i package.mkv -map 0 -c copy \
  -disposition:a:0 default -disposition:a:1 0 \
  -disposition:s:0 0 flagged.mkv

default means “choose this track if the user has no preference”, forced marks subtitles that must be shown even when subtitles are off (for example, translations of on-screen signs), and 0 clears all flags. When a player plays the commentary instead of the main audio, or shows subtitles nobody asked for, the flags are the first thing to check. The complaint I hear most about multi-track files is exactly this, and it is almost never the player’s fault: two audio tracks both marked default, or none, leaves the choice to each player’s own heuristics.

Attach fonts for styled subtitles

ffmpeg -i package.mkv -map 0 -c copy \
  -attach NotoSansKR-Regular.otf -metadata:s:t:0 mimetype=font/otf \
  with-fonts.mkv

ASS subtitles name fonts, and a player that does not have them installed falls back to a default font, which breaks carefully timed karaoke or sign styling. Attaching the fonts makes the file self-contained. The mimetype metadata tells players what the attachment is; FFmpeg stops with an error when it is missing and cannot be deduced from the file.

Extract a subtitle track

ffmpeg -i package.mkv -map 0:s:0 -c:s copy subs-track0.srt

-c:s copy only works when the output extension matches the subtitle codec. If the track is ASS, write subs.ass; FFmpeg will not turn ASS into SRT while copying, and converting (-c:s srt) drops all styling. Image-based subtitles (PGS from Blu-ray, VobSub from DVD) are bitmaps and cannot be turned into text by FFmpeg at all; that requires OCR tools.

MKV → MP4 for web (when codecs allow)

ffmpeg -i package.mkv -c:v copy -c:a aac -b:a 192k \
  -map 0:v:0 -map 0:a:0 -movflags +faststart for_web.mp4

The video is copied and only the audio is re-encoded, which is the usual case when the source audio is FLAC, DTS or TrueHD. -movflags +faststart moves the MP4 index to the front of the file after writing, so a browser can start playback before the whole file is downloaded. For subtitles on the web, ship a separate WebVTT file with a <track> element instead of embedding them.

Simple metadata edit

ffmpeg -i input.mkv -c copy -metadata title="Series title" -metadata date="2026-03-30" tagged.mkv

FFmpeg rewrites the whole file even for a one-word title change, which is slow for a 40 GB master. mkvpropedit from MKVToolNix edits track names, languages, flags and the title in place without rewriting, usually in under a second: mkvpropedit input.mkv --edit info --set title="Series title" --edit track:a2 --set flag-default=0. For chapter and tag work, MKVToolNix is generally the better tool.


Where MKV Plays Well and Where It Does Not

AspectMKV
Local playbackVLC, mpv, Kodi, Plex and most desktop players handle it well
HTTP single fileWorks in players that support it, but MP4 is the web default
HLS/DASHPackage to fragmented MP4 (or MPEG-TS for older HLS), not raw MKV
BrowsersNot a standard web format; use MP4 or WebM

The container’s own overhead is small compared with the video bitrate, even with many tracks and tags. What costs space is content: every additional audio dub or lossless audio track adds its full bitrate, and attachments add their file size. To slim a file down, map only the tracks you need:

ffmpeg -i heavy.mkv -map 0:v:0 -map 0:a:0 -c copy slim.mkv

For mobile apps, ExoPlayer/Media3 on Android plays MKV, while iOS’s AVFoundation does not, so an app that must play the same files on both platforms usually standardizes on MP4. In both cases the harder question is the codec: HEVC, AC-3, DTS or TrueHD support varies by device and licensing, and a remux cannot fix a codec the device does not decode.


Browser Playback, Codec, and Seeking Failures

The browser will not play the MKV. HTML5 video does not standardize Matroska. Remux to MP4 (-c copy if the codecs are H.264/HEVC/AV1 with AAC/Opus) or transcode to WebM.

-c copy to MP4 fails with codec not currently supported in container. MP4 does not accept some codecs that MKV does, most often ASS/SRT subtitles (use -c:s mov_text, losing styling, or drop them with -sn), PGS subtitles (cannot be carried at all) and some audio formats. Map the streams explicitly and re-encode only the ones that fail.

Metadata disappears after conversion. Tag names and support differ between containers and tools; MP4 has no equivalent for many Matroska tags, and chapters convert only partly. Keep important metadata in an external catalog or sidecar JSON rather than relying on the container alone.

Audio will not play on a TV or phone. TrueHD, DTS and sometimes AC-3 need decoders or licenses that many devices lack. Transcode to AAC (or AC-3 for home theatre targets) for distribution and keep the original track in the master.

Seeking is slow or impossible. The Cues index is missing (interrupted recording) or the video has very long keyframe intervals. Remuxing rebuilds the index; keyframe spacing can only be changed by re-encoding.


MKV in Short

  • MKV is an EBML element tree: flexible, extensible, and robust against interrupted writes because each cluster is self-describing.
  • FFmpeg handles most track work, as long as you use -map 0 or explicit maps and set flags with -disposition; MKVToolNix is better for in-place edits, chapters and attachments.
  • Distribution still favors MP4 and fragmented MP4, so plan a remux or transcode step at the release boundary.

When to choose MKV: multilingual masters, content with many subtitle tracks or chapters, recordings that must survive crashes, and intermediate editorial files. For delivery, see the MP4 container, the WebM guide, and the MP4 vs MKV vs WebM comparison.


Frequently Asked Questions (FAQ)

Q. Why does my MKV to MP4 remux with -c copy fail or drop the subtitles?

A. MP4 accepts a narrower set of codecs than MKV. Text subtitles like SRT or ASS cannot be copied as-is, so FFmpeg either errors out or you need -c:s mov_text (which loses ASS styling), and image-based PGS subtitles cannot go into MP4 at all without burning them in. Audio such as TrueHD or DTS may also need transcoding to AAC or AC3 for players that expect MP4. Check the tracks with ffprobe first and map only the streams MP4 can carry.