1

The ffmpeg command below is being used to capture the desktop and create a resulting mp4. ffmpeg log says the input stream is bmp and I specified the target as h264 yuv420p. I found several older articles talking about a ffmpeg color shift problem issue and experimented several hours with the suggestions and filters. But as the pics show the resulting mp4 is washed out and not as vibrant as the original screen.

Using

  • Win 10
  • ffmpeg 5.0
  • VLC 3.16
  • Chrome
ffmpeg -f gdigrab -offset_x 1600 -offset_y 0 -video_size 1600x1200 -i desktop -pix_fmt yuv420p -vcodec libx264 -profile:v main -crf 16 outfile.mp4

Original - orig screen Resulting file - color shift

--- end of original post ---

Updates and information

I really needed this project done so after making the original post I made some further experiments which I think will mostly address the issue and create a workable solution.

The first issue to resolve is which color space to use for the resulting file? The basic choice revolves around where you want to play the resulting file. Some players do not like certain formats. According to this post yuv420p is for old players and it was yuv420p that was causing the issues that resulted in my posting here.

The rest of this post will concern itself with the rgb & yuv options.

RGB

The ffmpeg string which captures desktop to an rgb colorspace mp4. Played fine in chrome and vlc 3.16

Just like the yuv file below the rgb colors in the output file were true to the original desktop.

ffmpeg -f gdigrab -offset_x 1600 -offset_y 0 -video_size 1600x1200 -i desktop -c:v libx264rgb -qp 0 -pix_fmt rgb24 outfile.mp4

Media info results

YUV

The ffmpeg string which captures desktop to a yuv colorspace mp4. Using the yuv444p color space results in a file which to the eye looks just like the desktop looked when it was recorded. There may be some rounding errors and slight color variations if you look at it from a mathematical perspective but for my eyes and purposes it offers great fidelity to the original image. I found no combination of parameters which could make yuv420p true to the original desktop - all my results with 420 resulted in washed out images. Played fine in chrome and vlc 3.16

I was hoping the file size would be significantly smaller than rgb but that was not the result of my test - yuv and rgb produced files approximately the same size.

ffmpeg -f gdigrab -offset_x 1600 -offset_y 0 -video_size 1600x1200 -i desktop -vf scale=out_color_matrix=bt709:out_range=full,format=yuv444p -color_primaries bt709 -colorspace bt709 -color_trc bt709 -pix_fmt yuv444p outfile.mp4

Media info results

1 Answer 1

1

You cannot go from BGR to YUV420p without having a shift in colors, a bug with a known workaround (accurate_rnd). https://trac.ffmpeg.org/ticket/979

You also did not tag the output.

ffmpeg -f gdigrab -offset_x 1600 -offset_y 0 -video_size 1600x1200 -i desktop \
    -vf scale=flags=accurate_rnd:out_color_matrix=bt709, format=yuv420p \
    -color_primaries bt709 -colorspace bt709 -color_primaries bt709 \
    -color_trc iec61966_2_1 -c:v libx264 -profile:v main -crf 16 outfile.mp4

I hope you understand that sRGB uses sRGB transfer (iec61966_2_1), not BT.709, but uses BT.709 primaries.

Your RGB is incorrectly tagged as limited, gdigrab had this bug, update FFmpeg to latest build here: https://github.com/BtbN/FFmpeg-Builds/

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.