Dev.to WebDev 🛠 Dev 👁 0 📖 5 min read

Why your iPhone video won't play on your PC (and how a browser tab fixes it in seconds)

You AirDrop a clip from your iPhone to your laptop, double-click it, and get an error. Or sound with no picture. Or a player asking you to buy a codec. You email it to a colleague, and they can't open it either. The fil

You AirDrop a clip from your iPhone to your laptop, double-click it, and get an error. Or sound with no picture. Or a player asking you to buy a codec. You email it to a colleague, and they can't open it either.

The file isn't broken. It's speaking a language half the world's devices don't understand, and the fix takes about ten seconds without uploading the video anywhere.

TL;DR

  • iPhones record HEVC (H.265) video inside .mov files. Many PCs, Android phones, TVs and editors can't decode HEVC.
  • Renaming .mov to .mp4 does nothing. The video inside is still HEVC.
  • Fix: convert to MP4 with H.264. You can do it right in your browser (nothing is uploaded), or flip one iPhone setting so it never happens again.

First, check what's actually inside your file

A video file has two layers. The container (.mov, .mp4, .mkv) is the box. The codecs inside decide how the picture and sound are compressed. The extension only tells you about the box.

If you have FFmpeg installed, one line shows the video codec:

ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 IMG_0412.MOV
# hevc

On a Mac, Get Info shows it under More Info → Codecs. If it says hevc or H.265, you've found the culprit.

Why HEVC breaks on so many devices

Since iOS 11 (2017, iPhone 7 and later), iPhones record MOV + HEVC by default. HEVC is excellent: roughly half the size of H.264 at the same quality. But it's patent-encumbered, so support is patchy:

  • Windows doesn't play HEVC out of the box. Microsoft sells HEVC Video Extensions in the Store for about $1, because it doesn't pay HEVC royalties on every Windows licence. There's also a free HEVC Video Extensions from Device Manufacturer package from Microsoft. It just doesn't show up in a normal Store search.
  • Many Android phones, smart TVs, older laptops and video editors can't decode it.
  • Plenty of upload forms and course platforms only accept MP4.

So "my iPhone video won't play" almost always means "this device can't decode HEVC". Sometimes it means "this site only wants .mp4".

The 10-second fix: change the box, re-encode only when you must

Here's the part most "online converters" don't explain: MOV → MP4 is often not a conversion at all. If the streams are H.264 or HEVC with AAC audio, they can move into an MP4 container untouched. No quality loss, and a 400 MB clip is done in seconds.

That only fixes the box. If the device can't decode HEVC, the video itself has to be re-encoded to H.264, which every computer, phone, TV and browser plays.

Which one you need:

Your problem What to do
A site rejects .mov but your devices play it Keep the original streams: instant, lossless
PC shows sound but no picture, or "codec not supported" Re-encode HEVC → H.264
File too big for email or WhatsApp Re-encode at 1080p/720p or set a target size

A real example: IMG_0412.MOV (HEVC, 4K, 380 MB) re-encoded to 1080p H.264 comes out around 60 MB, and plays everywhere.

How a browser tab does this without uploading anything

Until recently, converting video meant sending it to a server running FFmpeg. Browsers now ship WebCodecs: direct access to the device's own encoders and decoders, usually hardware-accelerated. You can ask the browser up front what it can produce:

const { supported } = await VideoEncoder.isConfigSupported({
  codec: 'avc1.640028', // H.264 High profile
  width: 1920,
  height: 1080,
});

On 4Dev.Net I pair WebCodecs with Mediabunny, which reads and writes the containers. The core is a few lines:

const input = new Input({ source: new BlobSource(file), formats: ALL_FORMATS });
const output = new Output({ format: new Mp4OutputFormat(), target: new BufferTarget() });
const conversion = await Conversion.init({ input, output }); // streams kept as they are when they fit
await conversion.execute();

That maps directly to the table above:

  • Keep original quality: streams go into the MP4 unchanged. Fastest, and enough when the problem is just the .mov extension.
  • High, Medium or Low: the video is re-encoded, and HEVC becomes H.264. This is the fix for the PC with sound and no picture.
  • Trim or set a target size in MB to make it fit an email or chat app.

Everything runs in the tab, so the video never leaves your device. That matters more than it sounds: the clip is often your kids, your home, or something you don't want sitting on a stranger's server. The limit is 500 MB per file, because the result is built in memory.

👉 Try it on one of your own MOV files. Drag it in, pick High, done.

Stop it happening again: one iPhone setting

Settings → Camera → Formats → Most Compatible makes the iPhone record H.264 instead of HEVC. The files are bigger, so many people keep HEVC and convert only the videos they share.

Same root cause, same trick: HEIC photos

iPhone photos have the same problem. They're saved as HEIC, which is also based on HEVC, and plenty of PCs, Android phones and upload forms reject them.

Safari decodes HEIC natively; Chrome, Firefox and Edge don't. So the site loads libheif compiled to WebAssembly, only when someone opens a HEIC file in a browser that needs it. It sniffs the real format from the file header instead of trusting the extension:

// Bytes 8-11 of an ISO-BMFF file hold the major brand.
const brand = new TextDecoder().decode(bytes.subarray(8, 12));
if (/^(heic|heix|hevc|hevx|heim|heis|mif1|msf1)$/.test(brand)) return 'heic';

Decoding runs in a Web Worker, so a 48-megapixel photo doesn't freeze the page. You can convert up to 50 photos at once into one ZIP. Location data from the HEIC isn't carried into the JPG, so sharing the photo doesn't share where you took it. 👉 HEIC to JPG

What else runs entirely in the tab

The same "nothing leaves your device" approach powers the rest of the site:

  • PDF to Word. PDF.js reads the PDF, a layout pass rebuilds paragraphs, real tables and headers/footers, and a hand-written OOXML writer produces the .docx. Hebrew and Arabic stay right-to-left.
  • MP4 to MP3, using a LAME encoder compiled to WASM (64–320 kbps).
  • Developer tools: JSON ↔ CSV/YAML/TypeScript, cURL to code, a regex tester, a JWT decoder, hashes, cron explained, timestamps and more.

The takeaway

  • If a video won't play, suspect the codec, not the file. Renaming the extension changes nothing.
  • Changing the container is instant and lossless. Re-encode to H.264 only when a device can't play HEVC.
  • Your browser can now do this on your own machine. Private videos don't need to be uploaded anywhere.

Next time a clip shows sound and no picture, you'll know it isn't broken, just speaking HEVC. Fix your first video here.

Have you hit a device or app that still won't play the result? Tell me in the comments. I'm collecting the edge cases.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.