Article async WebRTC tab stats demo

by jib1

HTML

<video id="video" width="320" height="240" autoplay></video><br>
<button id="call">Call!</button>
<label><input type="checkbox" onclick="mute()">mute</label>
<div id="div"></div><br><div id="statsdiv"></div>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="https://rawgit.com/jan-ivar/localSocket/master/localSocket.js"></script>

JavaScript

let pc = new RTCPeerConnection(), log = msg => div.innerHTML += msg + "<br>";

pc.onnegotiationneeded = async e => {
  await pc.setLocalDescription(await pc.createOffer());
  sc.send({sdp: pc.localDescription});
}
pc.onaddstream = e => video.srcObject = e.stream;
pc.onicecandidate = ({candidate}) => sc.send({candidate});

var sc = new localSocket();
sc.onmessage = async ({data: {sdp, candidate}}) => {
  if (sdp) {
    await pc.setRemoteDescription(sdp);
    if (pc.signalingState != "stable") {
      await pc.setLocalDescription(await pc.createAnswer());
      sc.send({sdp: pc.localDescription});
    }
  } else if (candidate) await pc.addIceCandidate(candidate);
}

call.onclick = async () => {
  try {
    video.srcObject = await navigator.mediaDevices.getUserMedia({video:true, audio:true});
    pc.addStream(video.srcObject);
  } catch (e) {
    log(e);
  }
};

(async () => {
  try {
    await new Promise(resolve => pc.oniceconnectionstatechange =
        () => pc.iceConnectionState == "connected" && resolve());
    while (true) {
      let html = "", stats = await pc.getStats();
      for (let stat of stats.values()) {
        if (stat.isRemote) continue;
        switch (stat.type) {
          case "outbound-rtp": {
            html += dumpOutbound(stat) + "<br>";
            let rtcp = stats.get(stat.remoteId);
            if (rtcp) html += "RTCP " + dumpInbound(rtcp) + "<br>";
            break;
          }
          case "inbound-rtp": {
            html += dumpInbound(stat) + "<br>";
            let rtcp = stats.get(stat.remoteId);
            if (rtcp) html += "RTCP " + dumpOutbound(rtcp) + "<br>";
            break;
          }
        }
      }
      update(statsdiv, `<small>${html}</small>`);
      await wait(100);
    }
  } catch (e) {
    log(e);
  }
})();

var mute = () => video.srcObject.getTracks().forEach(t => t.enabled = !t.enabled);
var update = (div, msg) => div.innerHTML = msg;
var wait = ms => new Promise(resolve => setTimeout(resolve,...