View Full Version : Colorspace issue for Youtube
Gauze
15th February 2015, 22:38
In the past, my workflow was to record lossless video in 0-255 color range > Import in Vegas > Debugmode Frameserver > AviSynth/MeGUI.
My script was simply:
AVISource("D:\signpost.avi").AssumeFPS(30,1)
ConvertToYV12(matrix="rec709")
Which I believe compressed the color range to 16-235 color range and it generally looked fine when uploaded to Youtube.
Had to switch my recording process and now I'm getting H.264 video in a 16-235 color range. If I did the same process, my final video has a color range in the 27ish to 221ish.
Now, I could do a filter in Sony Vegas to change the color levels so that the color range is back to 0 - 255 and run my old process. But, I thought it seemed silly to stretch the range just to scale it back down again.
So I attempted to use the script:
AVISource("D:\signpost.avi").AssumeFPS(60,1)
ConvertToYV12(matrix="PC.709")
The color range of that encode was 16-235 and looked fine in my media player. However, once uploaded to Youtube, the color range looks like it was slightly compressed again.
My current wild guess is Youtube assumed the video was full range and compressed it from 0-255 to 16-235. Maybe based on some meta-data in my video file.
Is there anything that I can do with AviSynth or MeGUI to flag my video so Youtube recognizes the color range is already 16-235 and not compress the color range again?
TheSkiller
15th February 2015, 22:56
Which I believe compressed the color range to 16-235 color range and it generally looked fine when uploaded to Youtube.Correct.
So I attempted to use the script:
AVISource("D:\signpost.avi").AssumeFPS(60,1)
ConvertToYV12(matrix="PC.709")If you use the PC.709 matrix to convert from RGB to YV12 the levels are not being touched at all, thus the ~27 to ~221 RGB source is translated into YV12 at the same levels. The YV12 result will be washed out, but not as much as the RGB source since upon playback 16-235 levels are assumed whereas for RGB 0-255 is assumed – this might have fooled you into thinking it's been corrected.
The color range of that encode was 16-235 and looked fine in my media player.Can't be. It was still ~27 to ~221 and for playback 16-235 was assumed.
My current wild guess is Youtube assumed the video was full range and compressed it from 0-255 to 16-235. Maybe based on some meta-data in my video file.Nope, YouTube doesn't read metadata at all. You have to upload in 16-235 luma and 16-240 chroma levels and Rec.709 colorimetry. Anything else will look wrong. It's as simple as that.
If you apply the TV to computer levels filter in Vegas that would fix the levels from ~27 to ~221 to about 16-235 and it should be fine.
However, this raises the question: why is your clip not 16-235 to begin with? There might be a levels squish during decoding of the source.
wonkey_monkey
15th February 2015, 23:19
Nope, YouTube doesn't read metadata at all.
If I upload MKVs made with AviDemux with "full range samples" ticked, then I get washed out results - but not if I untick it.
That's a metadata-only change, isn't it?
TheSkiller
16th February 2015, 00:46
Yes.
It's probably a new thing then. But who knows what's actually happening with such video during their processing and encoding. Will the range be compressed to 16-235 prior to re-encoding? Or would they leave it at 0-255 and somehow tell the player about it? If they compress it to TV range on their own (which I assume is the most likely) it's probably done the cheap way in 8 bits precision...
Edit: Would be easy to find out what's happening by downloading a video.
StainlessS
16th February 2015, 01:31
Posted elsewhere: Managed to cap the YouTube clip above with Firefox & VideoCacheView (NirSoft) and GPac.
EDIT: For a Mpeg-Dash clip.
EDIT: VideoCacheView requires GPac install for mp4box to mux the separate mpeg-Dash Video + Audio files to
single mp4 automatically.
EDIT: No re-encode, just muxes the separate streams from cache. (Dash is a bit weird).
Gauze
16th February 2015, 06:13
However, this raises the question: why is your clip not 16-235 to begin with? There might be a levels squish during decoding of the source.
My source is 16-235 when I checked with:
Blur(1.0).ColorYUV(analyze=true)
However, after I ran 'ConvertToYV12(matrix="rec709")' in my original script, the color range became ~27 to ~221.
I was hoping that I could change the matrix value and not get the color range compression.
TheSkiller
16th February 2015, 12:40
So your clip that is frame served out of Vegas is RGB 16-235. That's OK. ConvertToYV12(matrix="PC.709") will keep it 16-235 in YV12.
However, after I ran 'ConvertToYV12(matrix="rec709")' in my original script, the color range became ~27 to ~221.That's to be expected because RGB, by default, is supposed to be full range 0-255, so ConvertToYV12(matrix="rec709") squishes the full 0-255 levels to 16-235 for a standard YV12 result. Since the levels were already 16-235 they were squished once again, leaving you with ~27 to ~221.
StainlessS
16th February 2015, 16:18
Search for posts on "Studio RGB" including the quotes.
Gauze
16th February 2015, 18:39
So your clip that is frame served out of Vegas is RGB 16-235. That's OK. ConvertToYV12(matrix="PC.709") will keep it 16-235 in YV12.
Hmmm, that's what I tried to do.
So I attempted to use the script:
AVISource("D:\signpost.avi").AssumeFPS(60,1)
ConvertToYV12(matrix="PC.709")
The color range of that encode was 16-235 and looked fine in my media player. However, once uploaded to Youtube, the color range looks like it was slightly compressed again.
At the very least, the video's black looked more like a dark grey.
Perhaps I should attempt using "--fullrange off" in my x264 encode parameters.
wonkey_monkey
16th February 2015, 21:49
colorbars.converttoyv12(matrix="rec709")
Encoded in AviDemux 2.5.8 with "full range samples" ticked (default): https://www.youtube.com/watch?v=tgYZizkYhHo
Encoded in AviDemux 2.5.8 with "full range samples" unticked: https://www.youtube.com/watch?v=7lwvXSMBMcE
poisondeathray
16th February 2015, 21:55
colorbars.converttoyv12(matrix="rec709")
Encoded in AviDemux 2.5.8 with "full range samples" ticked (default): https://www.youtube.com/watch?v=tgYZizkYhHo
Encoded in AviDemux 2.5.8 with "full range samples" unticked: https://www.youtube.com/watch?v=7lwvXSMBMcE
Did you check both output file levels from avidemux before uploading? (did avidemux or x264 adjust the levels before youtube)
x264 can alter the actual levels in YUV if --input-range and --range differ now. In the past, it was just VUI data, the actual YUV data was unchanged
wonkey_monkey
16th February 2015, 22:11
Did you check both output file levels from avidemux before uploading?
How could I be sure whether or not whatever I played them back with was, or was not, honoring the "full range sample" flag correctly? ;)
I played both encodes in MPC-HC and they looked exactly the same. I've also just checked them with ffmpegsource2, and both came back identical.
poisondeathray
16th February 2015, 22:17
How could I be sure whether or not whatever I played them back with was, or was not, honoring the "full range sample" flag correctly? ;)
I played both encodes in MPC-HC and they looked exactly the same. I've also just checked them with ffmpegsource2, and both came back identical.
Yes - you can check with ffms2 like you did, and histogram()
So you are saying both have the same YUV levels, and one is flagged full range but has "normal" range YUV levels ?
poisondeathray
16th February 2015, 22:49
Well I can confirm YT reads flags
1) Fullrange YUV, full range flag => looks normal on YT, and downloaded video is normal range. So YT read the flag and clamped it to normal range
2) Normal range YUV, "wrong" full range flag (this looks like what avidemux must be doing ie. --input-range full --range full, so no actual range conversion ) => levels clamped on both ends both on YT and downloaded file (~35-205)
So it looks like YT reads the full range flag and applies clamp when re-encoding
In flash (not re-encoding sites like youtube), full range data can be displayed properly without clamping with full range flag (ie. proper full range matrix is used for RGB conversion for display)
wonkey_monkey
16th February 2015, 22:56
So you are saying both have the same YUV levels
No idea for certain - it's just possible ffms2 sees the flag and alters the levels, though I'd guess it doesn't - but they both look identical when opened via Avisynth with ffms2 (and so are their histograms).
The encodes were both done with x264 in Avidemux with all default settings, except for toggling the "Full range samples" checkbox.
poisondeathray
16th February 2015, 23:04
This is a new development - YT never used to react to any flags of any kind.
But this does explain what the OP is seeing. Just don't encode with full range flags
Also, you have to be careful these days (depending on browser and settings) if you're getting VPx or Flash.
(Flash is going bye-bye and getting phased out supposedly , at least on YT)
foxyshadis
17th February 2015, 02:44
Vegas and its stupid Studio RGB is one of the most annoying parts of working with the program. Aside from figuring out when it'll convert and when it won't, it'll introduce unnecessary banding from the small loss of precision in the conversions.
No idea for certain - it's just possible ffms2 sees the flag and alters the levels, though I'd guess it doesn't - but they both look identical when opened via Avisynth with ffms2 (and so are their histograms).
The encodes were both done with x264 in Avidemux with all default settings, except for toggling the "Full range samples" checkbox.
ffms ignores flags, because it returns the original YUV unless you force RGB output. Avisynth doesn't have any way to signal the colorometry of a clip, so either you control it in script, or you get the default Rec601/Rec709 depending on the software and resolution.
Robert Martens
17th February 2015, 17:47
Also, you have to be careful these days (depending on browser and settings) if you're getting VPx or Flash.
I did some tests last month only to discover this latest development in Youtube's levels handling, and it seems that you also have to worry, at least in YT's case, about a difference between their Flash player, their HTML5 player with hardware acceleration enabled, and their HTML5 player with acceleration disabled.
I threw together a quick test script:
base = BlankClip(height=120, pixel_type="YV12", length=240)
w_pc = BlankClip(base, color_yuv=$FF8080).Subtitle("PC White (255)", align=5)
w_tv = BlankClip(base, color_yuv=$EB8080).Subtitle("TV White (235)", align=5)
b_tv = BlankClip(base, color_yuv=$108080).Subtitle("TV Black (16)", align=5)
b_pc = BlankClip(base, color_yuv=$008080).Subtitle("PC Black (0)", align=5)
StackVertical(w_pc, w_tv, b_tv, b_pc)
Then encoded it as simply as I could:
x264 --input-range "pc" --range "pc" levelstest.mp4 levelstest.avs
And uploaded it to Youtube. Downloading the file (with a browser extension that doesn't convert the videos it grabs) and opening it with FFVideoSource, in AvsPmod with the range specifically set to PC levels, suggested that Youtube had in fact converted the range. Using "tv" instead of "pc" results in video that's mostly untouched (though 0 becomes 1 and 255 becomes 254, so obviously I don't fully understand their process, or I'm doing my tests wrong).
poisondeathray already made that point, but the other part of it is even more fun. In current versions of Chrome and Firefox, it seems that even though Youtube explicitly converts full range video to limited range, the HTML5 player with acceleration doesn't bother expanding that back to full range on playback. With acceleration disabled, or with the Flash player, the video looks the way it should.
You can check which one you're using at https://www.youtube.com/html5 and request the HTML5 player if your browser doesn't use it by default.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.