FFmpeg

  • Preferences
  • Forgot your password?
  • View Tickets

Context Navigation

Up-vote

Colorspace support in FFmpeg

What is colorspace why should we care.

Colorspace describes how an array of pixel values should be displayed on the screen. It provides information like how pixel values are stored within a file, and what the range and meaning of those values are.

Basically, it tells the format of the array of pixels (e.g. RGB or YUV), and how the values of each color component should be translated, to be properly displayed by the photons of the screen. (i.e. picking a colorspace randomly seems unlikely to be a good choice...)

The differences between RGB and YUV:

  • RGB distinguishes color pixel values into 3 components: Red, Green, Blue. (hence the name)
  • YUV uses a different representation schema that represents color pixel values in: Luma (Y, or brightness), Chroma (U and V, two color differences). This format exploits the fact that humans are able to better notice details in luminance (approximated by luma) than in chroma. [ Note: YUV represents color in 3 components. ]

Note: ͏    The term "YUV" is ambiguous and often used wrongly [1], including the definition of pixel formats in FFmpeg. ͏    A more accurate term for how colors stored in digital video would be ​ YCbCr . ͏    Y'UV on the other hand specifies a colorspace consisting of luma (Y') and chrominance (UV) components. ͏    For more info read Wikipedia ​ <YUV> . [ [1] ͏    There's no practical difference between YUV and YCbCr: sort of more like "RGB" and "BGR". ͏    "UV" doesn't explicitly state the exact type of color difference neither. (so it might be "CbCr") ]

͏    In following, the term YUV is used as in FFmpeg pixel formats: referring to YCbCr in digital video.

The conversion between YUV pixel buffer representation and its visual representation depends on the type of the YUV represented in the pixel buffers, which are essentially device-dependent. The accuracy of grey vs color separation depends on how well the transformation matrix matches the underlying RGB space.

Examples are:

  • ​ BT.601 ("Standard-Definition" or SD)
  • ​ BT.709 ("High-Definition" or HD)
  • ​ BT.2020 ("Ultra-High-Definition" or UHD)

These standards describe not just things like how to convert a YUV signal to RGB, but also how a RGB signal should be represented in terms of photon emission, in a device-independent way.

How does FFmpeg identify colorspaces?

In FFmpeg, colorspaces are represented in the form of ​ pixel format .

In practical terms, the properties you care about are:

  • the signal type: RGB, YUV, or other type, and
  • the signal bit-depth.
  • For YUV signals, the color range: full/pc/jpeg or limited/restricted/tv/mpeg. [ See also: # ͏"color_primaries" ] For 8bpc (bit-per-component): full means 0 .. 255, limited 16 .. 235.
  • The transformation matrix between YUV and RGB.
  • The linearization function from RGB to a linear RGB signal.
  • The conversion matrix between the linearized RGB and the device-independent XYZ colorspace.

FFmpeg stores these properties in the AVFrame struct:

  • The format (type and bit-depth)-> format
  • The signal range-> color_range
  • The YUV/RGB transformation matrix-> colorspace
  • The linearization function (a.k.a. transformation characteristics)-> color_trc
  • The RGB/XYZ matrix-> color_primaries

How to use FFmpeg to convert the colorspace

Warning: ​ https://trac.ffmpeg.org/wiki/Scaling#Warning

Pixel format conversion is often performed by libswscale , which you will most likely access through the FFmpeg Scaler or the scale video filter .

Other video filters include:

  • colormatrix ( native )
  • colorspace ( native )
  • zscale ( z.lib library )

Comparing and contrasting colorspace , colormatrix , libswscale, and zscale

  • colorspace and colormatrix can only convert YUV to YUV
  • libswscale can convert between YUV and RGB
  • colormatrix only supports 8bpc pixel formats
  • colorspace supports 8bpc, 10bpc, and 12bpc
  • colormatrix does not apply gamma and primaries correction (i.e. which exact color "red", "green", and "blue" each is)
  • colorspace applies gamma and primaries correction by default. (Use fast=1 to disable this for faster conversion or to make output compatible with output produced by colormatrix .)
  • colormatrix is C only, whereas colorspace uses x86 SIMD so it's faster
  • colormatrix produces horrible quality for 10bpc and 12bpc
  • colorspace produces something decent for 10bpc
  • For 8bpc, colorspace seems to produce slightly better quality than colormatrix
  • zscale produces better results at all bit depths

colorspace and friends

The easiest way to use these filters is to ensure that the input AVFrames have all relevant struct members set to the appropriate values. On ffmpeg command-line this is what options such as colorspace and color_trc do; you can also put them on the output side to modify what space the output is in.

If everything goes well, libswscale figures out how to do the conversion and you can avoid calling the filter manually. However, AVFrames does not cover every option needed, so advanced use will go back to colorspace or zscale .

See also sws_setColorspaceDetails () and ​ F.X.'s colorspace answer .

There is no colorspace default called sRGB in FFmpeg, because it's identical to BT.709 except for a different transfer function. Just use one of the following:

  • sRGB input, fast: -vf "colorspace=all=bt709:fast=1" , aka -colorspace bt709 (on the input side!)
  • sRGB input, accurate: -vf "colorspace=all=bt709:itrc=srgb:fast=0" , aka -colorspace bt709 -color_trc srgb (on the input side!)

See also ​ F.X.'s HDR answer and ​ Gyan's sRGB output answer . If srgb does not work, try the more academic name iec61966-2-1 .

"color_primaries"

͏    Quick reference for somewhat cryptic "color_primaries" names: ͏    1: "bt709" (BT.709) ͏    5: "bt470bg" / "gamma28" (BT.470 BG) ͏    6: "smpte170m" (SMPTE 170 M) ͏    (alike for "colorspace" "color_trc") ͏    . ͏    See also: (`ffmpeg -h full` derived) [[

]] ͏    [ Still cryptic whatsoever... ]

Examples (with 20240506 git-master)

͏    Note: ͏    Use [ ​ https://github.com/MasterInQuestion/Markup/blob/main/picdif.htm ] for image comparison. ͏    (may not work well on small screen and/or browser asserted ​ ͏"devicePixelRatio" != 1) ͏    . ͏    Image comparison also by: ͏    ffmpeg -hide_banner -nostdin -i ${in0} -i ${in1} -lavfi "ssim; [0][1]psnr" -f null - ͏    [ ​ https://trac.ffmpeg.org/ticket/10922#comment:description ]

͏    Warning: ͏    Due to TracWiki 's limitation, the page is riddled with Unicode special characters (to workaround). ͏    (either invisible or of tricky look; near links, indentation; maybe else) ͏    . ͏    Copy / Edit with caution. ͏    Some changes occurred for the ͏"colorspace" filter meanwhile. ͏    Differ the following 4: ͏    # colorspace_yuv444p10le-yuv444p ͏    # colorspace_fast=0_iall=bt601-6-625 ͏    # colorspace_fast=0_iall=bt601-6-525 ͏    # colorspace_yuv420p10le-yuv420p

͏    Common pattern: ͏    "-vf" involved either: ͏    |1| "colorspace=bt709:iall=bt601-6-625:fast=1" ͏    |2| "colorspace=bt709:iall=bt601-6-625" ͏    |3| "colorspace=bt709:iall=bt601-6-525"

͏    Rather noticeable visual difference for |2| |3|. [ Near right-upper houses/shrubs in dark. ] ͏    Clarification appreciated. [ Rationale and relevant commits? ] ͏    . ͏    Warning message of interest: ͏    “[Parsed_colorspace_0] Input range not set, assuming tv/mepg” ͏    Specifying "irange=2" white-out things. (assumed 1 when not set) ͏    Note 6.1.1 didn't emit the warning: but generated [near-]identical [1] files as 20240506 git-master. ͏    . ͏    Less noticeable for |1|: mostly noise differences. [ Near aforementioned area; and the sky banding. ]

[ [1] ͏    "fast=1" related ones differ petty noises: ͏    Presumably for the added "csp:bt709 range:tv" assertions.

͏    Caveat the execution may have platform dependent differences. (typically no matter) ͏    "+bitexact" to various flags ( ͏"-sws_flags" , ͏"-flags" , ͏"-fflags" ) to insist platform independent (also non-stochastic) output. (may sacrifice speed) ͏    [ ^ One would also typically like " -map_metadata -1 -map_chapters -1" in such case. ]

͏    "-bitexact" should be shortcut for above: ͏    ​ https://github.com/search?type=code&q=repo:FFmpeg/FFmpeg+path:/^fftools%5C//+/(?-i)BITEXACT/ ͏    (seemingly missing "SWS_BITEXACT" yet) [ #11007 ] ]

The input source (rgb24):

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/origin(rgb24).webp (~ 879.32 KiB; WebP Lossless: 1440x836)

" colormatrix " (yuv444p10le):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colormatrix=bt470bg:bt709" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colormatrix_yuv444p10le.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colormatrix_yuv444p10le.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colormatrix_yuv444p10le.webp"

Output bit-identical as "colormatrix" (yuv444p) .

" colorspace " (yuv444p10le):

[ Note: ͏    SSIM > 99.98% with The input source (rgb24). ͏    Should be 100% if the conversion algorithms are improved, though. ]

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_yuv444p10le.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_yuv444p10le.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_yuv444p10le.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv444p10le.webp

Reference (yuv444p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 5 -color_primaries 5 -color_trc 6 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "yuv444p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "yuv444p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "yuv444p.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/yuv444p.webp

" colormatrix " (yuv444p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -vf "colormatrix=bt470bg:bt709" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colormatrix_yuv444p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colormatrix_yuv444p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colormatrix_yuv444p.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colormatrix_yuv444p.webp

" colorspace " (yuv444p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_yuv444p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_yuv444p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_yuv444p.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv444p.webp

" colorspace " (yuv444p10le -> yuv444p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i " colorspace_yuv444p10le.avi " -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_yuv444p10le-yuv444p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_yuv444p10le-yuv444p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_yuv444p10le-yuv444p.webp"

͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv444p10le-yuv444p.webp ͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv444p10le-yuv444p.20190416.webp

" colorspace " with " fast=0 " " iall=bt601-6-625 ":

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_fast=0_iall=bt601-6-625.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_fast=0_iall=bt601-6-625.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_fast=0_iall=bt601-6-625.webp"

͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_fast=0_iall=bt601-6-625.webp ͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_fast=0_iall=bt601-6-625.20190416.webp

" colorspace " with " fast=0 " " iall=bt601-6-525 ":

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-525" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_fast=0_iall=bt601-6-525.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_fast=0_iall=bt601-6-525.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_fast=0_iall=bt601-6-525.webp"

͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_fast=0_iall=bt601-6-525.webp ͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_fast=0_iall=bt601-6-525.20190416.webp

" colorspace " with " fast=1 " " iall=bt601-6-525 ":

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-525:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_fast=1_iall=bt601-6-525.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_fast=1_iall=bt601-6-525.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_fast=1_iall=bt601-6-525.webp"

Output bit-identical as "colorspace" (yuv444p10le) .

Reference (yuv420p10le):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv420p10le -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 5 -color_primaries 5 -color_trc 6 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "yuv420p10le.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "yuv420p10le.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "yuv420p10le.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/yuv420p10le.webp

" colorspace " (yuv420p10le):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv420p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_yuv420p10le.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_yuv420p10le.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_yuv420p10le.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv420p10le.webp

Reference (yuv420p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 5 -color_primaries 5 -color_trc 6 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "yuv420p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "yuv420p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "yuv420p.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/yuv420p.webp

" colorspace " (yuv420p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i "origin(rgb24).png" -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_yuv420p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_yuv420p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_yuv420p.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv420p.webp

" colorspace " (yuv420p10le -> yuv420p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i " colorspace_yuv420p10le.avi " -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_yuv420p10le-yuv420p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_yuv420p10le-yuv420p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_yuv420p10le-yuv420p.webp"

͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv420p10le-yuv420p.webp ͏    ​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv420p10le-yuv420p.20190416.webp

" colorspace " (yuv444p10le -> yuv420p):

͏    ffmpeg -y -v trace -hide_banner -nostdin -nostats -i " colorspace_yuv444p10le.avi " -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" "colorspace_yuv444p10le-yuv420p.avi" ͏    ffmpeg -y -v debug -hide_banner -nostdin -nostats -i "colorspace_yuv444p10le-yuv420p.avi" -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int -lossless 1 -q 100 -compression_level 6 "colorspace_yuv444p10le-yuv420p.webp"

​ https://github.com/MasterInQuestion/attach/raw/main/@ext/trac.ffmpeg.org/wiki/colorspace/colorspace_yuv444p10le-yuv420p.webp

Hint about " full_chroma_inp "

͏    ​ https://github.com/search?type=code&q=repo:FFmpeg/FFmpeg+%22SWS_FULL_CHR_H_INP%22 ͏    ​ https://github.com/FFmpeg/FFmpeg/blob/f3fe2cb5f72a669bd737203f6f82ed7f2fa60ded/libswscale/utils.c#L1526-L1542 ͏    ​ https://github.com/FFmpeg/FFmpeg/blob/41ed7ab45fc693f7d7fc35664c0233f4c32d69bb/doc/swscale.txt#L50-L57

Attachments (14)

  • origin(rgb24).png ​ ( 1.2 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_yuv444p10le.png ​ ( 1.2 MB ) - added by gdgsdg123 5 years ago .
  • yuv444p.png ​ ( 1.3 MB ) - added by gdgsdg123 5 years ago .
  • colormatrix_yuv444p.png ​ ( 1.3 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_yuv444p.png ​ ( 1.3 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_yuv444p10le-yuv444p.png ​ ( 1.5 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_fast=0_iall=bt601-6-625.png ​ ( 1.3 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_fast=0_iall=bt601-6-525.png ​ ( 1.3 MB ) - added by gdgsdg123 5 years ago .
  • yuv420p10le.png ​ ( 1.2 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_yuv420p10le.png ​ ( 1.2 MB ) - added by gdgsdg123 5 years ago .
  • yuv420p.png ​ ( 1.2 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_yuv420p.png ​ ( 1.3 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_yuv420p10le-yuv420p.png ​ ( 1.4 MB ) - added by gdgsdg123 5 years ago .
  • colorspace_yuv444p10le-yuv420p.png ​ ( 1.4 MB ) - added by gdgsdg123 5 years ago .

Download in other formats:

Trac Powered

Powered by Trac 1.4.2 By Edgewall Software .

Visit the Trac open source project at http://trac.edgewall.org/

a journey through color space with ffmpeg

  • Enter Our Giveaways
  • PragProg Errata

A Journey Through Color Space with FFmpeg

A Journey through Color Space with FFmpeg. For those who want to understand color spaces, transform videos from one color space to another, or read how I almost went crazy working…

Read in full here:

This thread was posted by one of our members via one of our news source trackers.

Corresponding tweet for this thread:

Share link for this tweet.

Search icon

An Intro to Colorspaces and FFmpeg with InVideo

Read on Terminal Reader

Too Long; Didn't Read

Company mentioned.

featured image - An Intro to Colorspaces and FFmpeg with InVideo

The rendering process of a .mp4 video created on InVideo involves piping a sequence of virtual framebuffers, containing the information of each frame of the composition, to the FFmpeg encoder, which sequentially stitches them into a video with standard H.264 encoding. A virtual framebuffer is just another fancy term for — the array of RGB values corresponding to the pixels of the frame of the video. It’s a ‘virtual image’ of sorts.

Let’s also note here that all InVideos are rendered in HD resolution.

Now this operation is very similar to taking a sequence of .png images and piping them to FFmpeg. Instead of .png images, we are just piping ‘virtual images’.  (It might have minute differences, but for the scope of this discussion, we can assume that it’s the same.)

The simplified FFmpeg command for stitching a video from a sequence of images is —

ffmpeg -i img%03d.png -pix_fmt yuv420p video.mp4

The above converts a sequence of images ( ‘image001.png’ ,  ‘image002.png’ ) to a yuv420 chroma sub-sampled H.264 video at the standard 25 frames per second.  (Replace the sequence of real .png images, with the virtual framebuffers and the result is the same.)

Simple, no?

Well, we thought so too until we started getting complains that the colours in the video seemed  ‘washed out’, ‘faded’, ‘dull’ . So we did a visual comparison of our InVideo output with the output of the same composition from After Effects (via Adobe Media Encoder) in their export settings for  High Definition  videos.

Visual Differences

While the difference is minor (as you may notice on the cover image of this blog), you can notice how the colours in the AE render are richer as compared to the InVideo render; which seems more washed out.

It took some research and closely inspecting the video metadata using FFprobe and MediaInfo to figure out that there was a difference in the  colour spaces used  between the two renders.

Colour Spaces

Before going further, it is important to touch base on the concept of colour spaces -

Colour spaces are the mathematical profiles/ equations which transform a pixel value of a colour model (such as (255,255,255) of RGB) to a corresponding wavelength of light. These equations have been derived and re-derived from an empirical understanding of how we humans perceive light. In other words, colour spaces are responsible for creating the physical representation of the colour red (or green or blue or a combination) as we see it, on a device like an LCD or CRT screen.

Without colour spaces, different display devices and screens, or even applications and browsers, would render the colours of the same image differently.

To make this uniform, colour spaces were formalized and created by an international committee ( CIE ). Today, it is incomplete to save an image or video with just the pixel information. A colourspace should be attached to the metadata of the media file to ensure uniform colour generation across the board.

To read more about  colour spaces , do check out the following  article . To read more about  colour space support in FFmpeg , check out the following  article .

Popular Video Colour Spaces

Among others, the 3 popular video colour spaces for  YUV  encoded videos generated from FFmpeg are -

​BT.601  (“Standard-Definition” or SD) ​BT.709  (“High-Definition” or HD) ​BT.2020  (“Ultra-High-Definition” or UHD)

Converting an RGB signal to YUV  is done via the YUV/RGB transformation matrix  that is different for the different colour spaces  mentioned above. The BT.601 is an old format for SD TV videos from the days of PAL and NTSC, while BT.709 is the newer most used format for HD videos.

(It is interesting to note that BT.709 shares the same primaries and white point chromaticity as the  sRGB  space — which is the go-to colourspace for most images and web browsers.

The BT.2020 is the latest format for UltraHD with a wider and richer gamut. However, we can leave it out of the scope of discussion until we start creating UltraHD videos with richer colours for large screens.)

Coming back to the renders…

Which Colour Space was the AE video rendered in?  BT.709!

This makes sense since the video was in HD resolution, and BT.709 is the wider accepted colour space for most HD videos today.

Which Colour Space was the InVideo video rendered in?  BT.601!
After much digging, we realised that FFMPEG by default converts RGB to YUV using 601 matrices, irrespective of the resolution — if nothing is specified.

So which one is better?

Hmm, hard question. They were meant for different devices (BT.601 for CRTs and BT.709 for HD LCD screens) so we should not really compare.

However, BT.709, being a newer format, has a slightly wider colour gamut and is  arguably  closer to the human perception of colour and luminance than BT.601. It was also built for it and thus maps better than most HD formats used today.

And just based on the colour differences in the screenshots we saw above —  we like BT.709 better .

Rendering InVideos in the BT.709 Colour Space

Now that we had identified the problem, we just had to figure out how to get FFmpeg to generate the video in the BT.709 colourspace.

A hasty attempt led us to run the following modified command:

ffmpeg -i img%03d.png -pix_fmt yuv420p -vf colorspace=all=bt709:iall=bt601-6-625:fast=1 -colorspace 1 -color_primaries 1 -color_trc 1 video.mp4

We added the following parameters to the original command -

-colorspace 1 -color_primaries 1 -color_trc 1

The “1” corresponds to BT.709. (More on the relevant FFmpeg documentation  here .)

However, we soon realised that — all that this did was  assign the BT.709 tags to the video metadata . FFmpeg still encoded the video using the BT.601 transformation matrix.

This was wrong and a double whammy!

The video was still encoded using the BT.601 transformation matrix but was assigned BT.709 metadata tags. So a media player like VLC, would decode the video according to the BT.709 reverse transformation matrix — causing all sorts of  unwanted discolouration .

Instead of simply assigning the metadata tags, we also needed to ensure that the BT.709 transformation matrix was used, or alternatively do the YUV to YUV colour space conversion from BT.601 to BT.709.

For this, we used the  FFmpeg filters  feature (“-vf”). It could all implicitly be done in 1 FFmpeg pass using the command below -

The extra filters parameter takes care of the conversion to BT.709 -

-vf colorspace=all=bt709:iall=bt601-6-625:fast=1

(fast=1 was used so that the correct gamma correction happens.)

The metadata tags were still kept as a good practice. Many media players, by default, decode an HD video using the BT.709 colour space if nothing is specified, some still need the metadata tags for proper decoding.

And voila! We had an output which was almost identical in colour to the AE render.

Also published on: https://medium.com/invideo-io/talking-about-colorspaces-and-ffmpeg-f6d0b037cc2f

Mongo DB

About Author

InVideo.io HackerNoon profile picture

THIS ARTICLE WAS FEATURED IN ...

a journey through color space with ffmpeg

RELATED STORIES

Article Thumbnail

Stack Exchange Network

Stack Exchange network consists of 183 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

How to concat videos with different colour spaces?

enter image description here

I have tried converting the B.2020 videos to B.709 before concatenating by using the following command on each video but the outputs are still washed out:

It wasn't clear to me which way round the arguments should go so I also tried switching the bt2020 and bt709 terms but they still look washed out but with more saturation.

Is this the right approach? Am I missing some other arguments in order to convert the B.2020 videos to B.709 while preserving their colour?

I have attached a side by side of the original and converted video.

The metadata of the videos I am trying to concat are:

  • color_range=tv
  • color_space=bt709
  • color_transfer=bt709
  • color_primaries=bt709
  • color_space=bt2020nc
  • color_transfer=arib-std-b67
  • color_primaries=bt2020

Ham789's user avatar

You must log in to answer this question.

Browse other questions tagged ffmpeg video ..

  • Featured on Meta
  • We spent a sprint addressing your requests — here’s how it went
  • Upcoming initiatives on Stack Overflow and across the Stack Exchange network...

Hot Network Questions

  • Finding the Zeckendorf Representation of a Positive Integer (BIO 2023 Q1)
  • Does there exist a Dehn filling of an irreducible 3-manifold with toroidal boundaries which is still irreducible?
  • A manifold whose tangent space is a sum of line bundles and higher rank vector bundles
  • Real-life problems involving solving triangles
  • An algorithm for generating a permutation of N numbers ranging from 1 to N with the maximum of smallest neighbouring differences
  • Is this a Hadamard matrix?
  • Recommend an essay, article, entry, author, or branch of philosophy that addresses the futility of arguing for or against free will
  • What is the computational scaling of DFT energy vs gradient vs Hessian?
  • The rise and fall of oval chainrings?
  • Is "sinnate" a word? What does it mean?
  • How can one count how many pixels a GIF image has via command line?
  • Identify the story about an author whose work-in-progress is completed by a computer
  • Coincidence between coefficients of tanh(tan(x/2)) and Chow ring computations?
  • Reproducing Ruth Vollmer's acrylic Steiner surface
  • We have differing types of infinity; do we also have differing types of randomness?
  • Translation of 近乎是要套
  • Looking for the title of a short story for my students to read about a woman searching for the last man alive
  • How to POSIX-ly ignore "warning: command substitution: ignored null byte in input"?
  • What caused the builder to change plans midstream on this 1905 library in New England?
  • Substitute HS Experiment for Synthesis/Decomposition of HgO
  • Is it pragmatic to use slats and flaps to maintain position of center of lift?
  • Just another basic puzzle
  • Translation of the two lines of Latin in Shakespear's Venus and Adonis
  • Does the damage from Thunderwave occur before or after the target is moved

a journey through color space with ffmpeg

VideoHelp

  • Forum Index
  • Today's Posts
  • File Uploader
  • All software
  • Popular tools
  • Portable tools
  • Blu-ray / DVD Region Codes Hacks
  • Blu-ray / DVD Players
  • Blu-ray / DVD Media
  • Video Streaming Downloading
  • DVD and Blu-ray ripping
  • Blu-ray, UHD, AVCHD

Home

  • Video Conversion

FFmpeg ProRes output -- no BT470GB flag

Thread tools.

  • Show Printable Version
  • Email this Page
  • Subscribe to this Thread

a journey through color space with ffmpeg

I am converting video to ProRes format with options: Code: -c:v prores_ks -profile:v 1 -colorspace bt470bg I see that ffmpeg wants to do this too: Code: Stream #0:0: Video: prores (LT) (apcs / 0x73637061), yuv422p10le(tv, bt470bg/unknown/unknown, progressive), 720x576 [SAR 16:15 DAR 4:3] But the output file does not have the appropriate flag: Code: Video ID : 1 Format: ProRes Format version: Version 0 Profile format: 422 LT Codec ID: apcs Duration: 15 min 37 sec Bit rate mode: Variable Bit rate: 56.7 Mbps Width: 720 pixels Height: 576 pixels Display aspect ratio: 4:3 Frame rate mode: Constant Frame rate: 50,000 FPS Color space : YUV Chroma subsampling: 4:2:2 Scan type: Progressive Bits/(Pixel*Frame) : 2,732 Stream size: 6.18 GiB (100%) Writing library: Lavc So how to do it properly?

ProWo is online now

You have to set colormatrix and colortrace too.

Sharc is online now

Do you want to convert the colorspace by using the corresponding matrix, or just flag it? Maybe this helps: https://medium.com/invideo-io/talking-about-colorspaces-and-ffmpeg-f6d0b037cc2f https://www.canva.dev/blog/engineering/a-journey-through-colour-space-with-ffmpeg/ https://stackoverflow.com/questions/61834623/how-to-use-ffmpeg-colorspace-options
--> Last edited by Sharc; 28th Apr 2024 at 04:46 . Reason: Link added
Thanks. This is the only combination that worked for me. Missing one causes all flags to be missing. Code: -colorspace bt470bg -color_primaries bt470bg -color_trc gamma28 -color_range tv I think this is a bug in ffmpeg.
--> Last edited by rgr; 28th Apr 2024 at 05:56 .
Originally Posted by Sharc Do you want to convert the colorspace by using the corresponding matrix, or just flag it? Maybe this helps: https://medium.com/invideo-io/talking-about-colorspaces-and-ffmpeg-f6d0b037cc2f https://www.canva.dev/blog/engineering/a-journey-through-colour-space-with-ffmpeg/ https://stackoverflow.com/questions/61834623/how-to-use-ffmpeg-colorspace-options Just flag it (source: miniDV) However, I have a question by the way. AViSynth script, the source is let's say BT709 YUV420. I use the command: ConvertTo422() (no parameters) The output will be BT709/YUV422 or BT601/YUV420. I haven't tested it, but according to the instructions, ConvertToYUVxxx gives BT601 by default.
--> Last edited by rgr; 28th Apr 2024 at 05:55 .

hello_hello is offline

Originally Posted by rgr However, I have a question by the way. AViSynth script, the source is let's say BT709 YUV420. I use the command: ConvertTo422() (no parameters) The output will be BT709/YUV422 or BT601/YUV420. I haven't tested it, but according to the instructions, ConvertToYUVxxx gives BT601 by default. The matrix is only required for conversions between YUV and RGB. As far as I know the convert functions can't change the matrix when converting from one flavor of YUV to another, so if you want to convert a YUV BT709 source to BT601, you need to convert it to RGB with matrix="Rec709", and then back to YUV with matrix="Rec601".
Avisynth functions Resize8 Mod - Audio Speed/Meter/Wave - FixBlend.zip - Position.zip Avisynth/VapourSynth functions CropResize - FrostyBorders - CPreview (Cropping Preview)
Originally Posted by hello_hello The matrix is only required for conversions between YUV and RGB. As far as I know the convert functions can't change the matrix when converting from one flavor of YUV to another, so if you want to convert a YUV BT709 source to BT601, you need to convert it to RGB with matrix="Rec709", and then back to YUV with matrix="Rec601". AFAIK the colormatrix(mode=xxxx) filter can do the conversion staying within YUV in one step: http://avisynth.nl/index.php/ColorMatrix
  • Private Messages
  • Subscriptions
  • Who's Online
  • Search Forums
  • Forums Home
  • Latest Video News
  • Newbie / General discussions
  • VR Player and Hardware
  • Authoring (Blu-ray)
  • Authoring (DVD)
  • Camcorders (DV/HDV/AVCHD/HD)
  • Blu-ray Ripping
  • DVD Ripping
  • Software Playing
  • Restoration
  • Programming
  • DVD & Blu-ray Writers
  • DVD & Blu-ray Recorders
  • DVD & Blu-ray Players
  • Portable Video
  • Media Center PC / MediaCenters
  • User guides
  • Authoring (VCD/SVCD)
  • ffmpegX general discussion
  • SVCD2DVD & VOB2MPG
  • VCDEasy General

Similar Threads

Difference between switch and flag in ffmpeg., ffmpeg prores: packet too small, editing in nle after encoding prores 422 hq with ffmpeg in the window 10., is ffmpeg prores the same as the prores you get with fc pro, ffmpeg prores mov to 4k hdr mp4 or mkv.

a journey through color space with ffmpeg

  • Privacy Statement

COMMENTS

  1. A journey through color space with FFmpeg

    Luckily, the post didn't just talk about how to transform color spaces with FFmpeg but also highlighted a similar issue about pale videos generated using images. The following command was supposed to fix it all. ffmpeg -i img%03d.png -pix_fmt yuv420p \. -vf colorspace=all=bt709:iall=bt601-6-625:fast=1 \.

  2. video

    The YUV <-> RGB color matrix is bt2020nc (-colorspace) The primaries are bt2020 (-color_primaries) The EOTF/tone curve is arib-std-b67 (HLg) (-color_trc) Now, this is where it gets fun: some filters are automatically applied depending on what FFmpeg knows of the streams, usually using the libswscale component (-vf scale). This is obviously ...

  3. A Journey through Color Space with FFmpeg : r/programming

    Luminance channel, A channel (red-green axis) and B channel (blue-yellow axis). The transformation function is designed to fit well with human vision, and the space is good for image processing. I've found that a lot of color processing tasks end up with less artefacts (banding, etc.) than when you use other color spaces, for instance.

  4. Talking About Colorspaces and FFmpeg

    Popular Video Colour Spaces. Among others, the 3 popular video colour spaces for YUV encoded videos generated from FFmpeg are -. BT.601 ("Standard-Definition" or SD) BT.709 ("High-Definition ...

  5. FFmpeg

    A journey through color space with FFmpeg. For those who want to understand what color spaces are, find out how to transform videos from one color space into another one, or read about how I almost went crazy trying to find out why videos generated with Canva look slightly off in terms of color.

  6. colorspace

    In FFmpeg, colorspaces are represented in the form of pixel format . In practical terms, the properties you care about are: The signal format in the pixel buffer: the signal type: RGB, YUV, or other type, and. the signal bit-depth. For YUV signals, the color range: full/pc/jpeg or limited/restricted/tv/mpeg.

  7. determine video colorspace ? : r/ffmpeg

    The first hint was when my tonemapping filters got this response: code 3074: no path between colorspaces. Google wasn't very helpful and all results pointed to a "your ffmpeg binary is outdated". Which it isn't. ffprobe got me this: level=41. color_range=unknown. color_space=unknown. color_transfer=unknown.

  8. FFMpeg

    If this does not work you could try to add a colorspace conversion filter. ffmpeg -i input.mkv -vf "scale=2560:1440,colormatrix=bt709:smpte170m" output.mp4. It could also be your player that is displaying the converted video wrong. try tagging it as rec601. ffmpeg -i input.mkv -color_primaries smpte170m -color_trc smpte170m -colorspace ...

  9. A Journey Through Color Space with FFmpeg

    A Journey through Color Space with FFmpeg. For those who want to understand color spaces, transform videos from one color space to another, or read how I almost went crazy working… Read in full here: canva.dev - 17 Apr 23 A journey through color space with FFmpeg - Canva Engineering Blog

  10. An Intro to Colorspaces and FFmpeg with InVideo

    It could all implicitly be done in 1 FFmpeg pass using the command below -. ffmpeg -i img%03d.png -pix_fmt yuv420p -vf colorspace=all=bt709:iall=bt601-6-625:fast=1 -colorspace 1 -color_primaries 1 -color_trc 1 video.mp4. The extra filters parameter takes care of the conversion to BT.709 -.

  11. r/ffmpeg on Reddit: Any way to edit colour space / pix_fmt metadata

    FFmpeg should've added pix_fmt metadata by default. The fact you're player recognizes it as gbrp is worrying. I don't think there's any way to change this, honestly sounds like your file is corrupt or something. You can however easily change color space metadata using the hevc_metadata bitstream filter.

  12. ffmpeg

    caja is using mediainfo and mediainfo has some misleading labels. What mediainfo is describing as Color space is more accurately a color model.What ffprobe displays is the pixel format (pix_fmt) which is the specific combination of color model, chroma subsampling, bit depth and component interleaving that the decoder will produce.A Color space is a mathematical organization of reproducible colors.

  13. ffmpeg

    I have tried converting the B.2020 videos to B.709 before concatenating by using the following command on each video but the outputs are still washed out: ffmpeg -i input.mov -vf colorspace=all=bt709:iall=bt2020:fast=1 output.mov. It wasn't clear to me which way round the arguments should go so I also tried switching the bt2020 and bt709 terms ...

  14. Colorspace help please : r/ffmpeg

    FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created. ... Colorspace help please . Plan on encoding my media library to save space. A few 4k hdr remuxs and 1080 bluray remuxs. Is it necessary to set the colorspace when using ...

  15. ffmpeg

    In theory the way to solve this is to use 10- or 12-bit colour space through every stage from rendering, to editing and mastering, through to output and even in the screen or projector. ... 20 may not be transparent in mostly flat areas of color with animation. With rendered animation you should be able to get away with much lower CRF values ...

  16. Help with compressing to h.264 with full color space : r/ffmpeg

    That being said, with full color range they'll certainly look better than the limited color space that essentially creates a grey square on the webpage when the video is white. Currently, the only way that I can get my player to playback at the correct color space is to use the -pix_fmt yuvj420p flag. The color on playback looks a bit blown out ...

  17. Comments Page

    Comments about A Journey Through Color Space with FFmpeg ... "What is color space 1? And what are primaries?" Be thankful you have the ability to set the color space and primaries within the command. Back in the days of dinosaurs (mid-2000s to 2010ish) and when HD was just an infant sucking its thumb and before Apple updated the MOV container ...

  18. FFmpeg ProRes output -- no BT470GB flag

    AViSynth script, the source is let's say BT709 YUV420. I use the command: ConvertTo422 () (no parameters) The output will be BT709/YUV422 or BT601/YUV420. I haven't tested it, but according to the instructions, ConvertToYUVxxx gives BT601 by default. The matrix is only required for conversions between YUV and RGB.

  19. A Journey Through Color Space with FFmpeg : r/hypeurls

    566 subscribers in the hypeurls community. OFFICIAL COMMUNITY OF HYPEURLS.COM: r/hypeurls is a Reddit community for sharing and discussing new tech…

  20. ffmpeg not working with filenames that have whitespace

    REM Cut an audio file by right-cliking it (works also on multiple selected audio) REM 1) save this file. REM 2) open registry, browse to Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\SystemFileAssociations\audio\shell. On the left panel, right-click on "shell" and select "New", then "Key". Type "Cut audio 5min".