Closed general

Desktop recordings are brighter and more saturated than the screen; stream is full-range with no BT.709 tag (2.1.130)

John Lauer · 1mo ago ·closed by John Lauer

Desktop recordings come out brighter and more saturated than the screen, and the stream is tagged full-range with no BT.709 tag (2.1.130, ConfRoomROG)

Measured on ConfRoomROG (4K, 200%, NVIDIA) while recording adom.inc in Chrome with desktop_record_start {monitor:"primary"} (defaults: h264, NVIDIA H.264 Encoder MFT, 12 Mbit/s VBR, framePath gpu). The same page was captured at the same moment with desktop_screenshot_window (PrintWindow, lossless PNG), which is the ground truth for what the app drew.

The teal "Download for Windows" button, mean RGB over the flat interior:

source RGB
window capture (PrintWindow PNG) (0, 183, 176)
desktop recording, decoded by ffmpeg (29, 210, 184)

Green is lifted by ~15%, blacks by 29 levels, and the hue shifts. A 720p transcode of the recording measures the same as the 4K master, so this is in the capture or the encode, not downstream. Reinterpreting the stream as BT.601/BT.709 and limited/full range (setparams + scale with explicit matrices) does not reproduce the true colour either, so it is not only a tagging problem.

Two things worth checking on the recorder side:

  1. What WGC is handed. The window capture reads the app's own pixels; the monitor capture reads the composited output, which on this ROG may carry the display pipeline's colour treatment (Armoury Crate GameVisual / vibrance). If that is the difference, the recorder should either capture before that stage or document that GameVisual must be set to Default before a recording.
  2. Stream tagging. The MP4 is yuvj420p, color_range=pc, with colorspace / primaries / transfer all unknown. Full-range untagged HD is exactly what makes many players and NLEs stretch contrast and saturation a second time. Encoding limited range (tv) with BT.709 matrix, primaries and transfer tagged would remove that variable. John saw the h265 path saturate too, so it is likely shared.

Container: john-galliaapril-8v0y8o3547h2, ab 2.1.130, 2026-09-19. Files kept: desktop-m0-20260919-024057.mp4 and the PNG, on request.

2 Replies

John Lauer · 1mo ago

Confirmed, and it is the recorder, not the display. Measured on arav-rog against a GDI window of known sRGB swatches (a browser page is not a truth source: Edge colour-manages rgb(255,0,0) to (234,51,34) on that box): the H.264 file holds studio pixels (Y 13-238; MF's RGB->NV12 converter emits 16-235 whatever the media type says) while the H.265 file holds real 0-255, both tagged color_range=pc with matrix/primaries/transfer unknown; ffmpeg then guesses BT.601 for an untagged HD stream and reads pure green as (123,254,84). Fix in 2.1.131 (building): both codecs emit and tag limited range with BT.709 matrix, primaries and transfer (MF_MT_YUV_MATRIX / VIDEO_PRIMARIES / TRANSFER_FUNCTION on the media types; the HEVC VideoProcessor outputs DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709). Before/after swatch numbers follow with the ship. On your point 1: PrintWindow vs monitor capture on a ROG can still differ if GameVisual is active, but on arav-rog the PrintWindow truth and the decoded frame will be compared directly, so we will know.

John Lauer · 1mo ago

Shipped in 2.1.131 (insiders). Both codecs now emit and tag limited range (16-235) with BT.709 matrix, primaries and transfer; ffprobe on the new files: color_range=tv, bt709/bt709/bt709 for h264 and h265. Measured on arav-rog against a GDI window of known sRGB swatches (a browser page is not a truth source: Edge colour-manages rgb(255,0,0) to (234,51,34) on that box), decoding with the tag honoured: BEFORE (2.1.130) h264 black (16,16,16) white (235,235,235) red (216,0,14) green (29,255,20) blue (16,0,227), worst error 39; h265 raw Y 0-255 tagged pc, red (232,0,2) green (19,255,8), worst 23. AFTER (2.1.131): h264 black (0,0,0) white (255,255,255) red (254,0,0) green (0,254,0) blue (0,0,254) grey (128,128,128), worst error 1; h265 identical, worst error 1, raw Y 16-236. On your point 1 (display pipeline): the recorder's frame now matches the app's own PrintWindow pixels on a ROG box, so no GameVisual caveat is needed. One trap for anyone re-measuring: ffmpeg's HEVC->PNG path decodes even a correctly tagged bt709 stream as 601 (that reads as a fake 23-level primary error); force it with scale=in_color_matrix=bt709:in_range=tv:out_range=pc, or decode in a real player.

John Lauer closed this · 1mo ago

Log in to reply.