Question / Help My success with recording lossless 1920×1200 @ 60 fps for YouTube

AlexFolland

New Member
Hello! This isn't a question or request for help, but the thread asked for a prefix and there's no "general discussion" forum. I want to post this thread to help people who were having as much trouble as I was finding information about this topic. It took a lot of research to figure all this out.

I have previously had problems in OBS Studio trying to record 1920×1200 @ 60 fps in real time, as the entire CPU would be used, so the game was unplayable and the resulting video was very laggy. My only workable method was to use MagicYUV (proprietary but fast codec) in DxTory and not use OBS, but that was a bummer because I couldn't include other sources at the same time and all the other nice perks OBS provides. In OBS, I'd tried all the different available codecs with their corresponding lossless settings: ffvhuff (said to be extremely well optimized), UT Video (similarly said to be fast), Lagarith (known to be slow, but might as well try), HuffYUV, ZMBV, libx264rgb, and libx264. It seemed like nothing was fast enough, despite my CPU being pretty good and MagicYUV in DxTory working wonderfully with tons of CPU headroom.

Just now, I seem to have solved the problem in OBS with some arcane voodoo involving scary-looking ffmpeg command line parameters, and I don't think the problem was ever the codec. My hypothesis is that it was software color conversion, which is very slow! I read somewhere in my restless research that ffmpeg and/or libx264 invokes swscale and asks it to do heavy color conversion back-and-forth operations for no good reason unless it is told what the input color space is.

I think using the following parameters prevented these slow software color conversions, which allowed it to record at full speed using only 6 of my 8 available CPU cores:

Edit: I've changed some of these settings for the better. See https://obsproject.com/forum/thread...20×1200-60-fps-for-youtube.64735/#post-279686 for more details. These screenshots and settings remain here only for historical purposes.

00000738.png

00000739.png


After setting all those options just like that (particularly the "Video Encoder Settings" line), everything clicked and suddenly my game could play smoothly and the resulting video looked like an exact copy of the gameplay except with chroma subsampling!

The reason I want to record lossless video for YouTube is that YouTube transcodes all video it's given to its own lossy streaming formats, including YUV 4:2:0 which has chroma subsampling. For minimal quality loss on YouTube, one must upload lossless video.

Here are the settings I used, in case the pictures above are gone in the future and/or you want to copy what I did:

Edit: I've changed some of these settings for the better. See https://obsproject.com/forum/thread...20×1200-60-fps-for-youtube.64735/#post-279686 for more details. These screenshots and settings remain here only for historical purposes.

Code:
relevant fields in the "Output" section of the settings:
Output Mode: Advanced
"Recording" tab
Type: Custom Output (FFmpeg)
Container Format: matroska
Muxer Settings:
Video Bitrate: 999999999
Keyframe interval (frames): 120
Video Encoder: libx264
Video Encoder Settings: colorspace=bt470bg color_range=pc qp=0 preset=ultrafast x264-params=fullrange=on:input-csp=nv12:output-csp=i420:threads=6
Audio Bitrate: 999
Audio Encoder: flac
Audio Encoder Settings: compression_level 0

in the "Advanced" section of the settings:
Color Format: NV12
YUV Color Space: 601
YUV Color Range: Full

I hope this helps someone!
 
Last edited:

Fenrir

Forum Admin
So... have you tried the lossless preset in simple output mode? These settings are giving me anxiety.
 

AlexFolland

New Member
Yes, I have. It was extremely slow.

It uses UT Video, right? You suggested it in IRC and I tried it at that time.

Anyway, I think this goes to show that there's something that's not well understood in OBS that is killing performance by default.
 

Fenrir

Forum Admin
Or something with your specific system. I'm able to use the lossless preset with barely any impact on my system at all.
 

AlexFolland

New Member
OBS can record with even less impact and allow more people to record lossless video this way. Bragging about your system isn't very helpful.

Also, your negative attitude is not very productive. Instead of saying the settings give you anxiety, saying something about how you don't understand how the settings improve performance and that further research is warranted would be more productive. These settings have a profound impact on the encoding performance that I wasn't expecting after all the experimentation I did.
 
Last edited:

AlexFolland

New Member
Terrible how? Explain, if you know so well. They improved my performance extremely. My CPU usage was beyond capped and couldn't record anywhere near 60 fps by default, but had plenty of headroom for my game with these settings.
 

Rodney

Forum Moderator
If you want to record lossless with x264 just set CRF to 0 and preset to ultrafast in advanced mode. No need to use custom ffmpeg output. Also using the "indistingushable" preset will yield much smaller file sizes that are still perfectly usable for youtube videos imo. Also make sure color space is set to 709 with range being partial.

And as for the other settings:
  • colorspace=bt470bg - why? YouTube uses 709 for HD video
  • color_range=pc - youtube doesn't support full range
  • fullrange=on - again, youtube doesn't do full range
  • input-csp=nv12:output-csp=i420 - there should be no need to set this
  • lossless audio - simply pointless and a waste of bandwitdh, especially for youtube.
Not sure if there's any reason to set threads to 6, by default it's 1.5 * cpu threads. so 12 in your case.
 

koala

Active Member
I did successfully record lossless 2560x1440@60 with the simple settings of OBS. No need for esoteric ffmpeg or color space parameters. It just works with the defaults.
My CPU is a i7-6700k and GPU is a GTX 1070 and the game was Guild Wars 2. A very CPU-demanding game, which occupies about 3,5 cores for itself.

The challenge isn't CPU usage, it's the harddisk throughput. I was able to record only to SSD without frame loss. To HD, such a recording fails.
The bandwidth of my recording is 140MB/s, a corresponding 1920x1200 requirement would be about 90 MB/s. Few HDs can sustain such a high write data rate for an extended amount of time. Good SSDs can do this. Key point is a continuous write data rate with no drops. One drop in data rate and the recording stalls, resulting in frame losses and/or hanging OBS.

I assume with your settings you achieve a slightly smaller video size than with utvideo, sacrificing some quality, so the HD bandwidth requirement isn't that high, so you can record to HD.

Just for fun: if you have a SSD, try recording to SSD using the lossless preset of the simple settings of OBS.
 
Through testing quality for YouTube upload, I found it is best to try and match as close as possible the recommendations YouTube provides, completely disregarding the bitrate and pushing that through the roof, then using Shotcut or whatever editor of your choice to set it to a standard of 48M for bitrate at 1080p, adding a slight sharpening filter then uploading. YouTube will kill your upload times with the colour space conversion if you don't use their standard of 601 for 720p below, 709 for 1080p up, partial range and nv12 input.

Your settings are interesting though and I will test them out once I wake up from much needed sleep.

Never jump to a conclusion, especially when someone is trying to help!
 

AlexFolland

New Member
If you want to record lossless with x264 just set CRF to 0 and preset to ultrafast in advanced mode. No need to use custom ffmpeg output.

I tried that (though qp instead of crf as that is what Dark Shikari (formerly main x264 dev) has always recommended to ensure the lossless flag is set correctly; discussed in #obs-dev earlier), and got slow results, hence this experimentation and solution that worked for me.

Also using the "indistingushable" preset will yield much smaller file sizes that are still perfectly usable for youtube videos imo.

I want my recordings to be editable and professionally viable, and transcoding lossy video causes generational decay that I want to avoid. I agree, though, that that would be a good option for a quick-and-dirty upload of an unedited clip.

Also make sure color space is set to 709 with range being partial.

And as for the other settings:
  • colorspace=bt470bg - why? YouTube uses 709 for HD video
  • color_range=pc - youtube doesn't support full range
  • fullrange=on - again, youtube doesn't do full range

"bt470bg" is BT.601. I specify this to ensure that ffmpeg and/or libx264 is writing the same color space as it's receiving, hopefully to prevent it from invoking swscale. I could have easily used "bt709" instead if my OBS "YUV Color Space" field was set to 709. The point here is to avoid the swscale, and check for speed. This was the first test I found that had the speed I was looking for, and I can adjust that detail later.

Regarding full range, I have a full range video on YouTube that I uploaded a few years ago. It maintained its full range, and even displays in full range in Firefox, which is known to ignore the color range flag and display partial range video as is without upscaling the color range on playback. Here's the relevant bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=1161349 . I still see this bug on my computer in Firefox Nightly 55.

Here is a side-by-side comparison of YouTube displaying a limited-range video in Firefox and in Chrome, and my video I uploaded a while back which has full range color. I was hoping YouTube would allow full range video again, as this Firefox bug is really annoying, plus scaling video color range on the user's end on playback instead of just maintaining full range during the encode is just stupid of YouTube.

0000071C.png


Anyway, YouTube scales it to limited range on transcode, but they keep the original files on their server in case they need to fix something. I upload full range in case they fix this.

  • input-csp=nv12:output-csp=i420 - there should be no need to set this

That is the whole point of my settings. That and possibly the other generic avcodec "colorspace" setting is what made it start running extremely fast on my machine. Specifying this explicitly is what I am theorizing skips heavy and unnecessary swscale software color conversions.

  • lossless audio - simply pointless and a waste of bandwidth, especially for youtube.

As I understand it, YouTube transcodes everything it's given, including audio, meaning encoding lossless is necessary to avoid generational decay. Also, this is useful for editing, as editing lossy audio can perpetuate generational decay.

Not sure if there's any reason to set threads to 6, by default it's 1.5 * cpu threads. so 12 in your case.

12 threads were filling up my CPU cores. 6 leaves 2 guaranteed open cores, to ensure my game can run smoothly. The only thing to check after that is whether the encoding managed to keep up with only 6 cores. I wanted to eliminate this as a problem, so this option is still here in my result. I haven't tried the line without it yet.

I did successfully record lossless 2560x1440@60 with the simple settings of OBS. No need for esoteric ffmpeg or color space parameters. It just works with the defaults.
My CPU is a i7-6700k and GPU is a GTX 1070 and the game was Guild Wars 2. A very CPU-demanding game, which occupies about 3,5 cores for itself.

The challenge isn't CPU usage, it's the harddisk throughput. I was able to record only to SSD without frame loss. To HD, such a recording fails.
The bandwidth of my recording is 140MB/s, a corresponding 1920x1200 requirement would be about 90 MB/s. Few HDs can sustain such a high write data rate for an extended amount of time. Good SSDs can do this. Key point is a continuous write data rate with no drops. One drop in data rate and the recording stalls, resulting in frame losses and/or hanging OBS.

I assume with your settings you achieve a slightly smaller video size than with utvideo, sacrificing some quality, so the HD bandwidth requirement isn't that high, so you can record to HD.

Just for fun: if you have a SSD, try recording to SSD using the lossless preset of the simple settings of OBS.

My E drive is a relatively recent Samsung SSD and has way more than enough speed. It's definitely not that. Using DxTory to record with MagicYUV RGB encoding, which results in much higher bitrate than any NV12 recording, writes at full speed with no dropped frames. I've also benchmarked to see if the numbers are ample, and they are. Encoding is sequential writing.

0000073C.png


Through testing quality for YouTube upload, I found it is best to try and match as close as possible the recommendations YouTube provides, completely disregarding the bitrate and pushing that through the roof, then using Shotcut or whatever editor of your choice to set it to a standard of 48M for bitrate at 1080p, adding a slight sharpening filter then uploading. YouTube will kill your upload times with the colour space conversion if you don't use their standard of 601 for 720p below, 709 for 1080p up, partial range and nv12 input.

Your settings are interesting though and I will test them out once I wake up from much needed sleep.

Never jump to a conclusion, especially when someone is trying to help!

I am maximizing quality on purpose, out of the desire to meet an absolutely maximum quality ideal. I realize it is not the most common use case, but there may be others who are interested in the same thing; especially professionals. YouTube isn't technically the best place for maximum-quality video, but it is the most public place to share video.

Thanks for your acknowledgement that I'm trying to help! I really appreciate it.
 
Last edited:

Rodney

Forum Moderator
I tried that (though qp instead of crf as that is what Dark Shikari (formerly main x264 dev) has always recommended to ensure the lossless flag is set correctly; discussed in #obs-dev earlier), and got slow results, hence this experimentation and solution that worked for me.
Makes absolutely no difference for me. And I have the same CPU.

I want my recordings to be editable and professionally viable, and transcoding lossy video causes generational decay that I want to avoid. I agree, though, that that would be a good option for a quick-and-dirty upload of an unedited clip.
In this case the title was a bit misleading. If you are recording for editing then higher quality is fine.

"bt470bg" is BT.601. I specify this to ensure that ffmpeg and/or libx264 is writing the same color space as it's receiving, hopefully to prevent it from invoking swscale. I could have easily used "bt709" instead if my OBS "YUV Color Space" field was set to 709. The point here is to avoid the swscale, and check for speed. This was the first test I found that had the speed I was looking for, and I can adjust that detail later.
I don't have any issues with 709 color space and crf 0. Since obs is using x264 directly it should also never invoke swscale when encoding (if you're not using ffmpeg output or rescaling in the output options).

Regarding full range, I have a full range video on YouTube that I uploaded a few years ago. It maintained its full range, and even displays in full range in Firefox, which is known to ignore the color range flag and display partial range video as is without upscaling the color range on playback. Here's the relevant bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=1161349 . I still see this bug on my computer in Firefox Nightly 55.

Here is a side-by-side comparison of YouTube displaying a limited-range video in Firefox and in Chrome, and my video I uploaded a while back which has full range color. I was hoping YouTube would allow full range video again, as this Firefox bug is really annoying, plus scaling video color range on the user's end on playback instead of just maintaining full range during the encode is just stupid of YouTube..
The "full range" youtube video you're showing as an example is limited range but unlike the other video is also available in VP9 (which youtube prefers for playback). It seems VP9 encoded videos are displayed correctly in your Firefox. In my case Firefox 52.0 x64 also displays limited range h264 video correctly. Chrome however displays full range content incorrectly as long as hardware acceleration for decoding is enabled.
 

AlexFolland

New Member
The "full range" youtube video you're showing as an example is limited range but unlike the other video is also available in VP9 (which youtube prefers for playback). It seems VP9 encoded videos are displayed correctly in your Firefox. In my case Firefox 52.0 x64 also displays limited range h264 video correctly. Chrome however displays full range content incorrectly as long as hardware acceleration for decoding is enabled.

Ooh, that's good information. Thanks. By the way, how did you determine that my video is available as VP9, so I can see for myself and pass it on if I am discussing this issue with someone in the future?
 

Rodney

Forum Moderator
Ooh, that's good information. Thanks. By the way, how did you determine that my video is available as VP9, so I can see for myself and pass it on if I am discussing this issue with someone in the future?
Just right click and select "Stats for nerds" (or something like that). It shows the mime type and codec of the video that is being played back:
1cbBBD.png


Most videos > 1000 views have VP9 available as far as I can tell.
 

AlexFolland

New Member
Thanks. If YouTube truly doesn't ever serve full range video, then I will keep range limited in my entire process.
 

AlexFolland

New Member
Thanks to this discussion, I've made some improvements and tested them, and the situation is even better now.

I've changed "YUV Color Space" to "709" and "YUV Color Range" to "Partial" in the OBS "Advanced" options area. Then, I've modified "Video Encoder Settings" to this line:

Code:
colorspace=bt709 color_range=tv qp=0 preset=ultrafast x264-params=fullrange=off:input-csp=nv12:output-csp=nv12:threads=6:tune=fastdecode

I changed the color space to bt709 because YouTube supposedly uses that for 1920×1080 resolution video and above, so minimal loss when watching with the highest resolution available.

I still explicitly set color information wherever I can to ensure the stream header is written with the correct metadata, and I went further to avoid any color conversion by specifying output-csp=nv12 rather than i420. I also added tune=fastdecode, which improves decoding speed for realtime playback later.

I've tested and this line works just as well as the previous line and is more suitable for YouTube. Thanks for all the input; especially Rodney.

By the way, the reason I use qp 0 instead of crf 0 is because there was a time when crf -12 (yes, negative twelve) was the crf value that 10-bit x264 needed for lossless. In 2011 or so, Dark Shikari of x264 explained to me in IRC that 10-bit x264 had 12 extra levels of crf below 0 to somewhat align with qp. I know libx264 here is 8-bit, but I have done it for future-proofing and from a recommendation. I'm not sure if the range of possible crf values has been shifted so that crf 0 is lossless in 10-bit x264, but I know that qp 0 will always trigger qpprime_y_zero_transform_bypass to equal 1, which is the "lossless" flag that setting qp to 0 enables. My rationale for using qp 0 over crf 0 has nothing to do with performance. It's just a sure way to enable lossless with any version of x264 if desired.
 
Last edited:
Top