WebRTC 使用入门

在维护开放、不受阻碍的网络环境的长期战争中,WebRTC 可成为新的战线。

JavaScript 发明者 Brendan Eich

想象一下,您的手机、电视和计算机可以在一个通用平台上通信。想象一下,在您的 Web 应用中添加视频聊天和点对点数据共享非常简单。这就是 WebRTC 的愿景。

想试试吗?WebRTC 在桌面设备和移动设备上均可使用,可通过 Google Chrome、Safari、Firefox 和 Opera 使用。建议您从 appr.tc 中的一款简单视频聊天应用着手:

  1. 在浏览器中打开 appr.tc
  2. 点击加入即可加入聊天室,并让应用使用您的摄像头。
  3. 在新标签页中打开网页末尾显示的网址,最好在其他计算机上打开网址。

快速入门

没时间阅读本文或只想获取代码?

或者,您也可以直接跳转到 WebRTC Codelab,这是一份分步指南,介绍了如何构建完整的视频聊天应用,包括一个简单的信令服务器。

WebRTC 简史

网络面临的最后一大挑战之一就是要通过语音和视频实现人类通信,即实时通信(简称 RTC)。在 Web 应用中,RTC 应该和在文本输入中输入文本一样自然。没有它,您在创新和开发新的互动方式方面的能力会受到限制。

长期以来,RTC 一直是企业和复杂的行业,需要内部许可或开发昂贵的音频和视频技术。将 RTC 技术与现有内容、数据和服务集成在一起一直困难且耗时,尤其是在 Web 上。

Gmail 视频聊天从 2008 年开始流行,并于 2011 年推出了环聊,它采用了 Google Talk(Gmail 也是如此)。Google 收购了 GIPS,这家公司开发了许多 RTC 所需的组件,例如编解码器和回声消除技术。为了确保行业共识,Google 将 GIPS 开发的技术开源,并与互联网工程任务组 (IETF) 和万维网联盟 (W3C) 的相关标准机构进行了合作。2011 年 5 月,爱立信构建了首个 WebRTC 实现

WebRTC 实施了无插件的实时视频、音频和数据通信的开放标准。我们的需求是真实的:

  • 许多网络服务都使用 RTC,但需要下载功能、原生应用或插件。包括 Skype、Facebook 和 Hangouts。
  • 下载、安装和更新插件是一个复杂、容易出错且令人厌烦的过程。
  • 插件难以部署、调试、问题排查、测试和维护,并且可能需要获得许可以及与复杂的、昂贵的技术集成。从一开始说服人们安装插件通常是比较困难的!

WebRTC 项目的指导原则是,其 API 应开源、免费、标准化,内置于网络浏览器中,并且比现有技术更高效。

我们现在处于什么状态?

WebRTC 可用于各种应用,例如 Google Meet。WebRTC 也已与 WebKitGTK+ 和 Qt 原生应用集成。

WebRTC 实现了以下三个 API: - MediaStream(也称为 getUserMedia) - RTCPeerConnection - RTCDataChannel

我们在以下两个规范中定义这些 API:

Chrome、Safari、Firefox、Edge 和 Opera 在移动设备和桌面设备上均支持这三种 API。

getUserMedia:如需查看演示和代码,请参阅 WebRTC 示例或尝试 Chris Wilson 的出色示例,这些示例使用 getUserMedia 作为网络音频的输入。

RTCPeerConnection:如需查看简单演示和功能齐全的视频聊天应用,请分别参阅 WebRTC 示例对等连接appr.tc。此应用使用 adapter.js(Google 在 WebRTC 社区的帮助下维护的一个 JavaScript shim)去除了浏览器差异和规范变更。

RTCDataChannel:如需了解此操作的实际效果,请参阅 WebRTC 示例,查看其中一个数据通道演示。

WebRTC Codelab 介绍了如何使用所有这三个 API 来构建用于视频聊天和文件共享的简单应用。

您的第一个 WebRTC

WebRTC 应用需要执行以下几项操作:

  • 获取流式音频、视频或其他数据。
  • 获取 IP 地址和端口等网络信息,并与其他 WebRTC 客户端(称为对等)交换这些信息以实现连接,即使通过 NAT 和防火墙也能实现。
  • 协调信号通信,以报告错误以及启动或关闭会话。
  • 交换有关媒体和客户端功能的信息,例如分辨率和编解码器。
  • 传输流式音频、视频或数据。

为了获取和传输流式数据,WebRTC 实现了以下 API:

  • MediaStream 获取对数据流(例如通过用户的摄像头和麦克风)的访问权限。
  • RTCPeerConnection 支持通过加密和带宽管理设施进行音频或视频通话。
  • RTCDataChannel 支持通用数据的点对点通信。

(稍后会详细讨论 WebRTC 的网络和信号方面。)

MediaStream API(也称为 getUserMedia API)

MediaStream API 表示同步的媒体流。例如,从摄像头和麦克风输入获取的视频流已同步视频轨道和音频轨道。(请勿将 MediaStreamTrack<track> 元素混淆,后者是完全不同的内容。)

理解 MediaStream API 可能最简单的方法就是大体观察它:

  1. 在浏览器中,转到 WebRTC 示例 getUserMedia
  2. 打开控制台。
  3. 检查全局范围内的 stream 变量。

每个 MediaStream 都有一个输入(可能是由 getUserMedia() 生成的 MediaStream)和一个输出(可能会传递给视频元素或 RTCPeerConnection)。

getUserMedia() 方法接受 MediaStreamConstraints 对象参数,并返回解析为 MediaStream 对象的 Promise

每个 MediaStream 都有一个 label,例如 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'getAudioTracks()getVideoTracks() 方法会返回一个 MediaStreamTrack 数组。

对于 getUserMedia 示例,stream.getAudioTracks() 会返回一个空数组(因为没有音频),并且如果已连接一个可正常使用的摄像头,stream.getVideoTracks() 会返回一个数组,其中包含一个表示来自该摄像头的视频流的 MediaStreamTrack。每个 MediaStreamTrack 都有一个种类('video''audio')、label(类似于 'FaceTime HD Camera (Built-in)'),表示一个或多个音频或视频通道。在该示例中,视频轨道只有一个,没有音频,但很容易想到,应用场景更多,例如从前置摄像头、后置摄像头、麦克风获取视频流的聊天应用,以及共享其屏幕的应用。

您可以通过设置 srcObject 属性MediaStream 附加到视频元素。以前,这是通过将 src 属性设置为使用 URL.createObjectURL() 创建的对象网址来实现的,但此功能已被弃用

getUserMedia 也可用作 Web Audio API 的输入节点

// Cope with browser differences.
let audioContext;
if (typeof AudioContext === 'function') {
  audioContext = new AudioContext();
} else if (typeof webkitAudioContext === 'function') {
  audioContext = new webkitAudioContext(); // eslint-disable-line new-cap
} else {
  console.log('Sorry! Web Audio not supported.');
}

// Create a filter node.
var filterNode = audioContext.createBiquadFilter();
// See https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#BiquadFilterNode-section
filterNode.type = 'highpass';
// Cutoff frequency. For highpass, audio is attenuated below this frequency.
filterNode.frequency.value = 10000;

// Create a gain node to change audio volume.
var gainNode = audioContext.createGain();
// Default is 1 (no change). Less than 1 means audio is attenuated
// and vice versa.
gainNode.gain.value = 0.5;

navigator.mediaDevices.getUserMedia({audio: true}, (stream) => {
  // Create an AudioNode from the stream.
  const mediaStreamSource =
    audioContext.createMediaStreamSource(stream);
  mediaStreamSource.connect(filterNode);
  filterNode.connect(gainNode);
  // Connect the gain node to the destination. For example, play the sound.
  gainNode.connect(audioContext.destination);
});

基于 Chromium 的应用和扩展程序也可包含 getUserMedia。向清单添加 audioCapture 和/或 videoCapture 权限后,只有在安装时才能请求和授予一次权限。此后,系统便不会要求用户授予摄像头或麦克风使用权限。

只需为 getUserMedia() 授予权限一次。首次,浏览器的信息栏中会显示“允许”按钮。由于 getUserMedia() 的 HTTP 访问权限属于强大的功能,因此 Chrome 已于 2015 年底弃用了该功能。

其意图可能是为任何流式数据源(而不仅仅是摄像头或麦克风)启用 MediaStream。这将允许从存储的数据或任意数据源(例如传感器或其他输入)进行流式传输。

getUserMedia() 与其他 JavaScript API 和库结合使用,能够真正发挥作用:

  • Webcam Toy 是一款 Photobooth 应用,它使用 WebGL 为可在本地分享或保存的照片添加各种奇特的奇妙效果。
  • FaceKat 是一款使用 headtrackr.js 构建的面部跟踪游戏。
  • ASCII Camera 使用 Canvas API 生成 ASCII 图片。
。 <ph type="x-smartling-placeholder">
</ph> 由 idevelop.ro/ascii-camera 生成的 ASCII 图片
gUM ASCII 图片!

限制条件

限制条件可用于为 getUserMedia() 设置视频分辨率值。这样还可以支持其他约束条件,例如宽高比;朝向模式(前置或后置摄像头);帧速率、高度和宽度和 applyConstraints() 方法。

如需查看示例,请参阅 WebRTC 示例 getUserMedia:选择分辨率

例如,如果请求分辨率不可用,则设置禁止的约束条件值会给出 DOMExceptionOverconstrainedError。如需查看实际操作,请参阅 WebRTC 示例 getUserMedia:选择分辨率进行演示。

屏幕和标签页截取

借助 Chrome 应用,您还可以通过 chrome.tabCapturechrome.desktopCapture API 分享单个浏览器标签页或整个桌面的实时视频。(如需查看演示和更多信息,请参阅通过 WebRTC 共享屏幕。这篇文章是几年前发布的,但仍然很有趣。)

您还可以使用实验性 chromeMediaSource 约束条件在 Chrome 中使用屏幕截图作为 MediaStream 来源。请注意,屏幕截图需要使用 HTTPS,并且只应用于开发,因为此功能是通过命令行标志启用的(如博文中所述)。

信号:会话控制、网络和媒体信息

WebRTC 使用 RTCPeerConnection 在浏览器(也称为对等端)之间传输流式数据,但还需要一种机制来协调通信并发送控制消息,此过程称为信令。WebRTC 指定信令方法和协议。信号不是 RTCPeerConnection API 的一部分。

相反,WebRTC 应用开发者可以选择他们偏好的任何消息传递协议(例如 SIP 或 XMPP),以及任何适当的双工(双向)通信通道。appr.tc 示例使用 XHR 和通道 API 作为信号机制。Codelab 使用在 Node 服务器上运行的 Socket.io

信号用于交换三种类型的信息:

  • 会话控制消息:用于初始化或关闭通信以及报告错误。
  • 网络配置:对于外界,您计算机的 IP 地址和端口是什么?
  • 媒体功能:您的浏览器及其要通信的浏览器可处理哪些编解码器和分辨率?

必须先成功完成通过信号传输的信息交换,然后才能开始点对点流式传输。

例如,假设爱丽丝想要与小波通信。以下是 W3C WebRTC 规范中的代码示例,其中显示了信令流程的实际应用。该代码假定存在在 createSignalingChannel() 方法中创建的某种信令机制。另请注意,在 Chrome 和 Opera 上,系统当前显示的是 RTCPeerConnection 前缀。

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    // Send the offer to the other peer.
    signaling.send({desc: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

// Once remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
  // Don't set srcObject again if it is already set.
  if (remoteView.srcObject) return;
  remoteView.srcObject = event.streams[0];
};

// Call start() to initiate.
async function start() {
  try {
    // Get local stream, show it in self-view, and add it to be sent.
    const stream =
      await navigator.mediaDevices.getUserMedia(constraints);
    stream.getTracks().forEach((track) =>
      pc.addTrack(track, stream));
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({desc, candidate}) => {
  try {
    if (desc) {
      // If you get an offer, you need to reply with an answer.
      if (desc.type === 'offer') {
        await pc.setRemoteDescription(desc);
        const stream =
          await navigator.mediaDevices.getUserMedia(constraints);
        stream.getTracks().forEach((track) =>
          pc.addTrack(track, stream));
        await pc.setLocalDescription(await pc.createAnswer());
        signaling.send({desc: pc.localDescription});
      } else if (desc.type === 'answer') {
        await pc.setRemoteDescription(desc);
      } else {
        console.log('Unsupported SDP type.');
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

首先,小丽和小刚交换网络信息。(“查找候选定位设置”是指使用 ICE 框架查找网络接口和端口的过程。)

  1. Alice 创建了一个带有 onicecandidate 处理程序的 RTCPeerConnection 对象,该对象会在网络候选网络可用时运行。
  2. Alice 通过其使用的任何信令信道(如 WebSocket 或其他某种机制)将序列化的候选人数据发送给 Bob。
  3. 当 Bob 收到来自 Alice 的候选消息时,会调用 addIceCandidate 将该候选者添加到远程对等设备说明中。

WebRTC 客户端(在本例中也称为“对等设备”,或本例中的 Alice 和 Bob)还需要确定和交换本地和远程音频和视频媒体信息,例如分辨率和编解码器功能。系统通过使用会话描述协议 (SDP) 交换报价应答来发出交换媒体配置信息的信号:

  1. Alice 运行 RTCPeerConnection createOffer() 方法。系统会向此字段的返回传递 RTCSessionDescription - Alice 的本地会话说明。
  2. 在该回调中,Alice 使用 setLocalDescription() 设置本地说明,然后通过 Bob 的信号通道将此会话说明发送给 Bob。请注意,在调用 setLocalDescription() 之前,RTCPeerConnection 不会开始收集候选项。这已编码在 JSEP IETF 草案中。
  3. Bob 使用 setRemoteDescription() 将 Alice 发送给他的说明设置为远程说明。
  4. Bob 运行 RTCPeerConnection createAnswer() 方法,向其传递从 Alice 获取的远程说明,以便生成与 Alice 兼容的本地会话。系统会向 createAnswer() 回调传递 RTCSessionDescription。Bob 将其设为本地描述并将其发送给 Alice。
  5. 当 Alice 获得 Bob 的会话说明后,使用 setRemoteDescription 将该说明设置为远程说明。
  6. ping!

RTCSessionDescription 对象是符合会话描述协议 (SDP) 的 blob。序列化后,SDP 对象如下所示:

v=0
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 103 104 0 8 106 105 13 126

// ...

a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh810

网络和媒体信息的获取和交换可以同时完成,但两个流程必须都完成,对等设备之间的音频和视频串流才能开始。

之前介绍的优惠/应答架构称为 JavaScript 会话建立协议 (JSEP)。(在爱立信的演示视频中,我们针对其首次 WebRTC 实施展示了一段优秀的动画,介绍信令和流式传输过程。)

<ph type="x-smartling-placeholder">
</ph> JSEP 架构图
JSEP 架构

信令过程成功完成后,数据可以直接在调用方和被调用方之间以点对点的方式流式传输;如果失败,可通过中间中继服务器流式传输(稍后会详细介绍)。流式传输是 RTCPeerConnection 的工作。

RTCPeerConnection

RTCPeerConnection 是一个 WebRTC 组件,用于处理对等方之间的流式数据之间稳定而高效的通信。

下面的 WebRTC 架构图展示了 RTCPeerConnection 的作用。您会发现,绿色部分很复杂!

<ph type="x-smartling-placeholder">
</ph> WebRTC 架构图
WebRTC 架构(来自 webrtc.org

从 JavaScript 的角度来看,这个图中需要理解的主要内容是,RTCPeerConnection 可以保护 Web 开发者免受隐含的无数复杂性的侵扰。为了实现实时通信,WebRTC 使用的编解码器和协议做了大量的工作,即使在不可靠的网络上也不例外:

  • 丢包隐藏
  • 回声消除
  • 带宽自适应
  • 动态抖动缓冲
  • 自动增益控制
  • 降噪和抑制
  • 图片清理

之前的 W3C 代码从信号角度展示了 WebRTC 的简化示例。以下是两个正常运行的 WebRTC 应用的演示。第一个是一个简单的示例,用于演示 RTCPeerConnection,第二个是完全可操作的视频聊天客户端。

不使用服务器的 RTCPeerConnection

以下代码取自 WebRTC 示例对等连接,该示例在一个网页上包含本地和远程 RTCPeerConnection(以及本地和远程视频)。这不会构成任何非常有用的内容(调用方和被调用方位于同一页面上),但确实会使 RTCPeerConnection API 的运行变得更加清晰,因为页面上的 RTCPeerConnection 对象可以直接交换数据和消息,而无需使用中间信号机制。

在此示例中,pc1 表示本地对等方(调用方),pc2 表示远程对等方(被调用方)。

来电者

  1. 创建一个新的 RTCPeerConnection 并添加来自 getUserMedia() 的流: ```js // Servers 是可选的配置文件。(请参阅稍后关于 TURN 和 STUN 的讨论。) pc1 = 新的 RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) =&gt; { pc1.addTrack(track, localStream); });
  1. 创建优惠,并将其设置为pc1的本地说明和pc2的远程说明。这可以直接在代码中完成,而无需使用信号,因为调用方和被调用方位于同一页面上: js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );

被调用方

  1. 创建 pc2,并在添加来自 pc1 的流后将其显示在视频元素中: js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

RTCPeerConnection 个 API Plus 服务器

在现实世界中,WebRTC 需要服务器,尽管如此简单,可能会发生以下情况:

  • 用户可以互相发现并交换真实世界的详细信息,例如名字。
  • WebRTC 客户端应用(对等方)会交换网络信息。
  • 对等方会交换有关媒体的数据,例如视频格式和分辨率。
  • WebRTC 客户端应用会遍历 NAT 网关和防火墙。

换言之,WebRTC 需要四种类型的服务器端功能:

  • 用户发现和通信
  • 信令
  • NAT/防火墙穿越
  • 用于应对点对点通信失败的中继服务器

NAT 穿越、点对点网络,以及构建服务器应用进行用户发现和信号发送的要求不在本文讨论范围之内。可以说,ICE 框架使用 STUN 协议及其扩展 TURN,让 RTCPeerConnection 能够应对 NAT 遍历和其他网络变异性问题。

ICE 是用于连接对等设备(例如两个视频聊天客户端)的框架。最初,ICE 会尝试通过 UDP 直接连接对等方,并实现尽可能低的延迟。在此过程中,STUN 服务器有一项任务:使 NAT 后面的对等方发现其公共地址和端口。(如需详细了解 STUN 和 TURN,请参阅构建 WebRTC 应用所需的后端服务。)

<ph type="x-smartling-placeholder">
</ph> 查找候选连接
查找候选连接

如果 UDP 失败,ICE 会尝试使用 TCP。如果直接连接失败(特别是由于企业 NAT 穿越和防火墙),ICE 会使用中间(中继)TURN 服务器。换言之,ICE 会先使用 STUN 和 UDP 直接连接对等方,如果连接失败,则会回退到 TURN 中继服务器。“查找候选项”表达式是指查找网络接口和端口的过程。

<ph type="x-smartling-placeholder">
</ph> WebRTC 数据路径
WebRTC 数据路径

WebRTC 工程师 Justin Uberti 在 2013 年 Google I/O WebRTC 演示文稿中详细介绍了 ICE、STUN 和 TURN。(演示文稿幻灯片提供了 TURN 和 STUN 服务器实现的示例。)

简单的视频聊天客户端

appr.tc 中的视频聊天演示是试用 WebRTC 的好地方,该演示具有使用 STUN 服务器的信号实现和 NAT/防火墙遍历功能。此应用使用 adapter.js,一种 shim,用于使应用免受规范变更和前缀差异的影响。

代码被特意记录的详细内容。查看控制台,了解事件的顺序。以下是详细的代码演示。

网络拓扑

目前实现的 WebRTC 仅支持一对一通信,但可用于更复杂的网络场景,例如与多个对等方相互通信,每个对等体相互直接通信,或通过多点控制单元 (MCU) 或多点控制单元 (MCU)。MCU 是一台服务器,可以处理大量参与者并有选择地转发流以及进行音频和视频混音或录制。

<ph type="x-smartling-placeholder">
</ph> 多点控制单元拓扑图
多点控制单元拓扑示例

许多现有的 WebRTC 应用仅演示网络浏览器之间的通信,但网关服务器可以让浏览器上运行的 WebRTC 应用与设备(如电话,也称为 PSTN)和 VOIP 系统进行交互。2012 年 5 月,Doubango Telecom 开放了使用 WebRTC 和 WebSocket 构建的 sipml5 SIP 客户端的源代码,该客户端(以及其他潜在用途)支持在 iOS 和 Android 上运行的浏览器与应用之间进行视频通话。在 Google I/O 大会上,Teethr 和 Tropo 以公文包形式展示了灾难通讯框架,该框架使用一个 OpenBTS 单元通过 WebRTC 实现非智能手机和计算机之间的通信。不用运营商服务也能通话!

<ph type="x-smartling-placeholder">
</ph> 2012 年 Google I/O 大会上的 Tethr/Tropo 演示
Tethr/Tropo:公文包中的灾难通讯

RTCDataChannel API<

除音频和视频外,WebRTC 还支持其他类型的数据的实时通信。

RTCDataChannel API 支持点对点交换任意数据,并且延迟低、吞吐量高。如需查看单页演示并了解如何构建简单的文件传输应用,请分别参阅 WebRTC 示例WebRTC Codelab

该 API 有许多潜在用例,包括:

  • 游戏
  • 远程桌面应用
  • 实时文字聊天
  • 文件传输
  • 分散式网络

此 API 有多项功能可充分利用 RTCPeerConnection 并实现强大且灵活的点对点通信:

  • 利用RTCPeerConnection会话设置
  • 按优先级同步多个渠道
  • 可靠和不可靠的交付语义
  • 内置安全机制 (DTLS) 和拥塞控制
  • 能否搭配音频或视频使用

该语法被特意设计为类似于具有 send() 方法和 message 事件的 WebSocket:

const localConnection = new RTCPeerConnection(servers);
const remoteConnection = new RTCPeerConnection(servers);
const sendChannel =
  localConnection.createDataChannel('sendDataChannel');

// ...

remoteConnection.ondatachannel = (event) => {
  receiveChannel = event.channel;
  receiveChannel.onmessage = onReceiveMessage;
  receiveChannel.onopen = onReceiveChannelStateChange;
  receiveChannel.onclose = onReceiveChannelStateChange;
};

function onReceiveMessage(event) {
  document.querySelector("textarea#send").value = event.data;
}

document.querySelector("button#send").onclick = () => {
  var data = document.querySelector("textarea#send").value;
  sendChannel.send(data);
};

由于通信是直接在浏览器之间进行的,因此在打孔以应对防火墙和 NAT 失败时,即使需要使用中继 (TURN) 服务器,RTCDataChannel 的速度也可能比 WebSocket 快得多。

RTCDataChannel支持 Chrome、Safari、Firefox、Opera 和 Samsung Internet。Cube Slam 游戏使用该 API 传达游戏状态。与朋友一起玩,或者扮演小熊!创新平台 Sharefest 通过 RTCDataChannelpeerCDN 实现文件共享,让大家可以大致了解 WebRTC 如何实现点对点内容分发。

如需详细了解 RTCDataChannel,请参阅 IETF 的协议规范草案

安全

实时通信应用或插件可能会通过多种方式损害安全性。例如:

  • 未加密的媒体或数据可能会在浏览器之间或在浏览器与服务器之间被拦截。
  • 应用可能会在用户不知情的情况下录制和分发视频或音频。
  • 恶意软件或病毒可能会与看似无害的插件或应用一起安装。

WebRTC 有多项功能可以避免这些问题:

  • WebRTC 实现使用 DTLSSRTP 等安全协议。
  • 所有 WebRTC 组件(包括信令机制)都必须进行加密。
  • WebRTC 不是插件。其组件是在浏览器沙盒中运行,而不是在单独的进程中运行。组件不需要单独安装,并且会在浏览器更新时随之更新。
  • 必须明确授予摄像头和麦克风使用权限,并且当摄像头或麦克风运行时,界面会清楚地显示此权限。

本文不对流媒体安全性进行全面讨论。有关详情,请参阅 IETF 提出的提议的 WebRTC 安全架构

总结

WebRTC 的 API 和标准可以普及和分散用于内容创作和通信的工具,包括电话、游戏、视频制作、音乐制作和新闻收集工具。

技术的颠覆性没有比这更明显。

正如博主 Phil Edholm 所说:“WebRTC 和 HTML5 可以实现与原始浏览器在信息通信方面相同的转换。”

开发者工具

  • 如需查看正在进行的会话的 WebRTC 统计信息,请访问: <ph type="x-smartling-placeholder">
      </ph>
    • 在 Chrome 中使用 about://webrtc-internals
    • Opera 中的 opera://webrtc-internals
    • Firefox 中的 about:webrtc <ph type="x-smartling-placeholder">
      </ph> chrome://webrtc-internals 页面
      chrome://webrtc-internals 屏幕截图
  • 跨浏览器互操作说明
  • adapter.js 是适用于 WebRTC 的 JavaScript shim,由 Google 在 WebRTC 社区的帮助下进行维护,该社区对供应商前缀、浏览器差异和规范变更进行抽象化处理。
  • 如需详细了解 WebRTC 信号传递过程,请查看控制台的 appr.tc 日志输出。
  • 如果工作量太多,建议您使用 WebRTC 框架,甚至是完整的 WebRTC 服务
  • 欢迎您提供错误报告和功能请求: <ph type="x-smartling-placeholder">

了解详情

标准和协议

WebRTC 支持摘要

MediaStreamgetUserMedia API

  • Chrome 桌面版 18.0.1008 及更高版本;Chrome(Android 29 及更高版本)
  • Opera 18 及更高版本;适用于 Android 20 及更高版本的 Opera
  • Opera 12、Opera Mobile 12(基于 Presto 引擎)
  • Firefox 17 及更高版本
  • Microsoft Edge 16 及更高版本
  • iOS 上的 Safari 11.2 及更高版本以及 MacOS 上的 Safari 11.1 及更高版本
  • Android 设备上的 UC 11.8 及更高版本
  • Samsung Internet 4 及更高版本

RTCPeerConnection API

  • Chrome 桌面版 20 及更高版本;Chrome(Android 29 及更高版本)(无标记)
  • Opera 18 及更高版本(默认启用);适用于 Android 20 及更高版本的 Opera(默认开启)
  • Firefox 22 及更高版本(默认开启)
  • Microsoft Edge 16 及更高版本
  • iOS 上的 Safari 11.2 及更高版本以及 MacOS 上的 Safari 11.1 及更高版本
  • Samsung Internet 4 及更高版本

RTCDataChannel API

  • Chrome 25 中的实验性版本,但在 Chrome 26 及更高版本中更稳定(以及与 Firefox 交互操作功能);Chrome(Android 29 及更高版本)
  • Opera 18 及更高版本中的稳定版(以及与 Firefox 交互操作功能);适用于 Android 20 及更高版本的 Opera
  • Firefox 22 及更高版本(默认开启)

如需详细了解针对 API 的跨平台支持(例如 getUserMediaRTCPeerConnection),请参阅 caniuse.comChrome 平台状态

也可以在 webrtc.org 上的文档中找到适用于 RTCPeerConnection 的原生 API。