▶ Video & streaming

Colour spaces in video: BT.601, BT.709, BT.2020 and range

Primaries, transfer curve, matrix and limited or full range: why an exported video looks washed out or too contrasty, and how to avoid it in practice.

It happens all the time: a video looks perfect in the editing program and, once exported or uploaded, the blacks turn grey, the colours go dull or, on the contrary, the shadows crush into solid black. In the great majority of cases it is not a problem with the codec or the platform, but with inconsistent colour metadata along the chain. To understand it you need to know that, in video, pixel values alone are not enough: you also need to know how to interpret them.

The four pieces of information that define colour

A video stream should declare four distinct properties:

  1. colour primaries: which red, green and blue are used as references, that is, how wide the colour gamut is;
  2. transfer curve: how numeric values correspond to brightness;
  3. matrix: the formulas for converting from RGB to Y'CbCr and back;
  4. range: which numeric values represent black and white.

If the player interprets even one of these differently from how the file was created, the result changes visibly.

The main standards

Standard Original context Notes
BT.601 standard-definition television different primaries for PAL and NTSC
BT.709 high definition the reference standard for HD and SDR web video
BT.2020 ultra high definition much wider gamut, used with HDR

For high-definition SDR video, the correct choice today is almost always BT.709 for primaries, curve and matrix. The web and most players assume BT.709 for HD video when metadata is missing.

The BT.601 / BT.709 mistake

A classic problem arises when an HD video is converted with the BT.601 matrix and played with BT.709, or vice versa. The result is not dramatic but it is recognisable: skin tones shift slightly, greens and reds change hue. It often happens with conversions by older tools, or when scaling SD video to HD without converting the matrix.

Limited range and full range

This is the most frequent cause of «washed-out» video.

  • Limited range (also called TV or broadcast): in an 8-bit video black corresponds to 16 and white to 235. Values outside this interval are reserved as safety margins. It is the standard for almost all video.
  • Full range (also called PC or full): black is 0 and white is 255, as in computer images.

What happens when there is an error:

  • a limited-range file read as full looks washed out: black at 16 is shown as dark grey, white at 235 as light grey;
  • a full-range file read as limited looks too contrasty: everything below 16 becomes pure black and shadow detail disappears.

Screen recordings, some cameras and some smartphones produce full-range files; if the editing program or player does not recognise this, the error spreads.

Where the problem hides

  1. In capture: files recorded in full range without correct metadata.
  2. In editing: projects set to a colour space different from that of the footage.
  3. In export: encoders that do not write colour metadata.
  4. In playback: players or browsers that ignore metadata and apply a default assumption.
  5. In display: monitors or graphics cards set to the wrong range, which distort everything you see.

The last point is insidious: if the computer monitor is connected via HDMI and the graphics card sends a limited-range signal to a screen expecting full range, everything will look washed out, including correct files.

Checking and fixing with FFmpeg

With ffprobe you can read a file's colour metadata:

ffprobe -v error -select_streams v:0 -show_entries stream=color_range,color_space,color_transfer,color_primaries video.mp4

If the fields come back as «unknown», the player will have to guess. To declare them explicitly during encoding:

ffmpeg -i input.mov -c:v libx264 -crf 20 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -color_range tv output.mp4

Careful: these options declare the metadata, they do not convert the colours. If the pixels are full range and you want a limited-range file, you need a real conversion, for example with the scale filter and its input and output range parameters.

Good practice

  • check the colour spaces of source files with ffprobe or MediaInfo before you start;
  • keep a single working space for the whole project;
  • always export declaring primaries, curve, matrix and range;
  • check the result on several devices, including a smartphone;
  • calibrate, or at least verify, the monitor on which you make colour decisions.

In short

  • Colour in video depends on primaries, transfer curve, matrix and range.
  • BT.709 is the standard for SDR HD; BT.2020 is used with UHD and HDR.
  • A washed-out video is often limited range read as full range.
  • Metadata options declare the colour space but do not convert pixels.
  • Check source metadata and always declare it on export.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. A computer science graduate, he combines rigorous technical analysis with attention to the people who use technology.

Read also