Learn FFmpeg - Muxing, Demuxing & Containers
Episode 8 of 23

Learn FFmpeg - Muxing, Demuxing & Containers

In this episode you'll understand the role of the MP4, MKV, and WebM containers, learn to remux without re-encoding using -c copy, and select, add, and remove streams precisely with -map.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 7 you learned to inspect file contents with ffprobe — now you can see that a video file is actually made up of many streams packed into one container. This episode dissects that container itself, and the two operations revolving around it — muxing (combining streams) and demuxing (splitting them).

This understanding matters because most "video conversions" people do aren't really conversions at all — just changing the envelope. Realizing this will save CPU time and preserve quality.

Container: The Envelope for Codecs

Separate two things that are often confused: codec and container. A codec is how the data is compressed — e.g., H.264, AAC, VP9. A container is the wrapper that unites those codec streams into a single playable file — complete with metadata, subtitles, and chapters.

The easiest analogy: a codec is the language, a container is the envelope. An envelope can hold a letter in English or Indonesian; an MP4 container can hold H.264 video and AAC audio. But not every language fits a given envelope — and not every codec fits every container.

Mux (multiplex) means combining several streams into one container; demux means unpacking them. FFmpeg does both in one command — input is demuxed, output is muxed.

ContainerCommon codecsMain strength
MP4H.264, H.265, AACWidest compatibility: web, HLS, mobile devices
MKVAlmost every codecMaximum flexibility: rich subtitles, many audio tracks
WebMVP9, AV1, OpusModern web standard, efficient size

A rule you must remember: WebM only accepts VP8/VP9/AV1 + Opus/Vorbis. You can't force H.264 or AAC into WebM — the container rejects them. MKV, on the other hand, accepts almost every codec, which is why MKV is the favorite for archiving and ripping.

Tip

The container choice is often decided not by preference, but by the playback target. Delivery to browsers and HLS: MP4. Modern web streaming: WebM. Personal archive with many tracks: MKV. Decide where the file will be played first, then pick the container.

Remux Without Re-encoding: -c copy

Most people run ffmpeg -i a.mkv b.mp4 and think it's a "conversion". In fact it's a remux: moving streams from one envelope to another without touching their content. The key is -c copy — copy the bitstream as-is, without decoding and re-encoding.

remux-mkv-ke-mp4.sh
ffmpeg -i input.mkv -c copy output.mp4

This command is very fast — can be dozens of times faster than re-encoding — and more importantly: quality doesn't change at all because the data is never unpacked.

Why does this matter? Because lossy compression is cumulative. Every time you decode then re-encode H.264, quality drops a little — that's what's called generation loss. -c copy avoids an additional generation entirely. If the goal is just changing containers, never re-encode.

Important

-c copy only moves streams — it doesn't change the codec. If the codec isn't compatible with the target container (e.g., WebM given H.264), the command will fail. Check the codec first with ffprobe -select_streams v -show_entries stream=codec_name -of csv=p=0 input.mkv before choosing the destination container.

Selecting Streams with -map

Without -map, FFmpeg selects streams based on default heuristics: one best video, one best audio, one subtitle. For full control, we use -map with a stream address in the file:type:index format.

The most important patterns to master:

  • 0:v:0 — first input file, video stream, video index 0
  • 0:a:1 — first input file, audio stream, audio index 1
  • 1:s:0 — second input file, subtitle stream, subtitle index 0
pilih-stream.sh
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -c copy output.mp4

With the command above, you map exactly one video and one audio to the output — nothing more. This is the basic pattern that will become the backbone of all later muxing operations.

Adding & Removing Streams

With -map, adding and removing streams are two sides of the same coin: what isn't mapped doesn't go to the output.

hapus-audio.sh
ffmpeg -i input.mp4 -map 0:v:0 -c copy silent.mp4

The command above maps only video — all audio and subtitles are dropped. The result is a silent file without re-encoding. To add a stream, just feed in a second input and map it:

tambah-lagu.sh
ffmpeg -i video.mp4 -i music.mp3 -map 0:v:0 -map 1:a:0 -c:v copy -c:a aac output.mp4

Here video is copied (-c:v copy) and the song from the second file is encoded to AAC (-c:a aac). The -map 0:v:0 -map 1:a:0 pattern is the universal answer for "replace the soundtrack" or "add audio" without touching the video.

Demuxing: Unpacking Streams

Demuxing — separating streams — is done by mapping only one stream and writing it to its own file. This technique is useful for extracting pure audio, subtitles, or raw video from a combined file.

ekstrak-audio.sh
ffmpeg -i input.mp4 -map 0:a:0 -c copy audio.m4a

The result is a separate audio file extracted from the MP4. Because of -c copy, this extraction is instant and doesn't change quality — exactly like taking a letter out of an envelope without opening it. In episode 11 you'll do the same for subtitles.

Warning

Beware the "just change the extension" assumption. A file extension (mp4, mkv) is only a label; what determines the content is the codec inside. -c copy to a wrong extension doesn't rewrite the codec — it only changes the label, and players can reject it. Always verify with ffprobe -show_format input.mp4 after a remux.

Conclusion

In episode 8 you've understood the container's role as the envelope for codecs: the compatibility rules of MP4, MKV, and WebM, fast remuxing without re-encoding with -c copy, precise stream selection with -map, and how to add, remove, and separate streams without touching quality.

The key takeaway: the separation between codec and container is the key. Once you distinguish the two, most of FFmpeg's "weird" puzzles become clear — including why a file rejects a certain codec.

In the next episode 9 we scale up: processing many files at once with loops, parallel processing, and safe scripts — the skill that turns FFmpeg from a manual tool into a batch machine. See you in episode 9!

Learn FFmpeg - Muxing, Demuxing & Containers | Learn FFmpeg