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,...