You build an upload form, add a nice preview with URL.createObjectURL(file) in a <video> tag, and test it with an MP4 from your phone. Works great. Then support tickets arrive: "the preview is black", "it says the file is broken", "the upload button never activates".
The file usually isn't broken. It is in a container or codec the browser simply does not decode. Here's how I deal with it.
What browsers actually play
Roughly, across current Chrome, Firefox and Safari:
| Container | Typical codecs | Plays in <video>? |
|---|---|---|
| MP4 | H.264 + AAC | Yes, everywhere |
| WebM | VP8/VP9/AV1 + Opus | Yes (Safari: recent versions) |
| MOV | H.264/HEVC | Often, HEVC depends on OS/hardware |
| MKV | anything | Chrome sometimes, Safari no |
| AVI, WMV, 3GP, MTS/M2TS, FLV | DivX, WMV9, H.263, AMR, AC-3… | Usually no |
Old phones (3GP with AMR audio), Windows Movie Maker exports (WMV), camcorders (MTS/AVCHD) and screen recorders from 2010 (AVI) are exactly what non-technical users find in their archives.
Step 1: detect failure honestly
Don't rely on the file extension or file.type (it is often empty for MTS). Try to load it and listen:
function canPreview(file) {
return new Promise(resolve => {
const v = document.createElement('video');
v.muted = true; v.preload = 'metadata';
const url = URL.createObjectURL(file);
const done = ok => { URL.revokeObjectURL(url); resolve(ok); };
v.onloadeddata = () => done(v.videoWidth > 0);
v.onerror = () => done(false);
setTimeout(() => done(false), 4000);
v.src = url;
});
}
Note the videoWidth > 0 check: some browsers load audio from a file whose video codec they can't decode, giving you a black frame with sound.
Step 2: decide where to convert
Options, from cheapest to most robust:
- Accept and convert server-side with ffmpeg. Most reliable, but you pay for compute and you now store users' family videos.
- Convert client-side with ffmpeg.wasm. No server cost and better privacy, but slow on phones and memory-limited for files over ~2 GB.
- Ask the user to convert first, with a clear message and a link to a tool.
For many products, option 3 is the pragmatic first step. A precise message beats a black rectangle:
"This video is in WMV format, which browsers can't preview. Convert it to MP4 first, then upload it again."
Step 3: write the message per format
Generic "unsupported format" errors make users think their file is damaged. Name the format and the fix. For the conversion link I point people to Nibbo's video converter, which turns AVI, WMV, 3GP, MTS and friends into MP4 in the browser without uploading the file anywhere, so I'm not sending users' videos to yet another third party.
Step 4: still accept the original if you can
If your backend transcodes anyway, let the upload proceed without a preview and show a thumbnail placeholder instead. Blocking the upload just because the preview failed is the worst outcome.
Summary
- Probe playability with a real
<video>element, checkvideoWidth. - Never trust
file.typefor legacy containers. - Name the format in the error and give a concrete fix.
- Don't block the upload on preview failure.
— Vitalii
Top comments (0)