WEB RTC 直播Demo

发布时间 2023-10-06 00:38:41作者: havelearned

打开两个浏览器测试,手动设置SDP(offer),类似http三次握手

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div>
  <button id="test_div">获取摄像头和麦克风</button>
</div>
<video id="localVideo" autoplay controls></video>
<div>
  <video id="remoteVideo" autoplay controls></video>
</div>
<div>
  <button id="test_rtcConnection">创建RTC连接</button>
  <button id="test_localStream">本地流绑定</button>
</div>
<div>
  <button id="test_offer">创建offer</button>
</div>

<div>
  <textarea id="test_textarea" rows="20" cols="100"></textarea>
</div>
<div>
  <button id="test_setRmote">设置远程描述</button>
  <button id="test_setAnwer">创建Answer</button>
</div>
<div>
  <button id="test_CandiDate">添加候选</button>
</div>

</body>

<script>
  const localVideo = document.getElementById('localVideo')
  const remoteVideo = document.getElementById('remoteVideo')
  const test_offer = document.getElementById('test_offer')
  const test_textarea = document.getElementById('test_textarea')
  const test_setRmote = document.getElementById('test_setRmote')
  const test_rtcConnection = document.getElementById('test_rtcConnection')
  const test_setAnwer = document.getElementById('test_setAnwer')
  const test_CandiDate = document.getElementById('test_CandiDate')
  const test_localStream = document.getElementById('test_localStream')


  let localStream = undefined;
  let pc = undefined;

  test_localStream.addEventListener("click", () => {
    addLocalSteamToRtcConnection()
  })
  test_rtcConnection.addEventListener("click", () => {
    createRtcConnection()
  })

  test_CandiDate.addEventListener('click', () => {
    addCandidate()
  })

  document.getElementById('test_div').addEventListener('click', function () {
    getMediaDevices();

  }, true)
  test_offer.addEventListener("click", function () {
    createOffer();
  })

  test_setRmote.addEventListener("click", function () {
    setRemoteDesc()
  })

  test_setAnwer.addEventListener('click', function () {
    createAnswer()
  })


  /**
   * 获取摄像头,设置video媒体,保存本地流
   */
  const getMediaDevices = () => {
    navigator.mediaDevices.getDisplayMedia({
      video: {width: 400, height: 400},
      audio: false,
    }).then(stream => {
      console.log("得到本地流", stream)
      localVideo.srcObject = stream;
      localStream = stream;
    })
  }

  /**
   * 创建RTC连接,设置公共服务器,监控候选地址
   * 接收远程流,
   */
  const createRtcConnection = () => {
    pc = new RTCPeerConnection({
      iceServers: [{
        urls: 'stun:stun.l.google.com:19302'
      }]
    })
    console.log("rtc创建成功", pc)

    // 候选地址
    pc.onicecandidate = ev => {
      if (ev.candidate) {
        console.log("候选地址", JSON.stringify(ev.candidate))
      }
    }

    // 接收远程媒体流事件
    pc.ontrack = e => {
      remoteVideo.srcObject = e.streams[0]
    }
  }

  /**
   * 添加候选者
   */
  const addCandidate = () => {
    const ce = JSON.parse(test_textarea.value)
    pc.addIceCandidate(new RTCIceCandidate(ce))
    console.log("添加候选成功", ce)

  }

  /**
   * 创建offer,设置本地描述
   */
  const createOffer = () => {
    pc.createOffer({offerToReceiveVideo: true, offerToReceiveAudio: true}).then(sdp => {
      console.log("offer", JSON.stringify(sdp))
      pc.setLocalDescription(sdp)

    })
  }

  /**
   * 得到远程描述,设置远程描述
   */
  const setRemoteDesc = () => {
    const desc = JSON.parse(test_textarea.value)
    pc.setRemoteDescription(new RTCSessionDescription(desc))
    console.log("设置远程描述成功", desc)
  }

  /**
   * 接收到:候选者sdp,设置候选者
   */
  const createAnswer = () => {
    pc.createAnswer({offerToReceiveVideo: true, offerToReceiveAudio: true}).then(sdp => {
      console.log("answer", JSON.stringify(sdp))
      pc.setLocalDescription(sdp)

    })
  }

  /**
   * video媒体和本地流绑定
   */
  const addLocalSteamToRtcConnection = () => {
    let stream = localStream
    localStream.getTracks().forEach(track => {
      pc.addTrack(track, stream)
    })
    console.log("绑定本地流成功")
  }


</script>
</html>