Modern WebRTC max bitrate
by jib1
HTML
<table><tr>
<td><video id="v1" autoplay muted></video></td>
<td><video id="v2" autoplay></video></td></tr>
<tr><td id="v1info">0x0</td><td id="v2info">0x0</td></tr>
<tr><td id="v1brinfo">0 bps</td><td id="v2brinfo">0 bps</td></tr>
</table><button id="button">Start!</button><div id="div"></div>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
CSS
body { white-space: pre; font-family: monospace; }
JavaScript
const console = { log: msg => div.innerHTML += msg + "<br>" };
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
const update = (div, msg) => div.innerHTML = msg;
const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
button.onclick = async () => {
try {
const constraints = {video: {width: 320, height: 200}};
const stream = await navigator.mediaDevices.getUserMedia(constraints);
await setVideo(v1, v1info, stream);
const sender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await new Promise(r => pc1.oniceconnectionstatechange =
() => pc1.iceConnectionState == "connected" && r());
// get the current parameters first
const params = sender.getParameters();
if (!params.encodings) params.encodings = [{}]; // Firefox workaround!
params.encodings[0].maxBitrate = 60000;
params.encodings[0].scaleResolutionDownBy = 2;
await sender.setParameters(params);
console.log(JSON.stringify(sender.getParameters().encodings, 0, 2));
} catch (e) {
console.log(e);
}
};
const dimensions = v => v.videoWidth +"x"+ v.videoHeight;
const bitrate = (n, o) => (n - (o.old || 0)) * 8 + (o.old = n) * 0;
async function setVideo(v, vinfo, stream) {
v.srcObject = stream;
await new Promise(r => v.onloadedmetadata = r);
setInterval(() => update(vinfo, dimensions(v)), 1000);
}
const is = (stat, type) => stat.type == type;
const findStat = (map, type) => [...map.values()].find(stat => is(stat, type));
const add = (pc, can) => can && pc.addIceCandidate(can).catch(e => console.log(e));
pc1.onicecandidate = e => add(pc2, e.candidate);
pc2.onicecandidate = e => add(pc1, e.candidate);
pc2.ontrack = async e => {
await setVideo(v2, v2info, e.streams[0]);
let o1 = {}, o2 = {};
setInterval(async () => {
try {
let [s1, s2] = await Promise.all([pc1, pc2].map(pc => pc.getStats()));
s1 = findStat(s1, "outbound-rtp");
s2 = findStat(s2, "inbound-rtp");
update(v1brinfo,...