Congestion Control

woodbyte

New Member
This feature was silently introduced about a year and a half ago and can only be enabled by .ini edit (CongestionControl=1 under Video Encoding). Essentially, it will lower the bit-rate of the encoder if network strain is detected, and raise it back up when it becomes stable again.

It does not appear to be have been further developed after that initial implementation but it works well enough as is and I've used it extensively the past year. However, I recently discovered it tends to be overly aggressive at throttling, often leading to average bit-rates that are lower than what could be achieved with it off (and still no frame drops). For instance, while streaming to Twitch I've found that I can reliably stream at a constant 2500kbps with no frame drops, yet with congestion control on it will most likely settle at around 2000 instead. This represents a significant quality drop for 720p30 video, so I've been using this experimental feature less and less.

Of course, being lazy and with a fetish for automation, I'm not happy about this. Ideally I'd like to simply set my target maximum bit-rate (say, 3500 sounds good) and then let it try to reach as high as possible without frame dropping. I'd also like to have a lower bit-rate limit (lower than 2000 starts to become bit of a block fest during motion) and just accept some frame drops at that point.

This would allow me to theoretically average about 3000kbps for 24/7 Twitch streaming according to my measurements at different times of the day, and not have to worry much about it. I can't remember the last time I couldn't push 2000kbps to Twitch, and if there are intermittent connection issues that prevent it I'd rather drop a frame than lose quality.

After taking a peek at the source it looked like the currently hard-coded throttle application intervals, network strain detection thresholds and bit-rate increase/decrease values can be tweaked to better meet the objectives above. So I've been testing it with different formulas, trying to fine-tune the resulting throttling to an optimal state (highest average bit-rate without frame drops).

It's good fun and now much closer to a manually tweaked bit-rate (2300 auto vs 2500) for my connection at least, but still not quite there. So I'd like to know a few things going forward. Are there any plans to develop this feature further? Will it be a part of OBS MultiPlatform? (I don't see it under missing features). Thanks for reading.
 
Last edited:

R1CH

Forum Admin
Developer
I developed this feature, it was mostly just experimenting to see if it worked well enough. As you said the numbers are hard coded and the algorithm isn't very smart (it will rarely settle on a bitrate, it will keep going high then backing off repeatedly). I'm not the best person when it comes to algorithm design so I didn't work on it further.

For OBS MP, the network is all handled by ffmpeg as far as I'm aware, and metrics like buffer percentage used might not be visible for OBS to react on. I think this is actually the only feedback I've received about the feature, so it doesn't look like it's widely used and not really a priority to port.
 

Lain

Forum Admin
Lain
Forum Moderator
Developer
In regards to the multiplatform version, we don't use FFmpeg for output simply because their network code sucks quite badly due to lack of important windows-specific code, so we use our own custom stuff along with librtmp still. However, generally packets are less 'bursty' with the multiplatform build due to a better handling of audio/video packet interleaving so hopefully it isn't quite as necessary. In the original version it'd only output both audio and video data at every video frame, causing audio to wait until a video frame was output before sending out, and then it'd send all that data at once. Now it sends out more evenly without waiting like that, and so far the reported results of that have been great.

We haven't had time to put in the really advanced network code yet, I'm hoping it isn't quite as necessary (though it's super useful), but not much testing has been done with the windows multiplatform build at the moment so I don't know how much of an improvement it is just with the interleaving fix. If you want to try it out and see how it holds up feel free to report back your results.
 

woodbyte

New Member
@R1CH: I see, well thanks for coding it anyway. I think it's an important function as many people are able to upload to their favorite ingest at different rates throughout the day, sometimes with quite a large gap between high/low (1500kbps in my case). These kind of techniques are the only way to optimize stream quality without constantly fiddling with it.

Kinda wished it had been given a check-box under advanced settings or something. Perhaps then there might have been more feedback/improvement. Most users are likely not even aware of it, and instead follow the recommended practice of using a low, safe bit-rate guaranteed to always work without drops, but sacrificing potential quality.

I've finished a 3 hour test of my changes. Streaming to Twitch with max bit-rate set to 3500, ended up with an average of 2664kbps (95 stdev) and 0.15% dropped. The bit-rate was very similar to the stable one I found manually before and after the test (2700) and the drop-rate is what I've come to expect for long streams (maybe a bit higher, still tweaking). The low variance looks good for stability.

Adjustment intervals are increased, value adjustments vary according to current/max bit-rate and the lower limit is set to a fraction of the maximum bit-rate. The only substantial modifications made to the algorithm:
  • Use of moving averages for strain check (leads to better decisions of when to lower/increase rates);
  • Early throttling to lower limit if high strain is immediately detected (prevents lots of frame drops at start);
The overall strategy is to have fewer but more reliable adjustments over time. Particularly, the decision to increase bit-rate is crucial and only taken when there is high confidence that it won't be undone soon afterwards.

@Jim: Sure, I'll make it a part of my next test and post results here. Last I tried OBS2 it was a very early win build with crazy-low feature parity, but I enjoyed it nonetheless, especially that neat custom resizer. (very handy for those like myself stuck with weird resolutions like 1680x945). Thanks for all your efforts!
 
Last edited:

woodbyte

New Member
Tweaked the metrics a bit for better decision making, then ran a 1-hour test (see below) on the YouTube primary ingest (720p preset, maximum 4000 kbps). It is now much more stable, with no frames dropped and constant bit-rate for good chunks of time.

WQC5S.jpg


It mostly settled at 2500 kbps, having cancelled the one attempt it went higher. To confirm this was indeed the correct ceiling, I tried to manually set the bit-rate to 2700 kbps but it started dropping frames after just a couple of minutes.

OBS MultiPlatform (v0.7.2) was stable at 2700, but could not go any higher. Its less 'bursty' nature does seem to help slightly here.

NOTE: Just realized there is no time axis on that graph. Sorry about that, the whole thing is just over 1 hour long, with vertical lines showing 10 minute intervals.

UPDATE: And here are the results for a 2-hour gaming stream to Twitch (max 3500kbps). A rather frustating couple of hours... But for now I'm rather happy with the analysis/throttling in place. There were a few frame drops during one of the congestion spikes, but still only accounting for 0.03% of total sent.

PTz1r.jpg
 
Last edited:

R1CH

Forum Admin
Developer
@woodbyte: Is the new algorithm available anywhere? The results you posted look pretty good, it would be nice to implement it into OBS and perhaps make it available as a UI option if it works well.
 
Top