Async removetrack

by jib1

HTML

<script src="https://webrtchacks.github.io/adapter/adapter-latest.js"></script>
<video id="video1" width="160" height="120" autoplay muted></video>
<video id="video2" width="160" height="120" autoplay></video><br>
<button id="removeAudio">Remove Audio</button>
<button id="removeVideo">Remove Video</button>
<div id="div"></div>

JavaScript

const console = { log: msg => div.innerHTML += msg + "<br>" };
const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();

let videoSender, audioSender;

(async () => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
    audioSender = pc1.addTrack(stream.getAudioTracks()[0], stream);
    videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
    video1.srcObject = stream;
  } catch (e) {
    console.log(e);
  }
})();

removeAudio.onclick = () => pc1.removeTrack(audioSender);
removeVideo.onclick = () => pc1.removeTrack(videoSender);

pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc1.oniceconnectionstatechange = () => console.log(pc1.iceConnectionState);

pc1.onnegotiationneeded = async () => {
  try {
    await pc1.setLocalDescription(await pc1.createOffer());
    await pc2.setRemoteDescription(pc1.localDescription);
    await pc2.setLocalDescription(await pc2.createAnswer());
    await pc1.setRemoteDescription(pc2.localDescription);
  } catch (e) {
    console.log(e);
  }
}

pc2.ontrack = ({track, streams: [stream]}) => {
  track.onunmute = () => {
    if (!video2.srcObject) video2.srcObject = stream;
  };
  stream.onremovetrack = ({track}) => {
    console.log(`${track.kind} track was removed.`);
    if (!stream.getTracks().length) {
      console.log(`stream ${stream.id} emptied (effectively removed).`);
    }
  };
};