Your HEVC MP4 Won't Play on Apple: The FFmpeg hvc1 Tag Fix

Your HEVC file plays fine in VLC. In Safari you get a black player, in Finder you get a generic gray icon instead of a thumbnail, and somewhere in a pipeline log there's a line reading Could not find tag for codec hevc in stream #0. The video data is intact. Four bytes of container metadata are wrong.
Quick answer: FFmpeg's libx265 encoder writes HEVC into MP4 with thehev1sample entry by default, and Apple's AVFoundation stack (Safari, QuickTime, Finder thumbnails, QuickLook) only decodes HEVC taggedhvc1. Fix it without re-encoding by remuxing with the FFmpeg hvc1 tag:ffmpeg -i in.mp4 -c copy -tag:v hvc1 out.mp4. That rewrites the container box only, so it finishes in under a second on a 100 MB file with zero quality loss, and the same command fixes the "Could not find tag for codec" error when you're muxing raw HEVC into MP4.
Why hev1 and hvc1 are the same video with different packaging
The hev1 and hvc1 four-character codes both describe HEVC video inside an ISO Base Media File Format container, and they differ only in where the decoder parameter sets live. With hvc1, the VPS, SPS, and PPS parameter sets sit in the sample description box in the file header, so a player knows how to configure its decoder before reading a single frame. With hev1, those parameter sets are allowed to appear inline in the bitstream and change mid-stream, which is useful for live streaming and hostile to a player that wants to set up a hardware decoder once and be done.
Apple picked the strict option. AVFoundation, the framework behind Safari, QuickTime Player, Finder's thumbnail generator, and QuickLook, refuses hev1 outright. VLC, mpv, and Chrome on Windows use their own software decode paths and don't care, which is exactly why the file looks fine on your machine and broken on the client's.
FFmpeg's MP4 muxer defaults to hev1 when it takes HEVC from libx265. So a file you encoded with a perfectly reasonable command is unplayable on roughly every Apple surface a normal person touches.
You'll see the confusion play out in downstream trackers rather than in FFmpeg's own docs. PhotoPrism has an open issue (#5593) asking to tag HEVC remux output hvc1. The compressO project logged issue #122 specifically about hev1 breaking macOS thumbnails and QuickLook. LosslessCut has carried the same complaint in issues #33 and #231 for years. Apple's own developer forums (threads 79048 and 651262) answer it repeatedly. None of that is documented where you'd look first.
Fix it with a metadata-only remux
The repair for an already-encoded file is a stream copy with an explicit video tag, which touches the container and leaves every compressed frame byte-identical.
ffmpeg -i broken.mp4 -c copy -tag:v hvc1 -movflags +faststart fixed.mp4
Three things are doing work here. -c copy means no decode and no re-encode, so quality is untouched and the job is I/O bound. -tag:v hvc1 overrides the muxer's default sample entry. -movflags +faststart moves the moov atom to the front, which matters if the file is going to be streamed over HTTP. On a 100 MB clip this runs in well under a second on a laptop, because FFmpeg is copying bytes and rewriting a header, not encoding anything.
Verify the change instead of trusting it. ffprobe prints the tag:
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,codec_tag_string \
-of default=noprint_wrappers=1 fixed.mp4
codec_name=hevc
codec_tag_string=hvc1
If that still says hev1, your FFmpeg silently ignored the tag, which usually means the output container wasn't MP4 or MOV. Matroska has no concept of these tags at all, so -tag:v hvc1 on a .mkv output is a no-op.
To get it right at encode time and skip the second pass entirely, set the tag on the original command:
ffmpeg -i source.mov -c:v libx265 -crf 23 -preset medium \
-tag:v hvc1 -c:a aac -b:a 128k -movflags +faststart out.mp4
Make that flag a permanent part of every libx265-to-MP4 template you own. There's no downside for VOD delivery, and forgetting it is the single most common way a good HEVC encode becomes a support ticket.
What "Could not find tag for codec" actually means
The error Could not find tag for codec hevc in stream #0, codec not currently supported in container is the same problem seen from the muxer's side rather than the player's. FFmpeg raises it when you feed it HEVC and ask for a container or a muxer variant that has no registered four-character code for that codec. The quasarstream/PHP-FFmpeg-video-streaming project collected a long thread on it (issue #48), and the reports there split into two causes.
The first is an old FFmpeg build. HEVC-in-MP4 tag support landed years ago, but distro packages lag badly. Run ffmpeg -version and check what you actually have. If you're on a 3.x build from an old Ubuntu LTS or a minimal Docker base image, upgrade before you debug anything else. This is the same class of problem as an unknown encoder 'libx264' error, where the message describes your build rather than your command.
The second is a genuine container mismatch. Muxing HEVC into .avi, or into fragmented MP4 through a muxer configured for a codec list that predates HEVC, gives you this line no matter what tag you pass. The answer there isn't a tag, it's a different container or a different codec.
You can also hit it by asking for a tag the muxer doesn't recognize. -tag:v hcv1 (transposed letters) fails loudly, which is a small mercy compared to failing silently.
Skip the remux pass entirely
When the fix is a flag you must remember on every job, the durable version is an encoding step that already knows the target. FFmpeg Micro takes a source URL and a target profile and returns a correctly tagged rendition in one API call, with no encoder to host and no long-running job to babysit. You submit, you poll or take a webhook, you download.
curl -X POST https://api.ffmpeg-micro.com/v1/jobs \
-H "Authorization: Bearer $FFMPEG_MICRO_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "https://example.com/source.mov",
"operation": "transcode",
"options": {
"video_codec": "h264",
"crf": 23,
"faststart": true
}
}'
The point isn't that the API knows one flag you don't. It's that the tag problem, the faststart problem, and the yuv420p problem are all the same class of container-metadata mistake, and none of them should live in a shell script you maintain. Check the docs for the exact parameter names for your target.
The ingest rule: never ship HEVC alone to a browser audience
Tagging hvc1 fixes Safari. It does not fix Firefox, which has no HEVC decoder on most platforms, and it does not fix Chrome on systems without hardware HEVC support. If your audience is a browser rather than an Apple app, HEVC is a bonus rendition, never the only one.
The production shape is two outputs from one source:
- An H.264 High profile MP4 with
-pix_fmt yuv420pand-movflags +faststartas the universal fallback. This plays everywhere, including Firefox and every Android browser. - An HEVC MP4 with
-tag:v hvc1as the efficiency rendition, roughly 40 to 50 percent smaller at matched visual quality, served to clients that advertise support.
In HTML, order matters. The browser takes the first <source> it can decode:
<video controls playsinline>
<source src="clip-hevc.mp4" type='video/mp4; codecs="hvc1"'>
<source src="clip-h264.mp4" type='video/mp4; codecs="avc1.640028"'>
</video>
Note the codecs="hvc1" string in the MIME type. If you declare hev1 there while the file is tagged hvc1, Safari can reject the source before it ever fetches it. The declaration and the container tag have to agree.
If your files fail in browsers even after this, the cause is usually on the H.264 side, and four encoder flags cover almost all of it.
Common pitfalls
Most of the time lost on this bug goes to testing in the wrong place or fixing the wrong layer. These are the ones that recur.
Testing in VLC proves nothing. VLC decodes hev1 happily. Your test surface has to be Safari or QuickTime Player, or at minimum Finder's thumbnail, because those are the components that reject the tag.
Re-encoding to fix a tag is wasted compute and lost quality. If ffprobe shows codec_name=hevc, the video is fine. Copy the stream, don't re-encode it. A full libx265 re-encode of a 10-minute 1080p file can take several minutes; the remux takes under a second.
The audio codec matters too. HEVC in MP4 with Opus audio breaks in Safari even with a correct video tag, because AVFoundation won't decode Opus in MP4. Use AAC.
Finder caches thumbnails aggressively. After a correct remux, the old file's gray icon can persist. Move the fixed file to a new path or run qlmanage -r cache before you conclude the fix failed.
iPhone recordings are already tagged correctly. Video shot on iOS ships as HEVC in a .mov with the hvc1 tag, so the tag problem appears when you re-encode it, not on ingest. If you're converting those files, the MOV to MP4 recipe covers the rest of the flags.
Fragmented MP4 for HLS or DASH needs the tag as well. Setting -tag:v hvc1 on the init segment is what makes Safari's native HLS player accept an HEVC variant.
FAQ
Does adding the hvc1 tag reduce video quality?
Adding the hvc1 tag with -c copy changes zero video quality, because the command copies compressed frames byte for byte and only rewrites the container's sample description box. The output file is the same size as the input, give or take a few hundred bytes of header difference.
Why does my HEVC MP4 play in VLC but not in Safari?
VLC uses its own software HEVC decoder and accepts both hev1 and hvc1 sample entries, while Safari goes through Apple's AVFoundation, which only accepts hvc1. The file itself is valid HEVC in both cases; only the container tag differs, and ffmpeg -i in.mp4 -c copy -tag:v hvc1 out.mp4 reconciles them.
How do I check whether a file is tagged hev1 or hvc1?
Run ffprobe -v error -select_streams v:0 -show_entries stream=codec_tag_string -of csv=p=0 file.mp4 and read the four-character code it prints. On macOS you can also drop the file in Finder: no thumbnail on an HEVC file is a reliable sign of hev1.
Should I use HEVC or H.264 for web video?
Use H.264 as the baseline rendition for web video and HEVC as an optional smaller variant, because Firefox and many Chrome installations can't decode HEVC at all. HEVC cuts file size roughly 40 to 50 percent at matched quality, which is worth serving to Safari and iOS clients, but never as your only output.
Can I set the hvc1 tag without FFmpeg installed?
You can retag HEVC without a local FFmpeg install by sending the file to a hosted media API that outputs a compatible MP4 rendition per target, which is what FFmpeg Micro's transcode job does. On the desktop side, most GUI tools wrap FFmpeg anyway, so their behavior depends on whether the developer remembered the flag.
If your pipeline needs a correctly tagged rendition per target every time instead of a flag you hope someone remembered, that's one API call and a free tier to test it against your own files: sign up free and run a real clip through it.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

MP4 Not Playing in Browser? Four Encoder Flags Fix It
MP4 not playing in browser? VLC decodes almost anything, hiding the four real breakers: pixel format, H.264 profile/level, moov placement, audio codec.

Too many packets buffered? max_muxing_queue_size is the last fix
FFmpeg's "Too many packets buffered for output stream" error is a stream mapping problem. Fix the cause first, then size max_muxing_queue_size without an OOM.

FFmpeg Audio Out of Sync Isn't the Codec. It's the Frame Rate
FFmpeg audio out of sync is usually a variable-frame-rate source hitting a fixed -r. Detect VFR with ffprobe, then fix it with -fps_mode cfr and aresample.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free