text: const startButton = document.getElementById('startButton');
  const callButton = document.getElementById('callButton');
  const hangupButton = document.getElementById('hangupButton');
  const stopButton = document.getElementById('stopButton');
  
  callButton.disabled = true;
  hangupButton.disabled = true;
  stopButton.disabled = true;
  
  startButton.addEventListener('click', start);
  callButton.addEventListener('click', call);
  hangupButton.addEventListener('click', hangup);
  stopButton.addEventListener('click', stop);
  
  let startTime;
  const localVideo = document.getElementById('localVideo');
  const remoteVideo = document.getElementById('remoteVideo');
  
  let localStream;
  let remoteStream;
  let pc1;
  let pc2;
  
  function start() {
    startButton.disabled = true;
    stopButton.disabled = false;
  
    navigator.mediaDevices
      .getUserMedia({
        audio: true,
        video: true,
      })
      .then(gotStream)
      .catch(gotStreamError);
  }
  
  function call() {
    callButton.disabled = true;
    hangupButton.disabled = false;
    stopButton.disabled = true;
  
    startTime = window.performance.now();
  
    pc1 = new RTCPeerConnection(null);
    pc1.addEventListener('icecandidate', onIceCandidate);
  
    pc2 = new RTCPeerConnection(null);
    pc1.addEventListener('icecandidate', onIceCandidate);
    pc2.addEventListener('addstream', onAddStream);
  
    pc1.addStream(localStream);
  
    pc1.createOffer().then(onCreateOfferSuccess).catch(onCreateOfferError);
  }
  
  function stop() {
    const localTracks = localStream.getVideoTracks();
    localTracks.forEach(function (localTrack) {
      localTrack.stop();
    });
    startButton.disabled = false;
    stopButton.disabled = true;
    callButton.disabled = true;
  }
  
  function gotStream(stream) {
    localVideo.srcObject = stream;
    localStream = stream;
    callButton.disabled = false;
  }
  
  function gotStreamError(err) {
    alert('getUserMedia() error: ' + err.message);
  }
  
  function onIceCandidate(e) {
    getOtherPc(e.target)
      .addIceCandidate(e.candidate)
      .then(function () {
        onAddIceCandidateSuccess(e.target);
      })
      .catch(function (err) {
        onAddIceCandidateError(e.target, err);
      });
  }
  
  function getOtherPc(pc) {
    return pc === pc1 ? pc2 : pc1;
  }
  
  function onAddIceCandidateSuccess(pc) {
    console.log('onAddIceCandidateSuccess', pc);
  }
  
  function onAddIceCandidateError(pc, error) {
    console.log('onAddIceCandidateError', pc, error);
  }
  
  function onAddStream(e) {
    const mediaStream = e.stream;
    remoteVideo.srcObject = mediaStream;
    remoteStream = mediaStream;
  }
  
  function onCreateOfferSuccess(desc) {
    pc1
      .setLocalDescription(desc)
      .then(onSetLocalDescriptionSuccess)
      .catch(onSetDescriptionError);
    pc2
      .setRemoteDescription(desc)
      .then(onSetRemoteDescriptionSuccess)
      .catch(onSetDescriptionError);
    pc2.createAnswer().then(onCreateAnswerSuccess).catch(onCreateAnswerError);
  }
  
  function onSetLocalDescriptionSuccess() {
    console.log('onSetLocalDescriptionSuccess');
  }
  
  function onSetDescriptionError(error) {
    console.log('onSetDescriptionError', error);
  }
  
  function onSetRemoteDescriptionSuccess() {
    console.log('onSetRemoteDescriptionSuccess');
  }
  
  function onCreateAnswerSuccess(desc) {
    pc2
      .setLocalDescription(desc)
      .then(onSetLocalDescriptionSuccess)
      .catch(onSetDescriptionError);
    pc1
      .setRemoteDescription(desc)
      .then(onSetRemoteDescriptionSuccess)
      .catch(onSetDescriptionError);
  }
  
  function onCreateAnswerError(error) {
    console.log('onCreateAnswerError', error);
  }
  
  function onCreateOfferError(error) {
    console.log('onCreateOfferError', error);
  }
  
  function hangup() {
    pc1.close();
    pc2.close();
    pc1 = null;
    pc2 = null;
  
    hangupButton.disabled = true;
    callButton.disabled = false;
    stopButton.disabled = false;
  }
  