Your export looks washed out and nothing is broken
The most common complaint in video delivery: the file looked correct in the editor, and in QuickTime or on the web the blacks are milky and the contrast is gone. Or the opposite: the shadows are crushed and the highlights are blown.
Nothing was damaged. The pixel values in the file are almost certainly correct. What is wrong is the description of what those values mean, and the player is interpreting them under a different convention from the one they were written with.
The two conventions
Full range (also called PC range, or pc in ffmpeg). Black is 0, white is 255. All 256 levels carry picture.
Limited range (video range, studio range, tv in ffmpeg). Black is 16, white is 235. The headroom below 16 and above 235 exists for historical reasons (analogue signal excursions, overshoot from filtering) and is preserved in digital video because broadcast equipment expects it.
Almost all delivered video is limited range. Almost all computer graphics, screenshots and rendered output are full range.
Now the arithmetic. A limited-range file interpreted as full range: the player takes 16 to be a real 16 rather than black, so blacks sit above zero: washed out, milky, low contrast. A full-range file interpreted as limited: the player expands 16–235 to 0–255, so everything below 16 clamps to black and everything above 235 clamps to white: crushed shadows, blown highlights, over-contrasty.
Those two descriptions are the diagnosis. Milky means limited read as full. Crushed means full read as limited.
Why it happens, and why it happens more than it should
The container can carry the answer. MP4 and MOV have a colr atom; Matroska has colour elements; H.264 and HEVC bitstreams have video usability information. All of them can say “limited range, BT.709 primaries, BT.709 transfer”.
Many encoders do not write those tags. Faced with an untagged file, every player guesses, and different players guess differently: by resolution (assuming standard-definition means BT.601 and high-definition means BT.709), by codec, or by a fixed default. The same file then looks different in VLC, in Safari, in Chrome and in Premiere, and each of them is behaving reasonably.
Tag it explicitly
ffmpeg -i in.mov -c:v libx264 -crf 20 \
-pix_fmt yuv420p \
-colorspace bt709 -color_primaries bt709 -color_trc bt709 \
-color_range tv \
-movflags +faststart out.mp4Four tags, and they cost nothing. -colorspace is the matrix used to convert between RGB and the luma-chroma representation; -color_primaries says which red, green and blue; -color_trc is the transfer characteristic, the curve; -color_range is the one this lesson is about.
Check what a file claims:
ffprobe -v error -select_streams v:0 \
-show_entries stream=pix_fmt,color_range,color_space,color_primaries,color_transfer \
-of default=nw=1 out.mp4If those come back unknown, you have found your bug before anybody reports it.
Converting rather than relabelling
Tagging says what the numbers mean. Sometimes you need to actually change them: a full-range source going into a limited-range delivery has to be scaled, not relabelled.
ffmpeg -i graphics.mov -vf scale=in_range=full:out_range=limited \
-color_range tv -c:v libx264 -crf 18 out.mp4Relabelling without scaling produces exactly the crushed look described above. This is the usual reason a motion graphic cut into filmed footage has harder blacks than everything around it.
The macOS QuickTime gamma story
For years, files exported from one application and viewed in QuickTime on macOS appeared with shifted gamma, while the same file viewed in VLC looked right. The cause was a mixture of missing tags and a system colour-management path that applied a display transform some applications expected and others did not.
Modern macOS is far more consistent and the problem is much reduced, but two lessons survive. First, a video player is a colour-managed application and the display profile is part of the chain: the same file can look different on two calibrated monitors and both be correct. Second, judge an export in more than one player, on more than one machine, before deciding it is right.
Where this bites hardest
- Motion graphics and titles. Authored full range in a design tool, dropped into a limited-range timeline. Blacks become crushed and pure white text clips.
- Screen recordings. Full range by nature, delivered to platforms that assume limited.
- Green screen. A range error changes every value in the frame, including the ones the keyer thresholds against, so a key that worked on the original fails on the re-tagged copy.
- Anything round-tripped through a tool that strips tags, which includes several popular uploaders and converters.
The free path
ffmpeg and ffprobe do all the tagging, converting and checking, free. DaVinci Resolve’s free edition has proper colour management with explicit input and output settings and broadcast-grade scopes: the parade and waveform will show you a milky black at 16 instead of 0 immediately, which is far more reliable than judging by eye on an uncalibrated laptop. MediaInfo is free and shows every colour tag in a file in a readable form.
The limitation
The tags are a claim, and nothing enforces them. A file can be tagged limited and contain full-range data, and no tool will object. Tagging tells a well-behaved player what to do; it does not make the data correct, and a mislabelled file is harder to diagnose than an untagged one because everything looks authoritative.
There is also no universal agreement on what to do with an untagged file, which means the only safe position is to tag everything you produce and to verify anything you receive. This is unglamorous and it removes an entire class of problem that otherwise reappears on every project.
Every lesson here is open. Your progress is recorded once you pass the Video with AI exam.
Check your understanding
A motion graphic exported from a design tool is cut into filmed footage. In the finished piece, the graphic’s blacks are noticeably harder and its white text clips, while the surrounding footage looks correct. What has happened?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Deepa, your AI tutor