构建 WebRTC 应用程序所需的后端服务:STUN、TURN 和信令

发布于 2022-12-04 22:43:13 字数 27302 浏览 243 评论 0

WebRTC 支持点对点通信,但它仍然需要服务器,以便客户端可以交换元数据以通过称为信令的过程协调通信,并应对网络地址转换器 (NAT) 和防火墙。

本文向您展示如何构建信令服务,以及如何处理与 STUN 和 TURN 服务器的现实世界连接的怪癖。 它还解释了 WebRTC 应用程序如何处理多方呼叫并与 VoIP 和 PSTN(也称为电话)等服务交互。

如果您不熟悉 WebRTC 的基础知识,请 参阅WebRTC 入门。 在阅读本文之前

什么是信号?

信令是协调通信的过程。 为了让 WebRTC 应用程序建立呼叫,其客户端需要交换以下信息:

  • 用于打开或关闭通信的会话控制消息
  • 错误信息
  • 媒体元数据,例如编解码器、编解码器设置、带宽和媒体类型
  • 用于建立安全连接的关键数据
  • 网络数据,如主机的 IP 地址和端口,为外界所见

这个信令过程需要一种方式让客户端来回传递消息。 WebRTC API 未实现该机制。 您需要自己构建它。 在本文的后面,您将学习构建信号服务的方法。 但是,首先,您需要了解一些背景信息。

为什么 WebRTC 没有定义信令?

为了避免冗余并最大程度地与既定技术兼容,WebRTC 标准未指定信令方法和协议。 概述了这种方法 JavaScript 会话建立协议 (JSEP)

WebRTC 呼叫设置背后的想法是完全指定和控制媒体平面,但尽可能将信令平面留给应用程序。 理由是不同的应用程序可能更喜欢使用不同的协议,例如现有的 SIP 或 Jingle 呼叫信令协议,或者针对特定应用程序定制的协议,可能用于新的用例。 在这种方法中,需要交换的关键信息是多媒体会话描述,它指定了建立媒体平面所需的必要传输和媒体配置信息。

JSEP 的体系结构还避免了浏览器必须保存状态,即充当信号状态机。 例如,如果每次重新加载页面时信令数据都丢失,这将是有问题的。 相反,信令状态可以保存在服务器上。

JSEP架构图

JSEP架构

JSEP 需要 offer answer 之间的交换,即上面提到的媒体元数据。 提议和答案以会话描述协议 (SDP) 格式传达,如下所示:

v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2
…

想知道所有这些 SDP 官方文章的实际含义吗? 查看 Internet 工程任务组 (IETF) 示例

请记住,WebRTC 旨在通过编辑 SDP 文本中的值来调整提议或答案,然后再将其设置为本地或远程描述。 例如, preferAudioCodec()中的函数 appr.tc 可用于设置默认编解码器和比特率。 使用 JavaScript 操作 SDP 有点痛苦,并且有关于 WebRTC 的未来版本是否应该改用 JSON 的讨论,但 有一些优势。 坚持使用 SDP

RTCPeerConnectionAPI 和信号:Offer、answer 和 candidate

RTCPeerConnection是 WebRTC 应用程序用来在对等点之间创建连接以及交流音频和视频的 API。

要初始化这个过程, RTCPeerConnection有两个任务:

  • 确定本地媒体条件,例如分辨率和编解码器功能。 这是用于提供和回答机制的元数据。
  • 获取应用主机的潜在网络地址,称为 candidates

一旦确定了该本地数据,就必须通过信令机制与远程对等方进行交换。

想象一下 ,Alice 正试图给 Eve 打电话 。 这是完整的提供/回答机制的所有血淋淋的细节:

  1. 爱丽丝创造了一个 RTCPeerConnection目的。
  2. 爱丽丝创建一个提议(一个 SDP 会话描述) RTCPeerConnection createOffer()方法。
  3. 爱丽丝打电话 setLocalDescription()与她的提议。
  4. Alice 将提议字符串化并使用信号机制将其发送给 Eve。

  5. 夏娃呼唤 setRemoteDescription()有了爱丽丝的提议,所以她 RTCPeerConnection知道爱丽丝的设置。
  6. 夏娃呼唤 createAnswer()成功回调传递给本地会话描述——Eve 的回答。
  7. Eve 通过调用将她的答案设置为本地描述 setLocalDescription().
  8. Eve 然后使用信令机制将她的字符串化答案发送给 Alice。
  9. Alice 将 Eve 的答案设置为远程会话描述,使用 setRemoteDescription().

斯特鲁斯!

爱丽丝和夏娃还需要交换网络信息。 “寻找候选者”一词是指使用 ICE 框架 寻找网络接口和端口的过程。

  1. 爱丽丝创造了一个 RTCPeerConnection对象与 onicecandidate处理程序。
  2. The handler is called when network candidates become available.
  3. In the handler, Alice sends stringified candidate data to Eve through their signaling channel.
  4. When Eve gets a candidate message from Alice, she calls addIceCandidate() to add the candidate to the remote peer description.

JSEP 支持 ICE Candidate Trickling ,它允许调用者在初始报价后逐步向被调用者提供候选者,并让被调用者开始响应调用并建立连接,而无需等待所有候选者到达。

用于信令的 WebRTC 代码

以下代码片段是 W3C 代码示例 ,总结了完整的信令过程。 该代码假定存在某种信号机制, SignalingChannel. 稍后将更详细地讨论信令。

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stuns: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);
  }
};

// After 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);
  }
};

要查看实际的提议/答案和候选人交换过程,请参阅 simpl.info RTCPeerConnection 并查看控制台日志以获取单页视频聊天示例。 如果您需要更多信息,请从 Google Chrome 中的 chrome://webrtc-internals 页面或 Opera 中的 opera://webrtc-internals 页面下载完整的 WebRTC 信号转储和统计信息。

同行发现

这是一种奇特的提问方式,“我如何找到可以交谈的人?”

对于电话呼叫,您有电话号码和目录。 对于在线视频聊天和消息传递,您需要身份和状态管理系统,以及用户发起会话的方式。 WebRTC 应用程序需要一种方式让客户端相互发送信号,表明他们想要开始或加入通话。

对等发现机制不是由 WebRTC 定义的,因此您无需在此处深入了解这些选项。 这个过程可以像通过电子邮件发送或发送 URL 一样简单。 对于 Talky tawk.to Browser Meeting 等视频聊天应用程序,您可以通过共享自定义链接来邀请人们进行通话。 开发人员 Chris Ball 构建了一个有趣的 无服务器 webrtc 实验,使 WebRTC 呼叫参与者能够通过他们喜欢的任何消息服务(例如 IM、电子邮件或信鸽)交换元数据。

如何构建信令服务?

重申一下,信令协议和机制不是由 WebRTC 标准定义的。 无论您选择什么,都需要一个中间服务器来在客户端之间交换信号消息和应用程序数据。 可悲的是,网络应用程序不能简单地对着互联网大喊“帮我连接到我的朋友!”

值得庆幸的是,信令消息很小,而且大部分是在通话开始时交换的。 在使用 appr.tc 进行视频聊天会话测试时,信令服务总共处理了大约 30-45 条消息,所有消息的总大小约为 10KB。

WebRTC 信令服务不仅对带宽要求不高,而且不会消耗太多处理或内存,因为它们只需要中继消息并保留少量会话状态数据,例如哪些客户端已连接。

用于交换会话元数据的信令机制也可用于传递应用程序数据。 这只是一个消息服务!

从服务端向客户端推送消息

用于发信号的消息服务需要是双向的:客户端到服务器和服务器到客户端。 各种 hack,例如 长轮询,以便将数据从运行在 Web 服务器上的服务推送到运行在浏览器中的 Web 应用程序。 双向通信与 HTTP 客户端/服务器请求/响应模型背道而驰,但多年来已经开发出

最近, EventSourceAPI 已被 广泛实施 。 这会启用服务器发送事件——通过 HTTP 从 Web 服务器发送到浏览器客户端的数据。 EventSource专为单向消息传递而设计,但它可以与 XHR 结合使用以构建用于交换信令消息的服务。 信令服务传递来自调用者的消息,由 XHR 请求传递,通过将其推送到 EventSource给被叫者。

WebSocket 是一种更自然的解决方案,专为全双工客户端-服务器通信而设计——消息可以同时双向流动。 使用纯 WebSocket 或服务器发送的事件构建的信令服务的一个优势( EventSource) 是这些 API 的后端可以在大多数 Web 托管包通用的各种 Web 框架上实现,这些框架适用于 PHP、Python 和 Ruby 等语言。

除了 Opera Mini 之外的所有现代浏览器都 支持 WebSocket ,更重要的是,所有支持 WebRTC 的浏览器也都支持 WebSocket,无论是在桌面端还是移动端。 TLS 应该用于所有连接,以确保消息不会在未加密的情况下被拦截,并 减少代理遍历的问题 。 (有关 WebSocket 和代理遍历的更多信息,请参阅 中的WebRTC 章节 Ilya Grigorik 的 高性能浏览器网络 。)

也可以通过让 WebRTC 客户端通过 Ajax 重复轮询消息服务器来处理信令,但这会导致大量冗余网络请求,这对移动设备来说尤其成问题。 即使在建立会话之后,对等方也需要轮询信令消息,以防其他对等方发生更改或会话终止。 应用程序示例采用 WebRTC Book 此选项并对轮询频率进行了一些优化。

规模信号

尽管信令服务对每个客户端消耗的带宽和 CPU 相对较少,但流行应用程序的信令服务器可能必须处理来自不同位置的高并发级别的大量消息。 获得大量流量的 WebRTC 应用程序需要能够处理大量负载的信令服务器。

您不会在这里详细介绍,但是有许多选项可用于大容量、高性能的消息传递,包括以下内容:

 

(开发人员 Phil Leggetter 的 实时 Web 技术指南 提供了消息服务和库的完整列表。)

在 Node 上使用 Socket.io 构建信令服务

以下是一个简单的 Web 应用程序的代码,该应用程序使用 上使用Socket.io Node 构建的信号服务。 Socket.io 的设计使得构建交换消息的服务变得简单,并且 Socket.io 特别适合 WebRTC 信号,因为它内置了房间的概念。 此示例并非设计为可扩展为生产级信令服务,但对于相对较少的用户来说很容易理解。

Socket.io 使用具有后备功能的 WebSocket:AJAX 长轮询、AJAX 多部分流、Forever Iframe 和 JSONP 轮询。 它已被移植到各种后端,但最著名的可能是本示例中使用的 Node 版本。

此示例中没有 WebRTC。 它仅用于展示如何将信号构建到 Web 应用程序中。 查看控制台日志以查看客户端加入房间和交换消息时发生的情况。 此 WebRTC 代码实验室 提供了有关如何将其集成到完整的 WebRTC 视频聊天应用程序中的分步说明。

这是客户端 index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>WebRTC client</title>
  </head>
  <body>
    <script src='/socket.io/socket.io.js'></script>
    <script src='js/main.js'></script>
  </body>
</html>

这是 JavaScript 文件 main.js客户端中引用:

const isInitiator;

room = prompt('Enter room name:');

const socket = io.connect();

if (room !== '') {
  console.log('Joining room ' + room);
  socket.emit('create or join', room);
}

socket.on('full', (room) => {
  console.log('Room ' + room + ' is full');
});

socket.on('empty', (room) => {
  isInitiator = true;
  console.log('Room ' + room + ' is empty');
});

socket.on('join', (room) => {
  console.log('Making request to join room ' + room);
  console.log('You are the initiator!');
});

socket.on('log', (array) => {
  console.log.apply(console, array);
});

这是完整的服务器应用程序:

const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
  file.serve(req, res);
}).listen(2013);

const io = require('socket.io').listen(app);

io.sockets.on('connection', (socket) => {

  // Convenience function to log server messages to the client
  function log(){
    const array = ['>>> Message from server: '];
    for (const i = 0; i < arguments.length; i++) {
      array.push(arguments[i]);
    }
      socket.emit('log', array);
  }

  socket.on('message', (message) => {
    log('Got message:', message);
    // For a real app, would be room only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', (room) => {
    const numClients = io.sockets.clients(room).length;

    log('Room ' + room + ' has ' + numClients + ' client(s)');
    log('Request to create or join room ' + room);

    if (numClients === 0){
      socket.join(room);
      socket.emit('created', room);
    } else if (numClients === 1) {
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room);
    } else { // max two clients
      socket.emit('full', room);
    }
    socket.emit('emit(): client ' + socket.id +
      ' joined room ' + room);
    socket.broadcast.emit('broadcast(): client ' + socket.id +
      ' joined room ' + room);

  });

});

(你不需要为此学习 node-static 。它只是恰好在这个例子中使用。)

要在本地主机上运行此应用程序,您需要安装 Node、Socket.IO 和 node-static 。 Node 可以从 Node.js 下载(安装简单快捷)。 要安装 Socket.IO 和节点静态,请从应用程序目录中的终端运行节点包管理器:

npm install socket.io
npm install node-static

要启动服务器,请从应用程序目录中的终端运行以下命令:

node server.js

从您的浏览器,打开 localhost:2013. 在任何浏览器中打开一个新选项卡或窗口,然后打开 localhost:2013再次。 要查看发生了什么,请检查控制台。 在 Chrome 和 Opera 中,您可以使用 Google Chrome 开发者工具访问控制台 Ctrl+Shift+J(或者 Command+Option+J在 Mac 上)。

无论您选择何种方式发送信号,您的后端和客户端应用程序(至少)需要提供类似于此示例的服务。

信号陷阱

  • RTCPeerConnection直到 setLocalDescription()叫做。 这是 JSEP IETF 草案 中强制要求的。
  • 利用 Trickle ICE。 称呼 addIceCandidate()一旦候选人到达。

现成的信令服务器

如果你不想自己动手,有几个可用的 WebRTC 信令服务器,它们像前面的例子一样使用 Socket.IO,并与 WebRTC 客户端 JavaScript 库集成:

如果您根本不想编写任何代码,可以从公司获得完整的商业 WebRTC 平台,例如 vLine OpenTok Asterisk

作为记录,爱立信 使用 PHP 在 Apache 上构建了一个信令服务器 在 WebRTC 的早期 。 这现在有点过时了,但如果您正在考虑类似的事情,那么值得查看代码。

信令安全

“安全是不让事情发生的艺术。”

萨尔曼·拉什迪

加密 所有 WebRTC 组件都必须

但是,WebRTC 标准并未定义信令机制,因此您需要确保信令安全。 如果攻击者设法劫持信令,他们就可以停止会话、重定向连接以及记录、更改或注入内容。

确保信号安全的最重要因素是使用安全协议——HTTPS 和 WSS(例如,TL​​S)——确保消息不会在未加密的情况下被拦截。 另外,注意不要以可以被使用同一信令服务器的其他呼叫者访问的方式广播信令消息。

为了保护 WebRTC 应用程序,信令使用 TLS 是绝对必要的。

信令后:使用ICE应对NAT和防火墙

对于元数据信号,WebRTC 应用程序使用中间服务器,但对于实际的媒体和数据流,一旦会话建立, RTCPeerConnection尝试直接或点对点连接客户端。

在一个更简单的世界中,每个 WebRTC 端点都有一个唯一的地址,它可以与其他对等方交换该地址以便直接通信。

简单的点对点连接

一个没有 NAT 和防火墙的世界

实际上,大多数设备位于一层或多层 NAT 之后,有些设备具有阻止某些端口和协议的防病毒软件,还有许多位于代理和公司防火墙之后。 防火墙和NAT实际上可以由同一个设备实现,比如家用WIFI路由器。

NAT 和防火墙后面的同行

现实世界

WebRTC 应用程序可以使用 ICE 框架来克服现实世界网络的复杂性。 要实现这一点,您的应用必须将 ICE 服务器 URL 传递给 RTCPeerConnection,如本文所述。

ICE 试图找到连接同行的最佳路径。 它并行尝试所有可能性并选择最有效的选项。 ICE 首先尝试使用从设备操作系统和网卡获得的主机地址建立连接。 如果失败(它将用于 NAT 后面的设备),ICE 使用 STUN 服务器获取外部地址,如果失败,流量将通过 TURN 中继服务器路由。

换句话说,STUN 服务器用于获取外部网络地址,而 TURN 服务器用于在直接(对等)连接失败时中继流量。

每个 TURN 服务器都支持 STUN。 TURN 服务器是具有附加内置中继功能的 STUN 服务器。 ICE 还应对 NAT 设置的复杂性。 实际上,NAT 打洞可能需要的不仅仅是公共 IP:端口地址。

STUN 和/或 TURN 服务器的 URL 由 WebRTC 应用指定(可选) iceServers配置对象,它是 RTCPeerConnection构造函数。 对于 appr.tc ,该值如下所示:

{
  'iceServers': [
    {
      'urls': 'stun:stun.l.google.com:19302'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=udp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=tcp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    }
  ]
}

注意: TURN 凭据示例是有时间限制的,并于 2013 年 9 月过期。TURN 服务器的运行成本很高,您需要为自己的服务器付费或寻找服务提供商。 要测试凭据,您可以使用 候选人收集样本 并检查您是否获得了类型为 relay.

一次 RTCPeerConnection有了这些信息,ICE 魔法就会自动发生。 RTCPeerConnection使用 ICE 框架计算出对等点之间的最佳路径,必要时使用 STUN 和 TURN 服务器。

眩晕

NAT 为设备提供一个 IP 地址,供在私有本地网络中使用,但该地址不能在外部使用。 没有公共地址,WebRTC 端就无法进行通信。 为了解决这个问题,WebRTC 使用 STUN

STUN 服务器存在于公共互联网上并且有一个简单的任务——检查传入请求的 IP:端口地址(来自在 NAT 后面运行的应用程序)并将该地址作为响应发回。 换句话说,该应用程序使用 STUN 服务器从公共角度发现其 IP:port。 此过程使 WebRTC 对等点能够为自己获取一个可公开访问的地址,然后通过信令机制将其传递给另一个对等点以建立直接链接。 (在实践中,不同的NAT工作方式不同,可能有多个NAT层,但原理是一样的。)

STUN 服务器不需要做太多或记住太多,因此相对低规格的 STUN 服务器可以处理大量请求。

大多数 WebRTC 调用使用 STUN 成功建立连接——根据 Webrtcstats.com 的数据,86% ,但对于防火墙和复杂 NAT 配置后的对等点之间的调用,这一比例可能较低。

使用 STUN 服务器的点对点连接

使用 STUN 服务器获取公共 IP:端口地址

转动

RTCPeerConnection尝试通过 UDP 在对等点之间建立直接通信。 如果失败了, RTCPeerConnection求助于TCP。 如果失败,TURN 服务器可以用作后备,在端点之间中继数据。

重申一下,TURN 用于在对等点之间中继音频、视频和数据流,而不是信号数据!

TURN 服务器具有公共地址,因此即使对等方位于防火墙或代理之后,它们也可以被对等方联系。 TURN 服务器有一个概念上很简单的任务——中继流。 然而,与 STUN 服务器不同,它们天生就消耗大量带宽。 换句话说,TURN 服务器需要更强大。

使用 STUN 服务器的点对点连接

完整的 Monty:STUN、TURN 和信号

此图显示了运行中的 TURN。 纯 STUN 没有成功,因此每个对等方都求助于使用 TURN 服务器。

部署 STUN 和 TURN 服务器

为了进行测试,Google 运行了一个公共 STUN 服务器 stun.l.google.com:19302,由 appr.tc 使用。 对于生产 STUN/TURN 服务,请使用 rfc5766-turn-server。 提供了 STUN 和 TURN 服务器的源代码 GitHub 上 ,您还可以在其中找到有关服务器安装的多个信息源的链接。 Amazon Web Services的 VM 映像 也可用。

替代 TURN 服务器已恢复,可作为 源代码 使用,也可用于 AWS。 以下是有关如何在 Compute Engine 上设置 restund 的说明。

  1. 根据需要为 tcp=443、udp/tcp=3478 打开防火墙。
  2. 创建四个实例,每个公共 IP 一个,标准 Ubuntu 12.06 映像。
  3. 设置本地防火墙配置(允许来自 ANY 的 ANY)。
  4. 安装工具:
    sudo apt-get install make
    sudo apt-get install gcc
  5. creytiv.com/re.html 安装 libre 。
  6. 从 creytiv.com/restund.html获取 restund 并解压。
  7. wget hancke.name/restund-auth.patch 并申请 patch -p1 < restund-auth.patch.
  8. make, sudo make install为了自由和恢复。
  9. 适应 restund.conf根据您的需要(替换 IP 地址并确保它包含相同的共享密钥)并复制到 /etc.
  10. 复制 restund/etc/restund/etc/init.d/.
  11. 配置重启:
    一个。 放 LD_LIBRARY_PATH.
    b. 复制 restund.conf/etc/restund.conf.
    C。 放 restund.conf使用正确的 10. IP 地址。
  12. 运行重启
  13. 从远程机器使用 stund 客户端进行测试: ./client IP:port

超越一对一:多方 WebRTC

您可能还想查看 Justin Uberti 为访问 TURN 服务的 REST API 提议的 IETF 标准。

很容易想象媒体流的用例超越了简单的一对一通话。 例如,一组同事之间的视频会议或只有一位演讲者和数亿观众的公共活动。

WebRTC 应用程序可以使用多个 RTCPeerConnections,以便每个端点连接到网格配置中的每个其他端点。 这是 talky.io 等应用程序采用的方法,并且对少数同行非常有效。 除此之外,处理和带宽消耗变得过多,尤其是对于移动客户端。

Mesh:小型 N 路调用

全网状拓扑:每个人都连接到每个人

或者,WebRTC 应用程序可以选择一个端点以星形配置将流分发给所有其他端点。 也可以在服务器上运行 WebRTC 端点并构建您自己的重新分发机制( 一个示例客户端应用程序)。 webrtc.org 提供了

从 Chrome 31 和 Opera 18 开始, MediaStream从一个 RTCPeerConnection可以用作另一个的输入。 这可以实现更灵活的架构,因为它使 Web 应用程序能够通过选择要连接的其他对等点来处理呼叫路由。 要查看此操作,请参阅 WebRTC 示例对等连接中继 WebRTC 示例多个对等连接

多点控制单元

对于大量端点,更好的选择是使用 多点控制单元 (MCU)。 这是一个服务器,充当在大量参与者之间分发媒体的桥梁。 MCU可以应对视频会议中不同的分辨率、编解码器和帧率; 处理转码; 进行选择性流转发; 混合或录制音频和视频。 对于多方通话,有许多问题需要考虑,尤其是如何显示多个视频输入和混合来自多个来源的音频。 等云平台 vLine 也尝试优化流量路由。

可以购买完整的 MCU 硬件包或构建您自己的硬件包。

思科 MCU5300 后视图

的背面 Cisco MCU

有多种开源 MCU 软件可供选择。 例如, Licode (以前称为 Lynckia)为 WebRTC 生产开源 MCU。 OpenTok 有 螳螂

超越浏览器:VoIP、电话和消息

WebRTC 的标准化特性使得在浏览器中运行的 WebRTC 应用程序与在另一个通信平台(例如电话或视频会议系统)上运行的设备或平台之间建立通信成为可能。

SIP 是 VoIP 和视频会议系统使用的信令协议。 为了在 WebRTC 网络应用程序和 SIP 客户端(例如视频会议系统)之间进行通信,WebRTC 需要一个代理服务器来调解信号。 信令必须流经网关,但一旦建立通信,SRTP 流量(视频和音频)就可以直接点对点流动。

电路 公共交换电话网 (PSTN) 是所有“普通老式”模拟电话的 交换 网络。 对于 WebRTC 网络应用程序和电话之间的呼叫,流量必须通过 PSTN 网关。 同样,WebRTC 网络应用程序需要一个中介 XMPP 服务器来与 Jingle IM 客户端等 端点通信。 Jingle 由 Google 开发,作为 XMPP 的扩展,用于为消息服务启用语音和视频。 当前的 WebRTC 实现基于 C++ libjingle 库,这是最初为 Talk 开发的 Jingle 实现。

许多应用程序、库和平台利用 WebRTC 与外界通信的能力:

sipML5 开发人员还构建了 webrtc2sip 网关。 Tethr 和 Tropo 展示 了一个“在公文包中”的灾难通信框架, 使用 OpenBTS 单元 实现功能手机和计算机之间通过 WebRTC 的通信。 那是没有运营商的电话通信!

了解更多

WebRTC 代码实验室 提供了有关如何使用在 Node.js 上运行的 Socket.io 信号服务构建视频和文本聊天应用程序的分步说明

Google I/O WebRTC 演示 2013 年与 WebRTC 技术负责人 Justin Uberti 一起的

Chris Wilson 的 SFHTML5 演示文稿 — WebRTC 应用程序简介

350 页的书 WebRTC: APIs and RTCWEB Protocols of the HTML5 Real-Time Web 提供了大量关于数据和信令路径的细节,并包括许多详细的网络拓扑图。

WebRTC 和信号:两年的经验告诉我们 —TokBox 博客文章关于为什么将信号排除在规范之外是个好主意

Ben Strong 的 A Practical Guide to Building WebRTC Apps 提供了大量关于 WebRTC 拓扑和基础设施的信息。

中的 WebRTC 一章 深入 Ilya Grigorik 的 高性能浏览器网络 探讨了 WebRTC 架构、用例和性能。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

心舞飞扬

暂无简介

0 文章
0 评论
573 人气
更多

推荐作者

qq_7J1imQ

文章 0 评论 0

《一串符号》

文章 0 评论 0

hls.

文章 0 评论 0

雅心素梦

文章 0 评论 0

塔塔猫

文章 0 评论 0

微信用户

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文