/compat/ffmpeg/ffmpeg-codecs-containers
Which codec in which container? MP4, WebM, MKV, MOV with FFmpeg
verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · ffmpeg version 9.0.2-full_build-www.gyan.devupdated 2026-10-20
- tool
- FFmpeg
- versions
- FFmpeg 9.0
- os
- any
A container (MP4, WebM, MKV, MOV) is a wrapper; the codec inside decides the format of the audio and video data. FFmpeg 9 writes H.264, H.265, VP9 and AV1 video and AAC, MP3, Opus, Vorbis, FLAC and PCM audio into MP4; WebM accepts only VP8, VP9 and AV1 video and Vorbis or Opus audio; MKV holds almost any codec.
Tested with FFmpeg 9.0
Each cell below is the result of encoding a short generated stream into that container:
for c in libx264:mp4 libx264:webm libx264:mkv libvpx-vp9:mp4 libvpx-vp9:webm libaom-av1:mp4 libsvtav1:webm \
aac:mp4 aac:webm libopus:mp4 libopus:webm libmp3lame:mp4 libvorbis:mp4 flac:mp4 pcm_s16le:mp4 pcm_s16le:mov; do
codec=${c%%:*}; ext=${c##*:}
case $codec in
aac|libopus|libmp3lame|libvorbis|flac|pcm_s16le) src="-f lavfi -i sine=duration=0.5"; opt="-c:a $codec" ;;
*) src="-f lavfi -i testsrc=size=64x64:duration=0.5"; opt="-c:v $codec" ;;
esac
if ffmpeg -hide_banner -loglevel quiet $src $opt -y "t.$ext"; then r=ok; else r=rejected; fi
printf '%-11s in %-5s %s\n' "$codec" "$ext" "$r"
doneOutput
libx264 in mp4 ok libx264 in webm rejected libx264 in mkv ok libvpx-vp9 in mp4 ok libvpx-vp9 in webm ok libaom-av1 in mp4 ok Svt[info]: ------------------------------------------- Svt[info]: SVT [version]: SVT-AV1 Encoder Lib v4.2.0-123-g0c1c4deca Svt[info]: SVT [build] : GCC 16.2.0 64 bit Svt[info]: LIB Build date: Sep 13 2026 12:03:46 Svt[info]: ------------------------------------------- Svt[info]: Level of Parallelism: 4 Svt[info]: Number of PPCS 107 Svt[info]: [asm level on system : up to avx2] Svt[info]: [asm level selected : up to avx2] Svt[info]: ------------------------------------------- Svt[info]: SVT [config]: main profile tier (auto) level (auto) Svt[info]: SVT [config]: width / height / fps numerator / fps denominator : 64 / 64 / 25 / 1 Svt[info]: SVT [config]: bit-depth / color format : 8 / YUV420 Svt[info]: SVT [config]: preset / tune / pred struct : 8 / PSNR / random access Svt[info]: SVT [config]: gop size / mini-gop size / key-frame type : 161 / 32 / key frame Svt[info]: SVT [config]: BRC mode / rate factor : CRF / 35.00 Svt[info]: SVT [config]: AQ mode / Variance Boost : 2 / 0 Svt[info]: SVT [config]: sharpness / luminance-based QP bias : 0 / 0 Svt[info]: SVT [config]: QP scale compress strength : 0 Svt[info]: ------------------------------------------- libsvtav1 in webm ok aac in mp4 ok aac in webm rejected libopus in mp4 ok libopus in webm ok libmp3lame in mp4 ok libvorbis in mp4 ok flac in mp4 ok pcm_s16le in mp4 ok pcm_s16le in mov ok
Summary
| Codec | MP4 | WebM | MKV | Browser playback |
|---|---|---|---|---|
| H.264 (libx264) | yes | no | yes | MP4: all major browsers |
| VP9 (libvpx-vp9) | yes | yes | yes | WebM: all major browsers |
| AV1 (libaom-av1, libsvtav1) | yes | yes | yes | recent browsers |
| AAC | yes | no | yes | MP4: all major browsers |
| Opus | yes | yes | yes | WebM and MP4 in recent browsers |
| MP3 | yes | no | yes | yes |
| PCM (WAV audio) | yes | no | yes | no (in MP4) |
The MP4 and WebM columns for H.264, VP9, AV1, AAC, Opus and PCM are from the test above; the MKV and browser columns come from the Matroska codec list and browser documentation.
Sources
Related pages
errors · ffmpegffmpeg: Unknown encoder 'libx264' (Encoder not found)ffmpeg prints Unknown encoder when the codec name is misspelled or the build lacks that library, such as libx264 or libfdk_aac. List them with -encoders.commands · ffmpegffmpeg: extract audio from a video (with and without re-encoding)Extract audio with ffmpeg -i input.mp4 -vn -c:a copy audio.m4a without re-encoding, or make an MP3 with -c:a libmp3lame -q:a 2. Check codecs with ffprobe.compare · ffmpegffmpeg -c copy vs re-encoding: speed, quality and limits-c copy remuxes streams without decoding: fast and lossless, but cuts snap to keyframes and filters are impossible. Re-encoding is slower, lossy, flexible.