作者:Tsahi Levent-Levi
翻译:Alex
技术审校 | 刘连响
▲扫描图中二维码了解音视频技术大会更多信息▲
Easy-Tech #032#
WebRTC由很多模块构成。你想了解它的工作原理吗?
WebRTC工作起来就像施魔法一样。你将浏览器指向一个URL,让其他人也将他的浏览器指向一个URL,然后,你们就能看到彼此了。是不是很酷?
如果你了解WebRTC内部的工作原理,你就会知道那里发生了很多事。
我将从不同角度向大家解释WebRTC的工作原理。最后,它们将向你呈现出WebRTC的完整面貌。
WebRTC的基本概念
下面是我介绍WebRTC时首先强调的两点:
- WebRTC原生支持Web浏览器进行实时通信
- WebRTC是使用JavaScript API的媒体引擎
WebRTC是一种直接在Web浏览器内部实现实时通信(语音、音频和任意数据)的方法,无需任何插件和下载。
从另一方面看,WebRTC只是一个媒体引擎,其上层是JavaScript API,每个人都知道如何使用它(尽管浏览器实现依然各不相同)。所以从这一角度,我就不多做解释了。
现在,让我们从浏览器的角度开始了解真正令WebRTC独一无二的原因。
如果到现在为止,当你想到Web应用的时候,呈现在你眼前的是客户端和服务器:
你将浏览器作为客户端,它连接服务器后,并向其请求内容(让我们称之为请求)。服务器对请求发送响应。这里我们先抛开WebSocket,但它们的内在原理是一样的。如果我想给正在使用浏览器的朋友发送一条信息,这条信息需要先来到服务器,从那里再发送给我的朋友。这与现实生活中的邮局非常相似。
WebRTC的交互流程和上述的流程不大一样。
虽然我们仍然需要以某种方式从一个浏览器向另一个浏览器发送信令(以便我们能够相互定位),但一旦发送信令结束,我们就可以直接在两个浏览器之间发送消息——而Web服务器永远不会获取到这些消息。是不是像魔法一样?
这也是WebRTC被称为点对点技术(简称为P2P)的原因。因为浏览器之间可以直接通信。
媒体和信令的分离
在加载网页时,我们已经习惯了浏览器为了渲染页面要去获取100种不同的资源,这些资源来自各种不同的服务器:页面的托管服务器、保存静态文件的CDN和一些第三方网站。也就是说,这些文件主要被分为三类:
- HTML和CSS,构成了网站及其形式的主要内容
- JS,通常运行网站的交互部分
- 图片文件和其他类似资源
最终,静态文件和少许代码的组合实现了这一切。
而WebRTC不同。
它需要通过网络进行两种类型的交互:信令和媒体。
信令传输发生在HTTPS连接或者WebSocket上,通过JS代码实现。你在信令中所做的就是决定用户找到彼此,并开启对话。关于信令有一件很重要的事:它并不是WebRTC的组成部分。由开发人员决定如何传递创建WebRTC会话所需的信息。WebRTC将生成发送所需的信息,并处理接收到的信息,但它不会在网络上对这些信息进行任何操作。现在,WebRTC将这些信息打包进SDP消息中。
实际的媒体在一个完全不同的媒介和连接上传输:“媒体渠道(media channels)”。需要使用SRTP(用于语音和视频)或者SCTP(用于数据通道)实现。
与信令不同,媒体选择了一条不同的路线在网络上进行传输,并且表现也大不相同。对于你需要运行的浏览器、网络和服务器,情况也是如此。
音频和视频
音频和视频是你在使用WebRTC需要注意的主要内容。在几乎所有的WebRTC示例和demo中,你都可以看到它们的展示。原因非常简单,视频非常直观,并且交互性强。WebRTC中的音频和视频使用编解码器进行工作。编解码器是用于压缩和解压缩视频和音频数据的已知算法。WebRTC中有很多不同的编解码器供你使用,这里我就不细说了。
音频和视频还有一个有趣的地方,就是它们需要低延迟发送。如果数据包因为网络出现问题而丢失,那么再重新传输它们可能就没有什么价值了(这是另外一个和HTML不一样的地方)。
WebRTC使用VoIP技术处理媒体,并将其通过网络发送,这一切都在SRTP(RTP的安全、加密版本)之上进行。通过使用SRTP中的特定机制(以前并未广泛使用),WebRTC做了一些小的修改,如果你已经部署了VoIP服务,那么它们的互操作将变得更难。
数据
你也可以使用WebRTC传输任意数据,这个过程在WebRTC中的数据通道(data channel)中完成。
当你想要在浏览器之间直接传输信息而不通过任何服务器时(你也许仍然需要一个TURN服务器转发消息),就可以使用数据通道。
NAT 穿越
能够直接通过浏览器通信当然很棒,但是却并不总行得通。
三四十年以前,互联网创建在客户端-服务器模式上,并在之后进行了适度的修改。今天,大部分用户从防火墙或者NAT后方访问互联网,这些设备通常会更改用户设备的IP地址,并将其在开放网络中屏蔽。这种屏蔽有时也会提供某种“保护”措施,防止未经请求的流量流向用户设备。这种方法的问题在于,WebRTC使用了多种用于信令和媒体的媒介,所以为分辨流量是否被请求带来了困难。
此外,有些企业强调不允许任何类型的流量在未经审查的情况下进入他们的网络。这就产生了下列场景:
由于发起了STUN请求,左侧小人现在实际可能知道右侧小人的公有IP地址。但是公有IP地址也许只对STUN服务器开放,其他人想要通过创建的“针孔(pinhole)”进行连接依然会失败。
想要克服这些问题(用户设备无法直接与其他私有网络中的设备直接通信),解决办法是通过公有服务器转发被阻止的媒体。这就是TURN服务器的目的:
预计5~20%的会话都会使用到TURN服务器。
由于这种复杂性,WebRTC会话的实现要经过以下几个步骤:
- 向Web服务器发送SDP请求。这条信息描述了设备想要交换的媒体通道,以及如何找到它们。
- 通过Web服务器接收到一条来自其他设备的SDP回复。记住,其他设备有可能是媒体服务器。
- 开启一个被称为ICE(Interactive Connectivity Establishment,交互连接建立)协商的程序,目的是确定设备是否可直接访问、点对点传输或者是否需要通过TURN转发媒体。这个过程最好使用trickle ICE完成,但要以后才能实现。
- 一旦完成,媒体就可以在设备之间通信了。
以上这些步骤需要在浏览器上使用JS进行异步编程,使用JS Promises也能实现。在服务器端,你可以使用任何你想管理媒体和信令的工具。
很多时候,开发者不会直接针对WebRTC API进行开发,而会使用第三方框架和模块(开源或者商业)来做这件事。
WebRTC工作原理速览
- WebRTC直接在浏览器间发送数据:P2P。
- 它可以实时发送音频、视频或者任意数据。
- 它需要通过NAT穿越机制使浏览器之间相互访问。
- 有时,P2P必须经过中继服务器(TURN)。
- 使用WebRTC,你需要考虑到信令和媒体,它们彼此分离。
- 并不一定要使用P2P,它只是一种选择。你也可以在需要时使用媒体服务器。这种方式“破坏”了P2P,但是我们的目的是解决问题,而不是写学术论文。
WebRTC中你需要的服务器包括:
- 信令服务器(或者作为你的应用服务器的一部分,或者是一个独立个体)。
- STUN/TURN服务器(用于NAT穿越)。
- 媒体服务器(可选,只有在你的用例需要时才使用)
WebRTC API观点
WebRTC拥有三个API,分别是:
- getUserMedia
- PeerConnection
- Data Channel
getUserMedia
getUserMedia负责让用户访问摄像头、麦克风和屏幕。它仅为本地执行的操作提供服务,而无法实现实时对话。下列是getUserMedia的一些用法:
- 获取用户头像图片
- 收集音频样本,将它们发送给音频转文本的引擎
- 录制音频和视频(不会因为丢包而导致质量下降)
我敢肯定你可以想到它的更多用法。
PeerConnection
PeerConnection是WebRCT的核心内容,也是最难实现和理解的部分。在某种程度上,它是万能的。
- 它负责处理所有SDP信息交换(不是将它们通过网络发送,而是生成信息并处理传入的信息)。
- 为了连接媒体通道,它实现了ICE(如果需要,它会经过TURN转发信息)。
- 它可以实时编码、解码视频和音频数据。
- 它通过网络发送和接收媒体。
- 它通过使用自适应jitter buffer、带宽估计、丢包隐藏和前向纠错等算法处理网络问题(虽然你很不想了解这些算法,但最后都需要学习)。
- 使用回声消除等算法处理本地音频问题。
大部分这些影响最终媒体质量的操作(发生在PeerConnection内部)都是基于探测:一组特定规则。因此,不同的实现也许具有不同的表现和媒体质量。
DataChannel
我之前曾讨论过数据通道(data channel)。
这里我唯一要补充的是:
- 数据通道可以配置为可靠或者非可靠。如果将它设置为非可靠,那么信息将无法自动通过它重传。有时,这要看你的个人喜好。数据通道也可以被配置为有序和无序传输信息。
- 数据通道被设计为在类似于WebSocket的API上运行,一旦你打开它,你可以按照类似的方式进行操作。
你可以在这里找到更多使用数据通道的方法:
https://bloggeek.me/webrtc-da...
WebRTC实现者的观点
如果你想利用WebRTC实现一个应用,你需要处理以下活动:
- 客户端
- 信令
- NAT穿越
- 媒体
客户端
客户端可以是浏览器、移动应用、PC应用,也可以是嵌入式设备。
对于Web浏览器来说,你需使用JavaScript进行开发:或者直接使用WebRTC的API(不太可能),或者使用现存的框架,很多开发者会从Github开始(只要确保你选择的是最近更新的流行平台即可)。
对于移动应用来说,最重要的是找到适合你使用的SDK。Github上有一些可以选用,也可以使用来自Google的一些官方SDK(用于iOS和Android)。有些商业的SDK也很好用。
对于PC应用,你可以通过Electron实现。也可以使用嵌入式方法,这意味着你或者将官方的Google WebRTC代码库移植到你的设备上,或者自己开发。这两种方法都有效。
信令
你需要信令服务器。WebRTC客户端做的第一件事就是连接信令服务器。这么做的目的是协调你发起的任何会话。
信令服务器并不在WebRTC规定的范围之内,所以你需要自行决定在此处使用的代码。大部分代码你可以在Github中找到,实际上浏览器客户端将会成为信令服务器的实现。
请记住信令服务器可以和你的Web服务器分开,或者它们位于同一进程中(由你自己来决定)。不管如何,首先要做的是检查是否已经为你的应用提供了某种信令机制,用于检查非WebRTC事务。你也许可以在此机制上搭载SDP信息和其他与信令服务器相关的WebRTC。
NAT穿越
NAT穿越需要部署STUN/TURN服务器。我们先来看看哪些事不要做:
- 不要认为你不需要TURN。
- 不要使用公有STUN服务器。
- 不要让一台服务器做所有事。
- 不要从构建世界级服务器网络开始,你会实现它,但需要时间。
现在来看看你该做哪些事:
- 将STUN和TURN部署在同一服务器,在相同进程。
- 使用coturn(大家都在用)。
- 或者从他人那里获得NAT穿越服务,XirSys和Twilio都是很好的选择。
媒体
如果你计划开启群组语音和视频会话、连接到PSTN或其他网络,录制或者其他高级功能,那么你就将需要使用媒体服务器。
寻找适用于你用例的服务器。
我甚至会说,在你的技术栈里选择任何技术之前就从这里开始。
还有一些开源或者商业选择,它们在很多方面都不同。
WebRTC工作原理问与答
✅ WebRTC可以用于移动应用吗?
可以。WebRTC在浏览器和操作系统间(包括iOS和Android)工作。作为开源项目,许多人也将它移植到自己的环境。
✅ 开发WebRTC我都需要做什么?
除了支持WebRTC的浏览器,你需要安装自己的信令服务器和TURN服务器。根据你的用例,也可以使用媒体服务器。
✅ 我在哪里了解更多关于WebRTC工作原理的知识?
你可以关注WebRTC Weekly和webrtcHacks,上面的资源非常丰富。也可以访问官方网站(https://webrtc.org/)。
结语
本篇文章的目的是帮助你理解最基础的WebRTC知识(如果你是一个新手)。我不想从创建“hello world”应用程序开始,你可以在网上找到很多这样的应用。我想做的是带你到更高的地方,让你一览全局。
在很多情况下,人们从一个“hello world”WebRTC实现开始,并想要使其适用于他们自己的场景。我发现很多时候这种方法是错误的,因为它依赖于你想要构建的内容(它将决定你的WebRTC旅程的起点)。
花些时间阅读这篇文章,然后再阅读一两个WebRTC的“hello world”手册。如果你能够这样做,你的WebRTC实现将会更高效。
更多拓展内容:
https://bloggeek.me/started-l...
https://bloggeek.me/webrtcglo...
https://bloggeek.me/webrtcglo...
https://bloggeek.me/webrtcglo...
https://bloggeek.me/webrtcglo...
https://bloggeek.me/webrtcglo...
https://bloggeek.me/webrtc-el...
https://github.com/coturn/coturn
作者简介:
Tsahi Levent-Levi:WebRTC专家,曾为testRTC的联合创始人和CEO,现为Spearline公司testRTC的产品负责人。Tsahi拥有多年WebRTC技术培训经验,并拥有自己的技术博客BlogGeek.Me,你可以到这里
(https://webrtccourse.com/)了解和学习他的课程。
致谢:
本文已获得作者Tsahi Levent-Levi授权翻译和发布,特此感谢。
原文链接:
https://bloggeek.me/how-webrt...