DEV Community

Cover image for Why Your MP4 Won't Play After Converting from MOV
Noah Chen
Noah Chen

Posted on AI-assisted

Why Your MP4 Won't Play After Converting from MOV

An .mp4 filename tells you little about the decoder a video needs. An export can have a valid MP4 container and still carry a video profile, pixel format, or audio stream that a particular player cannot handle. Before converting the file again, inspect the streams and identify what actually changed.

This walkthrough uses a short, reproducible test to separate three operations: changing the container, re-encoding the video, and choosing MP4 in an online converter. It is part of a VideoBee promotional campaign, prepared with AI; the file measurements and commands below were checked locally on October 27, 2026.

Start with the streams, not the extension

MDN's container guide explains how a container packages media tracks. The video codec, codec profile, pixel format, audio codec, and the target playback environment are additional pieces of the compatibility question.

Run this against the exported file:

ffprobe -v error \
  -show_entries stream=index,codec_name,profile,pix_fmt,width,height \
  -show_entries format=format_name,duration \
  -of json output.mp4
Enter fullscreen mode Exit fullscreen mode

For example, codec_name: h264 does not settle the issue. A High 4:4:4 Predictive stream with pix_fmt: yuv444p differs from a High stream with pix_fmt: yuv420p. Check the decoder requirements of the device or browser where playback fails. Do not infer its capabilities from what works on your development machine.

Also inspect the audio stream. A silent clip and a clip that cannot be decoded at all need different investigations.

A controlled MOV-to-MP4 test

The source was MDN's public CC0 flower video. I used FFmpeg to make a deliberately specific test fixture: a MOV containing H.264 High 4:4:4 Predictive video at 960 × 540, plus AAC audio. This is a constructed fixture, not a claim about the default output of an iPhone or camera.

ffmpeg -i flower.mp4 \
  -c:v libx264 -pix_fmt yuv444p -profile:v high444 -crf 18 \
  -c:a aac input-444.mov
Enter fullscreen mode Exit fullscreen mode

Four files were inspected with ffprobe and fully decoded with FFmpeg:

File Operation Video profile Pixel format Bytes
input-444.mov Constructed source High 4:4:4 Predictive yuv444p 870,866
remuxed.mp4 Copy the streams into MP4 High 4:4:4 Predictive yuv444p 870,816
transcoded.mp4 Explicit local re-encode High yuv420p 640,761
videobee.mp4 VideoBee, MP4 output with default settings High 4:4:4 Predictive yuv444p 446,524

Measured profiles and pixel formats in four variants of the same short video.

Results from one constructed 960 × 540 sample. Both local MP4 variants played in the test Chrome 138 Linux environment; this table is not a universal device compatibility rating.

The important observation is that MP4 output did not necessarily change the profile or pixel format. File size also failed as a shortcut: the smallest output in this test still used 4:4:4.

Both local MP4 variants played in the Chrome 138 Linux environment used for the browser check. That is useful evidence about that environment, but it is not a reproduction of a failing phone or television. The test demonstrates stream preservation and explicit conversion; a compatibility claim still needs a check on the actual target device.

Use stream copying when the codecs already fit

When the destination accepts the existing streams and only the container needs changing, a remux avoids another generation of video encoding. This command produced the second row above:

ffmpeg -i input-444.mov \
  -map 0:v:0 -map '0:a:0?' \
  -c copy -movflags +faststart remuxed.mp4
Enter fullscreen mode Exit fullscreen mode

The optional audio mapping handles an input without an audio track. It also deliberately selects only the first video and first audio stream; it does not promise to preserve every subtitle, alternate soundtrack, or metadata track.

FFmpeg's stream-copy documentation describes why copying compressed packets does not perform a decode-and-encode cycle. If the original stream is the reason playback fails, copying it into another container leaves that problem in place.

Re-encode the properties you need to change

For a conventional H.264/AAC delivery copy with 4:2:0 pixels, make those choices explicit:

ffmpeg -i input-444.mov \
  -map 0:v:0 -map '0:a:0?' \
  -c:v libx264 -preset medium -crf 20 -pix_fmt yuv420p \
  -c:a aac -b:a 128k \
  -movflags +faststart transcoded.mp4
Enter fullscreen mode Exit fullscreen mode

That command produced the High / yuv420p row in the table. The quality setting is a starting point, not a file-size target. Inspect the result, especially if the clip contains small text, gradients, or motion.

For older or tightly constrained decoders, you may also need a suitable profile, level, frame size, and frame rate. Choose them from the target's requirements instead of assigning one preset to every device. HDR, wide-gamut color, rotation, and multiple tracks deserve their own checks; a generic SDR command is not a complete preservation workflow.

The faststart option changes the placement of MP4 metadata to help progressive playback. It does not make an unsupported video codec supported.

Where an online converter fits

For a one-off file, VideoBee's video converter provides an upload-and-export workflow without requiring a local FFmpeg installation. In this test, I uploaded input-444.mov, left the output at MP4, ran the conversion, and downloaded the result without signing in.

The exported file was valid and smaller, but it retained the source's H.264 4:4:4 profile and pixel format. That makes the same diagnostic rule useful with a graphical tool: inspect the downloaded file rather than assuming what an MP4 selector means internally. When a delivery specification explicitly requires yuv420p, use a workflow that exposes that choice and verify the output.

Separate file failures from delivery failures

If the file decodes locally but fails inside a website, test the delivery path too. Inspect the request status, Content-Type, redirects, and whether the response is actually media bytes rather than an HTML login or error page. If a browser reports a media error, capture its code and the network request that preceded it.

A useful bug report includes the input and output probe results, the exact conversion settings, the failing player and operating system, and a small non-sensitive sample. That evidence lets you change the failing layer without repeatedly converting a file that was already valid.

Top comments (0)