Video containers vs codecs: why your MP4 won’t play

“It’s an MP4, why won’t it play?” — because the extension tells you almost nothing about the video. A video file is a box (the container) holding streams encoded with particular codecs, and a player can fail on either layer. Once you can tell which layer is failing you can read any playback error, predict whether a conversion will take ten seconds or an hour, and pick the fix that does not throw away quality. This guide gives you the model, the byte signatures and commands that reveal what a file really contains, and the traps that catch people who skip the diagnosis.

Containers: the box

The container (.mp4, .mkv, .mov, .webm, .avi) is a filing system. It interleaves the video stream, one or more audio streams, subtitles and metadata, and it holds the index a player needs to seek. In MP4 that index is the moov box, and a file whose moov sits at the end cannot start playing over a network until the whole thing has downloaded. MP4 (ISO/IEC 14496-14) is the universal citizen — phones, browsers, TVs, editors. MOVis Apple’s QuickTime format, the older sibling MP4 was derived from; the two share the same box structure and differ mostly in which codecs they will carry (MOV also takes ProRes and uncompressed PCM audio). MKV (Matroska) is the flexible open one — any codec, any number of tracks, chapters, embedded fonts — beloved for archives and media servers, refused by iPhones and many TVs. WebM is a Matroska subset that Google restricted to royalty-free codecs (VP8, VP9 or AV1 video with Vorbis or Opus audio) so browsers could support it without licence fees. AVIis Microsoft’s 1992 RIFF-based format: no proper home for modern codecs, subtitles or variable frame rates, yet it keeps turning up from old cameras and screen recorders.

Codecs: what is inside the box

The codec is the compression algorithm for the pictures themselves, and it is where the real engineering lives. H.264/AVC (2003) decodes in hardware on essentially everything made in the last fifteen years — the safe choice. H.265/HEVC (2013) needs roughly half the bits for the same picture but has patchy support outside Apple hardware: Windows typically decodes it only after the HEVC Video Extensions are installed from the Microsoft Store, and Chrome only when the operating system supplies a decoder. VP9is Google’s royalty-free answer to HEVC — YouTube serves much of its catalogue in it — and AV1 (2018) is the newer royalty-free standard from the Alliance for Open Media: better compression again, hardware decoders in most chips from about 2020 (Intel Tiger Lake, NVIDIA 30-series, MediaTek Dimensity) but in Apple silicon only from the A17 Pro and M3, and slow to encode in software. Within a codec there are also profiles: an H.264 file in the High 10 profile (10-bit colour) stalls the hardware decoders in most phones and TVs even though “H.264” is on the box.

Audio has its own codecs. AAC is the universal partner for MP4 and MOV; MP3 plays everywhere too; Opus and Vorbis belong to WebM; AC-3 (Dolby Digital) and DTS come from discs and MKV rips and are exactly the tracks browsers cannot decode. A file whose picture plays fine but stays silent almost always has one of those last two inside.

Which container will hold what

ContainerVideo codecs it acceptsAudio codecsSubtitlesPlays in a browser <video> tag
MP4H.264, HEVC, AV1, MPEG-4 Part 2AAC, MP3, AC-3, Opus, ALACTimed text (mov_text) onlyYes — H.264/AAC everywhere; HEVC and AV1 only where the device has a decoder
MOVEverything MP4 takes, plus ProRes, DNxHDAAC, PCM, ALACQuickTime textUsually, if the codecs are H.264/AAC; Safari is the most forgiving
MKVAnything — H.264, HEVC, VP9, AV1, MPEG-2, even ProResAnything — AAC, AC-3, DTS, FLAC, Opus, VorbisSRT, ASS/SSA, PGS, VobSubNot officially; Chrome opens some, Safari and Firefox refuse
WebMVP8, VP9, AV1 onlyVorbis, Opus onlyWebVTT (rarely used)Chrome, Firefox, Edge; Safari from 14.1 on the Mac and on recent iPhones
AVIMPEG-4 Part 2 (DivX/Xvid), MJPEG, H.264 awkwardlyMP3, PCM, AC-3None (external .srt)No

Read the table row by row and most conversion questions answer themselves. MKV to MP4 is usually a container swap, because H.264 and AAC fit both. MKV to WebM is always a re-encode unless the source is already VP9 or AV1. An MKV with DTS audio cannot go into MP4 unchanged: the audio has to be re-encoded, normally to AAC, while the video is copied across untouched.

Why this explains your playback error

A player must understand bothlayers, and the two failures look different. A TV that “supports MP4” may support only H.264 inside it — hand it an MP4 containing HEVC and you get a black screen or an error, even though the extension looks right. On Windows the message is Can’t play. This item was encoded in a format that’s not supported. 0xc00d5212: the container opened fine, the codec did not. An MKV, by contrast, often fails on a device not because of its codecs (H.264/AAC, perfectly supported) but because the device refuses the container — QuickTime Player says The file isn’t compatible with QuickTime Player before it has looked at a single frame. Same symptom, different layer, different fix.

Browsers make the layer visible if you know where to look. In Chrome, chrome://media-internals logs DEMUXER_ERROR_COULD_NOT_OPEN when the container cannot be parsed and DEMUXER_ERROR_NO_SUPPORTED_STREAMS: FFmpegDemuxer: no supported streams when the container is fine but none of the codecs inside are; a script reading video.error.code sees 4 (MEDIA_ERR_SRC_NOT_SUPPORTED) in both cases. Firefox shows No video with supported format and MIME type found for the container case and Video can’t be played because the file is corrupt — misleading, but reliable — for the codec case.

One further trap hides inside MP4 itself. HEVC can be labelled hvc1 or hev1, and Apple software plays only hvc1. An MP4 that ffmpeg produced with its default tag plays in VLC and refuses in Safari, QuickTime and iMovie with no explanation. Re-tagging (-tag:v hvc1) is a remux, not a re-encode.

How to tell which case you are in

Start with the bytes, because extensions lie — a renamed file keeps its real signature. Run xxd -l 16 input.mp4 (or Format-Hex -Path .\input.mp4 -Count 16 in PowerShell) and match the leading bytes against this list:

offset  bytes                                  ascii            container
4       66 74 79 70 69 73 6f 6d                ftypisom         MP4 (brands isom, mp42, avc1, M4V)
4       66 74 79 70 71 74 20 20                ftypqt           MOV
0       1a 45 df a3                            .E..             MKV or WebM (DocType "matroska" or "webm" follows within ~40 bytes)
0       52 49 46 46 .. .. .. .. 41 56 49 20    RIFF....AVI      AVI
0       46 4c 56 01                            FLV.             FLV
0       47  (and again at 188, 376, ...)       G                MPEG transport stream (.ts, .mts, .m2ts)

The file command on macOS and Linux does the same lookup in words: ISO Media, MP4 Base Media v1, Matroska data, WebM, RIFF (little-endian) data, AVI.

Then read the streams. Windows Explorer’s Details tab lists frame size and bit rate but never the codec, so use a tool that does:

ffprobe -v error -show_entries stream=index,codec_type,codec_name,profile,pix_fmt,codec_tag_string -of default=noprint_wrappers=1 input.mp4

A line such as codec_name=hevc with codec_tag_string=hev1 explains a Mac failure on its own; pix_fmt=yuv420p10le flags 10-bit video that TV decoders reject; codec_name=ac3 or dts on the audio stream predicts silence in a browser. Without a terminal, open the file in VLC and press Ctrl+J (Cmd+I on a Mac) for the Codec Information panel, or run MediaInfo. Then match the symptom to the layer:

SymptomFailing layerFix
Player refuses to open the file at all; iPhone shows it greyed outContainerRemux into MP4 — nothing is re-compressed
File opens, audio plays, picture is black or frozenVideo codec (HEVC, AV1 or 10-bit H.264)Re-encode the video to H.264; copy the audio
Picture plays, no soundAudio codec (AC-3, DTS)Re-encode only the audio to AAC; copy the video
Plays in VLC, not in Safari or on an iPhoneHEVC tagged hev1, or an MKVRe-tag as hvc1, or remux into MP4
Plays on a Mac, not on WindowsHEVCInstall the HEVC extension, or re-encode to H.264
Starts instantly from disk, takes ages over the networkmoov index at the end of the MP4Remux with faststart

Remux vs re-encode: seconds vs hours

This is where the model pays off. If only the container is wrong (MKV with H.264 inside, device wants MP4), the streams can be moved into a new box unchanged — a remux. The work is copying bytes, so a 2 GB file takes about as long as reading and writing 2 GB, and quality is untouched because nothing is decompressed. If the codec is wrong (HEVC, device needs H.264), every frame must be decoded and encoded again — a re-encode. A ten-minute clip at 30 frames per second is 18,000 frames, and at 4K each of them is 8.3 million pixels; that is why the same file can take seconds one way and an hour the other, and why every re-encode costs a little quality.

With ffmpeg on a desktop the remux is one line, and the flags people forget are the ones that fix the most common complaints:

ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -c copy -movflags +faststart output.mp4
# HEVC source bound for Apple devices: add    -tag:v hvc1
# AC-3 or DTS audio: replace -c copy with     -c:v copy -c:a aac

Which route the converters on this site take

The MP4, MKV, MOV and WebM converters make the same remux-or-re-encode decision, and you can predict it. When you drop a file the page probes it twice: a hidden <video>element reads the frame size and duration, and the conversion engine asks the browser’s WebCodecs decoder whether it can decode the primary video track. That answer, the two containers and the options you set decide the route:

You dropRouteWhat happens to the streamsLimits
MP4, MOV, MKV, WebM, 3GP or MPEG-TS (.ts, .mts, .m2ts) whose video codec the browser decodes; target MP4, MOV, MKV or WebM; resolution on “Keep original”, target size blank, Compress untickedHardware, in memoryTracks the target container accepts are copied unchanged — a remux, so an HEVC MOV becomes an HEVC MP4 in seconds. Only a track the target refuses (H.264 into WebM) is re-encoded. moov is written up front.Output is built in one browser buffer; the file auto-downloads
The same, with a resolution, a target size or Compress tickedHardware re-encodeVideo goes through your device’s encoder at full size — a 4K source stays 4K, and the dialog says so: “High-resolution source — converts at original size using your device’s hardware encoder.” Compress aims at about 3 Mbps for 1080p H.264, scaled with the pixel count.As above
The same, but the file is over 1.5 GiB, in Chrome or EdgeHardware, streamed to diskA save dialog opens first and the result streams straight into the file you chose, so it never has to fit in memory. A size budget gets one pass, no overshoot correction, and moov lands at the end.Needs the File System Access API; other browsers use the in-memory route
AVI, FLV or WMV; a codec the browser cannot decode; or a GIF, AVI or FLV targetffmpeg.wasm fallbackAlways a re-encode: libx264 for MP4, MOV and MKV, VP8 with Opus for WebM, audio to AAC for MP4 and MOV. moov lands at the end.Fixed 1 GiB heap: “output is capped at 1080p for in-browser conversion on this device”; cannot load files above about 2 GB

Two consequences are easy to miss. First, the hardware route is gated on decoding even when a remux would not need to decode anything: on a Windows PC without the HEVC extension the browser reports that it cannot decode HEVC, so an HEVC MOV that remuxes in seconds on a Mac takes the ffmpeg route there and comes back as H.264, capped at 1080p. Second, only the in-memory hardware route writes the moov box first; a streamed or ffmpeg-produced MP4 needs the -movflags +faststart remux above before it goes on a web server. Whatever the route, the output is named <name>_output.<ext>, and a failure shows one message — “Conversion failed. The file may be unsupported, corrupted, or too large to process in this browser.” — whose three causes map onto the diagnosis above. Nothing is uploaded on any route; how the on-device tools work explains the machinery.

Audio follows its own rules on the hardware route. The engine knows AAC, Opus, MP3, Vorbis, FLAC, AC-3, E-AC-3 and PCM, so an AC-3 track from a disc rip is copied into MP4, MOV or MKV untouched — which keeps the sound in VLC and still leaves Chrome or Firefox silent, because no browser decodes AC-3. DTS is not on that list and is dropped on every hardware-route conversion; AC-3 is dropped too when the target is WebM or a size budget forces the audio through a re-encode the browser cannot start. The large-file route says so in its result card — “note: the audio couldn’t be converted and was left out” — while the in-memory route simply hands you a silent file. The ffmpeg fallback, by contrast, re-encodes whatever audio it finds to AAC.

Common mistakes

  • Renaming .mkv to .mp4. The extension is a hint for the operating system, not the container; the first bytes still say 1A 45 DF A3 and the player still refuses. Remux instead.
  • Remuxing HEVC into MP4 and expecting Windows to play it. The container changed; the codec did not. That MP4 still needs the HEVC extension or a re-encode to H.264 — and if you convert on the Windows machine itself, the converter has already made that choice for you, as the route table shows.
  • Copying an MKV with subtitles into MP4. MP4 carries only timed text, so ffmpeg stops with Could not find tag for codec subrip in stream #0:2, codec not currently supported in container. Convert them with -c:s mov_text or leave them out with -sn.
  • Ignoring the audio codec. DTS vanishes on the hardware route; AC-3 survives the conversion and then plays nowhere in a browser. Check codec_name on the audio stream before you start, and if it says ac3 or dts, plan on the desktop -c:a aac line above.
  • Setting a target size on a screen recording. Browsers’ MediaRecorder writes WebM with no duration (a player reports Infinity), and the size budget is bits divided by seconds. With no duration the field is silently ignored and the file converts at normal quality. Pick a resolution instead — that lever needs no duration.
  • Re-encoding HEVC to H.264 to “compress” it. H.264 needs up to twice the bits for the same picture, so the file grows. Compress by lowering the resolution or setting a size budget, and keep HEVC if the destination decodes it.
  • Compressing the compressed. Every re-encode re-quantises the picture; three rounds of convert, compress, convert back leave blocky shadows. Keep the original and export from it once.

Quick answers

Video must play everywhere: MP4 with 8-bit H.264 + AAC — convert to MP4. iPhone, WhatsApp or a TV refuses your file: same answer, H.264 MP4; the iPhone video guide covers the HEVC MOV case. Need a moment from a long recording: trim it — the trimmer runs ffmpeg’s stream copy (-ss start -to end -c copy), so it finishes in seconds with no quality loss, at the cost of cuts landing on the nearest keyframe. Only the audio matters: extract the audio, which starts the moment you drop the file and saves an audio-only MP4 (AAC) — rename it .m4a if a player is fussy, it is the same container; for an MP3 use the MP3 converter, which accepts video files directly and encodes with LAME at -q:a 2. Web page background clip: WebM (convert) with an MP4 fallback — WebM vs MP4 covers the source-order details. A short silent loop for chat: GIF, kept to a few seconds at 360p or 480p, because GIF stores 256 colours per frame with no inter-frame compression.

File too large to send: compress it. The Compress box uses x264’s default quality, CRF 23, on the ffmpeg route, and the “Target file size (MB)” field turns a budget into a bitrate: 93% of the budget, minus 128 kbps reserved for audio, divided by the duration. When that bitrate is too thin for the frame size it steps the resolution down — below 4 Mbps it caps at 1080p, below 1.5 Mbps at 720p, below 700 kbps at 480p — and re-encodes once more if the first result overshoots, then hands the job to x264’s strict rate control if a hardware encoder still ignores the budget. A 25 MB cap on a 60-second clip works out at about 3.1 Mbps for video, so a 4K source comes out at 1080p. Lowering the resolution on its own (360p to 1080p) is the other big lever, and the only one that works on a file with no duration.

Do this

  • Diagnose before converting: xxd or file for the container, ffprobe or VLC (Ctrl+J) for the codecs.
  • Container wrong, codecs fine: remux. Never re-encode what you can copy.
  • Must play everywhere: 8-bit H.264 + AAC in MP4, with -movflags +faststart if it will be streamed.
  • HEVC for Apple: tag it hvc1. HEVC for Windows: install the extension or re-encode to H.264.
  • Picture fine, no sound: re-encode just the audio to AAC.
  • Keep the original and export copies from it; never re-compress an export.

Frequently asked questions

What is the difference between a video container and a codec?

The container (MP4, MKV, MOV, WebM, AVI) is the file wrapper: it stores the video stream, the audio streams, subtitles and the index a player uses to seek. The codec (H.264, HEVC, VP9, AV1 for video; AAC, Opus, AC-3 for audio) is the compression scheme used for each stream inside it. A player has to support both layers, which is why a file can be a perfectly valid MP4 and still refuse to play.

Why won’t my MP4 play on Windows when it plays fine on a Mac?

Almost always because the video inside is HEVC (H.265), which iPhones and Macs decode natively but Windows only decodes once the HEVC Video Extensions are installed from the Microsoft Store. The typical message is “Can’t play. This item was encoded in a format that’s not supported. 0xc00d5212”. Re-encoding to an H.264 MP4 fixes it on every device.

Can I convert MKV to MP4 without losing quality?

Yes, when the codecs inside the MKV are ones MP4 accepts — H.264 or HEVC video with AAC audio. The streams are then copied into the new container unchanged (a remux), which takes seconds and loses nothing. Only when a codec has to change, for example DTS audio to AAC or HEVC to H.264, is the stream actually re-compressed.

Why does my converted video have no sound?

The audio track used a codec the player or converter could not handle, so it was skipped or carried across in a form the player cannot decode. AC-3 and DTS from MKV rips are the usual culprits — no browser decodes either. Check the audio stream’s codec_name with ffprobe or VLC, then re-encode just the audio to AAC while copying the video.

Which video format plays on every device?

MP4 with 8-bit H.264 video and AAC audio. It is decoded in hardware on essentially every phone, TV, browser and laptop made since about 2010, which is why it remains the safe delivery format even though HEVC and AV1 compress better.

Tools used in this guide

Every one of these runs in your browser — the files you work on never leave your device.

More video guides