peerjs icon indicating copy to clipboard operation
peerjs copied to clipboard

Video bitrate

Open timikrutik opened this issue 3 years ago • 5 comments

Is it possible to check the channel bandwidth somehow, and change the video bitrate depending on it? Which method in the script of PeerJS should I change to do this? (or I need to create it?)

timikrutik avatar May 03 '21 19:05 timikrutik

I have the same question...

rodrigomarcell avatar Jul 18 '21 16:07 rodrigomarcell

a work around could be change video resolution from the Sender... and set a fixed video size on receiver.....

It will work.. but not a good way...

rodrigomarcell avatar Aug 28 '21 19:08 rodrigomarcell

Same question here but for audio.

YoussF avatar Oct 24 '21 21:10 YoussF

Something I've been looking at for a solution I've created for my company.

You can set sender's video resolution using the media constraints API. Whether or not you can do this in real-time, I'm not sure - simply because I haven't tried; the use case for me is only for setting the constraint beforehand.

You can, however, update the bitrate in real time by accessing the call's underlying media parameters. Here's a snippet from part of our solution:

// Assuming that 'call' has already been defined, as a Peer.MediaConnection from the result of 'Peer.call()',
// and that this is a video-only call, for simplicity - though the same logic applies to the audio sender.

const vid_sender = call.peerConnection.getSenders().filter(s => s.track?.kind == "video")[0]
const vid_params = vid_sender.getParameters()
if ("degradationPreference" in vid_params) {
    // So that the webrtc implementation doesn't alter the framerate - this is optional
    vid_params.degradationPreference = "maintain-framerate"
}

// Set a base encoding setup if there isn't one already
vid_params.encodings == vid_params.encodings ?? [{ maxBitrate: 0 }]
vid_params.encodings[0].maxBitrate = 4000000 // For a 4mbps stream; the value is in bps
// Set the new bitrate
await (vid_sender.setParameters(vid_params))

It's not widely-supported to be able to measure the 'available' bandwidth of a given connection, as this is usually only determinable by flooding the pipe with traffic and seeing when you max out. You can, though, measure the bitrate of the stream you're sending, and then compare it against your target bitrate as part of a feedback loop to find the optimal bitrate for your connection. Note that webrtc can do this for you, if you don't want to have to manage the bitrate manually.

To do this, check out the RTCPeerConnection.getStats() method, and look for the report with the type outbound-rtp, which gives you an RtcRtpSentStreamStats report (amongst other things.) This tells you that amount of bytes sent on that stream. Measuring this every second gives you a bitrate that you can compare against your target. The page above has a nice example of how to use the report.

calmcl1 avatar Feb 22 '22 15:02 calmcl1

I too have this question. I haven't yet tried the solution provided by @calmcl1, but it seems that the recipient negotiates a lower bitrate with the sender? Everywhere else I've looked seems to be pointing to a different approach, but I've not quite figured it out:

In the docs there is an Options object you can pass to both .call() and .answer() that contains a sdpTransform function. Supposedly this can be used to set the bitrate at the time of calling.

This StackOverflow question has an answer related to raw WebRTC that I suppose could work combined with the options object, but there are literally 0 examples of how to work this function anywhere.

const videobitrate = 20000;
var offer = pc.localDescription;
// Set bandwidth for video
offer.sdp = offer.sdp.replace(/(m=video.*\r\n)/g, `$1b=AS:${videobitrate}\r\n`);
pc.setLocalDescription(offer);

Would really appreciate a definitive answer on how to lower the bitrate for a data stream

Knockturnal avatar Jan 07 '23 09:01 Knockturnal