What You Will Learn

Tested version: Verified with FFmpeg 6.1 (ubuntu-latest / CI-validated) Target OS: Windows / macOS / Linux

About filenames: This article uses placeholder filenames such as input.mkv and input.mp4. Replace them with the actual file paths you want to process.


Containers vs. Codecs

The most common source of confusion when working with video files is the distinction between containers and codecs.

ConceptDescriptionExamples
Container (extension)A “wrapper” that holds video, audio, subtitles, etc..mp4, .mkv, .webm, .mov, .avi
Video codecCompression format for video dataH.264, H.265, VP9, AV1
Audio codecCompression format for audio dataAAC, MP3, Opus, Vorbis

Simply renaming the file extension does not convert it. For example, if an .avi file contains H.264+AAC video, you only need to “repack” it into an MP4 container (stream copy). On the other hand, converting a WebM file with VP9 video to MOV may require re-encoding the codec.


Checking Codecs (ffprobe)

Checking codecs before conversion helps you choose the right approach.

ffprobe -v error -show_streams -select_streams v:0 input.mp4
ffprobe -v error -show_entries stream=codec_name,codec_type -of default=noprint_wrappers=1 input.mkv

Commands that use only -hide_banner or -show_streams without an output file are shown in text blocks.


When to Use Stream Copy (-c copy)

If you only need to change the container (keeping the codec as-is), -c copy is the fastest option.

ffmpeg -i input.mkv -c copy output.mp4

Benefits:

Caveats and failure cases:


Common Conversion Commands

MKV → MP4 (Stream Copy)

If the MKV contains H.264+AAC, a single command converts it instantly.

ffmpeg -i input.mkv -c copy output.mp4

If the content uses a different codec and stream copy fails, re-encode instead.

ffmpeg -i input.mkv -c:v libx264 -crf 23 -c:a aac output.mp4

MOV → MP4 (iPhone / Mac Video Conversion)

MOV files recorded on iPhone or Mac almost always contain H.264/HEVC, so stream copy often works.

ffmpeg -i input.mov -c copy output.mp4

If the file contains HEVC (H.265) video and you need broad compatibility, re-encode:

ffmpeg -i input.mov -c:v libx264 -crf 22 -c:a aac output.mp4

AVI → MP4 (Converting from Legacy Format)

AVI files use a wide variety of codecs, so re-encoding is recommended for safety.

ffmpeg -i input.avi -c:v libx264 -crf 23 -c:a aac output.mp4

MP4 → MKV (Container-Only Conversion)

MKV can hold virtually any codec, so stream copy works reliably here.

ffmpeg -i input.mp4 -c copy output.mkv

MP4 → WebM (For Web Delivery)

WebM uses VP8/VP9 video and Vorbis/Opus audio as its standard. Well-suited for browser delivery.

ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus output.webm
OptionMeaning
-c:v libvpx-vp9Use VP9 encoder
-crf 30 -b:v 0Constant quality mode (CRF mode)
-c:a libopusUse Opus encoder (recommended audio for WebM)

How Automatic Codec Selection Works

Simply specifying the output container causes FFmpeg to auto-select default codecs.

ffmpeg -i input.avi output.mp4

This command automatically selects libx264 (video) and aac (audio) — the defaults for the MP4 container. However, since you have no quality control, it is recommended to explicitly specify options like -crf.


Supported Codecs by Container

ContainerCommon Video CodecsCommon Audio Codecs
MP4H.264, H.265AAC, MP3
MKVH.264, H.265, VP9, AV1, etc.AAC, MP3, Opus, FLAC, etc.
WebMVP8, VP9, AV1Vorbis, Opus
MOVH.264, H.265, ProResAAC, PCM
AVIH.264, DivX, Xvid, etc.MP3, PCM, etc.

Common Errors and Solutions

Could not write header for output file Error

This is a codec/container compatibility problem. Switch from -c copy to -c:v libx264 -c:a aac.

Encoder not found Error

The FFmpeg build you installed does not include that codec. Reinstall a full-featured build from the official site or gyan.dev (Windows).

WebM Conversion Is Extremely Slow

VP9 encoding is time-consuming. Add -cpu-used 4 to prioritize speed.



Tested with: ffmpeg 6.1.1 / Ubuntu 24.04 (GitHub Actions runner) Primary sources: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-formats.html / trac.ffmpeg.org/wiki/Encode/H.264