前端使用WebRTC———HelloWorld

450 阅读2分钟

什么是webrtc?

借助 WebRTC,您可以将实时通信功能添加到基于开放标准运行的应用程序。它支持在对等点之间发送视频、语音和通用数据,允许开发人员构建强大的语音和视频通信解决方案.

重点: 点对点发送视频、语音和数据。

如何在浏览器中使用webrtc?

浏览器中可以通过一下方法判断当前浏览器是否支持webrtc

   window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection

简单的Demo

先从最简单的例子开始,我们在一个网页中,通过两个RTCPeerConnection对象来建立一个连接,一个RTCPeerConnection(pc_pub)对象发送视频和语音,另一个RTCPeerConnection(pc_sub)对象接收视频和语音。

效果

image.png

此处使用了Safri的虚拟摄像头。可以避免使用真实摄像头还要露脸的尴尬。可以看到左侧是本地采集的画面,右侧是接收到的视频画面。中间有大概几十毫秒的延迟。

流程

sequenceDiagram
Note left of 页面 : 点击打开本地摄像头
页面 ->> 页面: 获取摄像头,并显示

Note left of 页面 : 点击建立连接

pc_pub ->> pc_pub: addEventListener,监听icecandidate
pc_sub ->> pc_sub: addEventListener,监听icecandidate
pc_sub ->> pc_sub: addEventListener,监听track

Note left of pc_pub : 对推流的PeerConnection添加要推流的内容
pc_pub ->> pc_pub: addTrack

Note left of pc_pub : 生成offer
pc_pub ->> pc_pub: createOffer,得到offer

Note left of pc_pub : 将offer的内容设置到浏览器中
pc_pub ->> pc_pub: setLocalDescription,设置offer

Note left of pc_sub : 订阅的PeerConnection将推流的Peerconnection的offer设置到浏览器中
pc_pub ->> pc_sub: setRemoteDescription,设置offer

Note left of pc_sub : 订阅的Peerconnection生成Answer
pc_sub ->> pc_sub: createAnswer,得到answer

Note left of pc_sub : 订阅的Peerconnection将Answer设置到浏览器中
pc_sub ->> pc_sub: setLocalDescription,设置answer

Note left of pc_sub : 推流的Peerconnection将Answer设置到浏览器中
pc_sub ->> pc_pub: setRemoteDescription,设置answer

在上面的流程图中,pub_pc表示推流的对象(PeerConnection), sub_pc表示订阅的对象(PeerConnection)。

总结

先尝试跑通这个简单的Demo,可以看从页面中看到本地预览、推拉流的效果。如果你是第一次接触webrtc,上面的流程中有很多看不懂的名字和方法可以先忽略它们。

代码

可以直接从gittee获取源代码,也可以直接使用下面的代码

<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>webrtc连接</title>
</head>

<body>
  <video id="localStream" style="width: 320px; height: 240px;" autoplay muted></video>
  <video id="remoteStream" style="width: 320px; height: 240px;" autoplay muted> </video>
  <button id="deviceBtn">打开本地摄像头</button>
  <button id="startBtn">建立连接</button>
  <script>
    let localStream = null;
    let localVideo = document.getElementById("localStream");
    let remoteVideo = document.getElementById("remoteStream")
    let deviceBtn = document.getElementById("deviceBtn");
    let startBtn = document.getElementById("startBtn");

    let pc_pub = new RTCPeerConnection();
    let pc_sub = new RTCPeerConnection();

    deviceBtn.addEventListener("click", () => {
      navigator.mediaDevices.getUserMedia({ video: true }).then((mediastream) => {
        localStream = mediastream;
        localVideo.srcObject = mediastream;
      })
    })

    startBtn.addEventListener("click", () => {
      pc_pub.addTrack(localStream.getVideoTracks()[0], localStream);
      pc_pub.createOffer().then((offer) => {
        pc_pub.setLocalDescription(offer).then(() => {
          pc_sub.setRemoteDescription(offer).then(() => {
            pc_sub.createAnswer().then((answer) => {
              pc_sub.setLocalDescription(answer).then(() => {
                pc_pub.setRemoteDescription(answer).then(() => {

                })
              })
            })
          })
        })
      })
    })

    pc_pub.addEventListener('icecandidate', (event) => {
      if (event.candidate) {
        pc_sub.addIceCandidate(event.candidate);
      }
    })

    pc_sub.addEventListener('icecandidate', (event) => {
      if (event.candidate) {
        pc_pub.addIceCandidate(event.candidate);
      }
    })

    pc_sub.addEventListener('track', (event) => {
      remoteVideo.srcObject = event.streams[0];
    })
  </script>
</body>

其他

如果你也是专注前端多媒体或者对前端多媒体感兴趣,可以关注前端多媒体公众号

qrcode_for_gh_1f34d1ba9020_258.jpg