@shotcut, this post contains a solution that makes the Ut Video preset color-accurate. Would you be willing to update the preset for the next version of Shotcut? I really appreciate your efforts at making the colors look so good!
After exporting around 200 test files, I finally understand what’s happening with the Ut Video color issues, and I’ve found simple and predictable workarounds for the common scenarios. Basically, there’s nothing wrong with Ut Video as a codec. The problem is colorspace signaling within ffmpeg. Here are the scenarios and their workarounds using Shotcut 18.11.18 and ffmpeg 4.0.2, tested on Windows 10 and Linux Mint 18.3:
Scenario: Exporting a video from Shotcut using the Ut Video preset
This doesn’t work:
Simply clicking the Ut Video preset and exporting.
This does work:
Go to the Export > Advanced > Other tab and add these lines:
color_range=mpeg
pix_fmt=yuv422p
Then export as usual. @shotcut, I believe adding these lines to the preset would cover 99.9% of use cases. No one should mind the change since it wasn’t working in the first place.
The problem:
If nothing is added to the Other tab, MediaInfo reports that the Ut Video file was encoded in RGB. That’s a massive problem because the Lossless H.264 source file was YUV444. (I used the limited.mp4 file as generated in previous posts.) I chose yuv422p with MPEG range as the export format because that’s the native internal processing format of Shotcut (best I recall). I didn’t see a point in making the preset use yuv444p when Shotcut won’t deliver 4:4:4 material to it in the first place. Likewise, using yuv420p for the preset didn’t make sense because Ut Video is for people who want to get as lossless as possible. (I tested 4:2:0 to 4:2:2 to 4:4:4 for conversion errors, and there were none.) Curiously, it was not necessary to specify a colorspace in the Other box. I assume Shotcut is explicitly passing this to ffmpeg since Shotcut knows the colorspace from the video mode profile. In fact, adding colorspace switches to the Other box actually messed up the colors rather than fix them. Perhaps a double conversion happened in that case.
Scenario: Transcoding a video with ffmpeg command line
This doesn’t work:
ffmpeg -i limited.mp4 -c:v utvideo -an export.avi
This does work:
ffmpeg -i limited.mp4 -colorspace 1 -color_primaries 1 -color_trc 1 -c:v utvideo -an export.avi
The problem:
ffmpeg figures out (or defaults) to BT.709 colorspace upon reading the limited.mp4 file. It also figures out that the file is in YUV444 format with MPEG range and correctly passes this to Ut Video. However, ffmpeg does not pass the BT.709 spec to Ut Video (which is a bug), so Ut Video defaults itself to BT.601 colorspace. The mismatch shifts the colors, and BT.601 is confirmed because MediaInfo says the FourCC is ULY4 (that’s Ut Video-speak for “4:4:4 8-bit limited BT.601”). Adding switches to explicitly declare the colorspace will push Ut Video into BT.709 and then it works. I can’t find documentation confirming that “1” as a colorspace value means “explicitly tag the output file with the same colorspace as the input”, but this seems to be how it works. I would rather be generic than hard-code “bt709” in my batch conversion scripts, just in case a source actually is bt601. @DRM, you and I will need to keep this workaround in mind if using ffmpeg scripts to create Ut Video proxies.
Scenario: Using ffmpeg to create video from an image file
This doesn’t work:
ffmpeg -loop 1 -t 5 -r 29.97 -s 1920x1080 -i r16g180b16-shotcut-rgb24.bmp -vf zscale=matrix=709:range=limited,format=yuv444p -c:v utvideo -an limited.avi
This does work:
ffmpeg -loop 1 -t 5 -r 29.97 -s 1920x1080 -i r16g180b16-shotcut-rgb24.bmp -vf zscale=matrix=709:range=limited,format=yuv444p -colorspace 1 -color_primaries 1 -color_trc 1 -c:v utvideo -an limited.avi
The problem:
This is the same issue as above. The filter graph is in BT.709 mode, but ffmpeg isn’t communicating that fact to the Ut Video codec. So again, Ut Video defaults itself to BT.601 colorspace which is confirmed by MediaInfo. Explicitly declaring the colorspace (even if using “1” for pass-thru) solves this problem.
I think I have enough test cases (around 40) to submit a bug report to ffmpeg. If anyone else could confirm or refute this hypothesis before I send it in, that would be awesome. In particular, my tests are very incomplete when the source material actually is in BT.601 colorspace. It would be great if one conversion script could handle a source in any colorspace or pixel format (bt601, bt709, RGB, RGBA, etc).
So, figuring out this madness is how I burned my afternoon yesterday. How about you guys? This Shotcut forum is a thing of beauty. A conversation with @D_S got me aware of Ut Video’s existence in the first place and it quickly replaced my H.264 CRF 12 proxies. Then @chris319 found a color problem that would have compromised my hopes of color grading on the proxies. Now it’s fixed, and on the audio side @shotcut informed me that AC-3 doesn’t have the delay issues that AAC does. @DRM got me thinking about proxy resolution again, and as I’ll describe on the proxy thread soon, I’m moving away from 480x270 because 270 isn’t divisible by 4 (long story). After pooling it all together, this new proxy setup is an editing dreamland and I doubt I would have found it on my own. Thanks everyone for the ideas!