webrtc学习

音视频背景

音视频通话领域发展现状

人们在很久以前就利用各式各样的技术和工具进行通信,以移动电话运行商为例,大型电话公司建立起大规模的音视频通信网络,为全球成千上万用户提供音视频通信服务,让每个人的语音都能够传播到世界各地。

后来视频通信也随之流行起来。基于苹果的FaceTime、Google的Hangouts还有Skype的视频通话这些工具背后的技术,用户可以很方便地与其他人进行视频对话。开发者们为了将用户体验优化到极致,通过大量的技术手段保证视频质量,针对每一种问题都提出了相应的工程化解决方案,例如:减少丢包、断网恢复、及时响应网络变化等。

webrtc的目标是将这些技术都植入到浏览器中,上述解决方案大多都需要用户在PC和移动设备中安装相关的插件或者应用程序,这些公司还会向开发者征收技术授权费。并构筑起巨大的技术壁垒以防止新公司加入到这个领域中蚕食市场份额,每一位浏览器用户不再需要安装插件,开发者也不再需要交纳昂贵的授权费用,大家只需要打开特定的网站就可以立即和其他用户建立连接。

webrtc的核心其实就是在两个浏览器之间建立起来一条点对点连接,webrtc是这项技术在浏览器本身首次真正意义上的实现,所以任何通过点对点连接实现的程序都可以轻松地扩展到webrtc,例如文件共享、文本聊天、多人游戏。这些应用大都有一个共同的特点—需要在两个用户之间建立一条低延迟、高性能的连接。这要求webrtc不得不使用底层协议来提供高速性能,从而加速数据在网络间的流动,实现在端时间内传输大量的数据。

在web平台传输音频和视频

webrtc成就非凡,无需借助第三方软件或插件就可以在开放网络中传输高质量音视频流,在过去的浏览器中一直没出现过这种免费优质的实时通信解决方案。互联网的成功很大程度上可以归因于HTML、HTTP还有TCP/IP这些高度开放且高度可用的技术,我们希望基于此来构建webrtc。

从零开始构建一个实时通信应用,首先需要引入大量的库和框架,这些代码能够解决实际开发中将面临的问题,例如:连接断开、数据丢失、NAT穿透等,webrtc的优点是可以在浏览器API中内建上述这些库和框架,google也开源了许多提供高品质完整通信功能的技术。

为了使开发者专注于具体的产品细节,webrtc在浏览器API中集成了大量的技术,解决了所有繁重的问题,例如:捕捉摄像头和麦克风、音视频解码、传输层以及会话管理。

音视频通话原理

首先思考的问题:

两个不同网络环境的(具备摄像头/麦克风多媒体设备的)客户端 (浏览器或APP),要实现点对点的实时音视频对话,难点在哪里?

哪部分问题需要我们自己解决,哪部分问题由google解决

  • 音视频编解码能力沟通
  • 网络传输数据
  • 如何发现对方

1.怎么知道彼此的存在 -》进到同一个房间 -》2方登录服务器 由服务器去通知 信令服务器

2.音视频数据怎么传输,才能让对方看到彼此-》服务器转发还是P2P 商业方案 基本走服务器转发

3.音视频编码,音视频解码

媒体协商-音视频编解码,彼此要了解对方支持的视频格式

比如:Peer-A端可支持VP8、H264多种编码格式,而Peer-B端支持VP9、H264,要保证二端都正确的编解码,最简单的办法就是取交集H264

注:有一个专门的协议,称为session description protocol(SDP),可用于上述这类信息,在webrtc中,参与视频通讯的双方必须先交换SDP信息,这样双方才能知根知底,而交换SDP的过程,也称为媒体协商。

4.麦克风采集、摄像头采集

本机ip : 10.11.55.97 (局域网) -》 外网ip:223.75.224.98 中间存在nat转换

STUN协议:

告诉我你的公网IP地址+端口是什么

问题:STUN并不是每次都能成功的为需要NAT的通话设备分配IP地址,在传输媒体流时,使用的本地带宽,在多人视频通话的过程中,通话质量往往需要根据使用者的带宽确定。 TURN可以解决

STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序),它位于NAT(Network Address Translation网络地址转换协议)(或多重NAT)后的客户端找出自己的公网地址(ip),查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的端口。

TURN协议:

TURN的全称为Traversal Using Relays around NAT,是STUN/RFC5389的一个拓展,添加了relay功能后。如果终端在NAT后,那么在特定的情景下,有可以和其对等段(peer)进行直接的通信,这时候就需要公网的服务器

本地(局域网)音视频通话 —不需要中继,同一个网段打洞都不需要

远程通话—STUN和TURN服务器我们使用coturn开源项目来搭建。—coturn不起作用,打洞没法打,中继也没法中继

补充:ICE(Interactive Connectivity Establishment,交互式连接建立)

跟STUN和TRUN不一样,ICE不是一种协议,而是一个框架,它整合了STUN和TURN,coturn开源项目集成了STUN打洞和TRUN中继的功能。

网络信息:放在candidate

媒体协商+ 网络协商 数据的交换通道

2个客户端协商媒体信息(SDP)和网络信息(candidate)怎么去交换?是不是需要一个中间商?所以我们需要一个信令服务器(Signal server)(房间服务器)转发彼此的媒体信息和网络信息

信令服务器不仅只是交换 媒体信息sdp和网络信息candidate,比如:

1)房间管理 2)人员进出房间

早期IM即时通讯只有文字

如何集成视频通话,强耦合在一起:

一开始自研音视频通话(通话不佳),换第三方要做解耦

弱耦合:

webrtc技术堆栈

Transport/session 管理p2p,传输会话管理类

RTP stack 与实时传输协议相关

STUN/ICE

VoiceEngine 管理声音

iSAC/iLBC/Opus 采样率,低码率到高码率

Noise Reduction(NR) 噪音消除

Acoustic Echo Canceler(AEC) 回声消除

VP8/Vp9/H264 编解码

Video Jitter Buffer 缓冲区保存视频数据

几个问题

WebRTC可以不需要Media Server,即可以完成音视频通话的功能,但如果是多人同时通话呢?

如果多人音视频通话时,数据接收方由于带宽限制,只能接收小码率音视频数据怎么办?

网络状况瞬息万变,跨区域,跨运营商等错综复杂的网络状况下,如何保证音视频的通话质量?

几种常见的webRTC媒体服务器

  • Mesh

    Mesh网状结构,参与音视频的与会者需要同时推送多路视频以及接收多路视频

    • 优点

      不需要考虑Media Server的具体实现,简单搭建STUN/TURN服务即可完成开发

    • 缺点

      客户端资源消耗大,多路视频编码解码,网络带宽等消耗巨大

  • MCU多媒体控制中心

    与会者客户端只需要上传一路视频,接收一路多媒体数据

    • 优点

      客户端不需要做消耗资源的编解码操作,节省大量用户带宽,服务端可以根据客户端需要,分发不同码率的音视频数据。

    • 缺点

      服务端业务逻辑复杂,编解码资源消耗巨大,服务器成本高昂。

  • SFU

    (Selective Fowarding Unit 选择性分发控制单元)由服务端负责媒体数据的分发,从而实现一对多的音视频通话功能

    • 优点

      客户端和服务端逻辑均简单,服务端不需要支持编解码。不需要性能强劲的硬件资源,客户端可以使用发布订阅机制实现多对多的音视频通话

    • 缺点

      媒体数据下行依然需要很高的网络下行带宽,另外客户端对带宽需求也很高。

如何做好信令系统

稳定健壮的信令系统,全球音视频通话需要一张信令系统大网,保证消息的实时可达,高并发,高可用。

通常信令系统需要交换以下信息:

  • 会话描述的信息(SDP)
  • 设备的音视频能力,编解码,分辨率,码率等
  • 秘钥信息,用于创建安全连接
  • 维护一套发布订阅系统,房间信令系统
  • 传递信息,通过信令来实现业务场景中的通话控制

如何做好webRTC

MS/SS双剑合璧,也即是Media Server和Signal Server的完美组合才是音视频服务高可用的前提

获取用户媒体

创建一个基于webrtc的通信平台,首先需要通过用户网络摄像头和麦克风获取实时的视频和音频流,在过去的浏览器中,我们通常使用插件来实现这个功能,而现在,我们可以使用javascript调用浏览器的getUserMedia API来实现。

访问媒体设备

开发者们尝试将媒体设备接入浏览器中,有的是基于Flash,有的是基于插件,但这些方案都需要在浏览器中安装某些程序才能捕捉到摄像头。为此,W3C最终决定筹备一个专门的小组来制定相关的标准。

getUserMedia API又被称为MediaStream API,这组API有以下几个关键功能:

  • 提供一个stream对象:这个对象用以表示音频或视频形式的实时媒体流。
  • 提供设备间切换的功能:当多个摄像头或者麦克风连接到计算机上时,可以选择所需设备。
  • 提供充分的安全保障:获取用户的访问许可,根据偏好设置从用户的计算机设备获取数据流。

配置静态服务器

开发者们首先应该配置一台本地的web服务器。

创建我们的首个媒体流页面

首个支持webrtc的页面很简单:在屏幕上展示一个元素,请求使用摄像头后在元素里实时显示它此刻拍摄到的内容。vedio是html5里的一个强大的特性,既可以通过它展示实时的视频流,也可以用它回放很多的视频源。

创建简单的webrtc应用

开发任何webrtc应用的首个步骤就是创建RTCPeerConnection。成功创建一个RTCPeerConnection的前提就是需要理解浏览器创建对等连接的内部工作原理

理解UDP传输协议和实时传输

数据的实时传输要求双方有快速的连接速度,一个典型的网络连接需要将音频和视频都放在同一帧中,并以每秒40-60帧的速度发送给另一个用户,以此来获得较好的效果,在这种要求下,为了保持连接速度,音频和视频应用允许部分数据帧的丢地。这意味着传送最新的数据帧比确保每一帧都不丢失来得更为重要。

webrtc API

这些方法和对象使得开发者们可以与webrtc层沟通,并与其他用户建立对等连接,它主要由以下技术组成:

  • RTCPeerConnection对象
  • 信号传递和交涉
  • 会话描述协议(SDP)
  • 交互式连接建立(ICE)

RTCPeerConnnection对象

RTCPeerConnection是webrtcAPI的主入口,我们通过它初始化一个连接,连接他人以及传送流媒体信息。它负责与另一用户建立UDP连接。

RTCPeerConnection对象的功能是维护浏览器内会话和对等连接的状态。它也负责对等连接的建立。它将所有这些封装起来并暴露一系列事件,它们会在连接过程的关键点被触发。这些事件使你可以访问配置项,同时了解对等连接的内部正在发生什么。

信号传递和交涉

一般来说,我们需要知道对方浏览器的网络地址才能连接到它。通常地址是由IP地址和端口号组成,你的电脑或移动设备的IP地址可以允许其他的网络设备来直接传送数据给你的设备,RTCPeerConnection建立在这之上。当这些设备知道如何在互联网上找到其他设备之后,它们需要知道如何与其他设备进行沟通,这意味着它们需要交换数据,这些数据支持哪种协议以及视频和音频的解码器及信息。

发送信令的过程由以下几个步骤组成:

1.为一个对等连接创建潜在的候选列表

2.用户或计算机选择一个用户去连接

3.信令层将通知那个用户有人想要连接,用户可以选择接受或拒绝

4.当连接的请求被接受时,第一个用户会被通知

5.若接受,第一个用户将初始化RTCPeerConnection

6.双方将通过信令通道交换各自的电脑的硬件和软件信息

7.双方将通过信令通道交换各自电脑的位置信息

8.用户之间的连接将成功或失败

webrtc规范并不包含两个用户该如何交换信息的标准,这是因为连接用户的标准一直在扩充

会话描述协议(SDP)

为了连接到其他用户,需要了解对方所支持的音频和视频编解码器、他们使用何种网络以及他们的电脑可以处理多少数据。双方也需要能方便的传送数据。这意味着我们需要一张有用户所有信息的字符串形式的名片来传送给其他用户。

SDP是由浏览器提供的基于字符串的二进制数据对象,这种字符串是一系列的键值对从,由换行符分隔。

= \n

Key 是一个单字符,用来表明值的类型。value是由及其可读的配置项组成的有结构的一组文本。不同的键值对由换行符分隔。

SDP涵盖一个指定用户的描述、时间配置和对媒体的限制。SDP是在与其他用户建立连接的过程中由RTCPeerConnection对象给出。

找到一条清晰的路线到其他用户

网络安全是现今大部分网络的一大重点,你所使用的任何网络肯可都有好几层的访问控制,告诉数据在哪以及如何发送,意味着需要在网络里找到一条清晰的路线来连接对方,为了达到这个目的,webrtc使用了多种技术:

  • NAT会话穿透工具(STUN)
  • 使用中继技术穿透(TURN)
  • 交互式连接建立(ICE)

这个过程需要许多服务器和连接的建立,为了理解如何工作,首先要知道一个典型的webrtc架构怎么样:

首先要找到你的IP地址,通过它你才能让数据包到达正确的地址,当你的网络位于路由器之后,路由器会隐藏你电脑的IP地址并用其他的地址来替代,这是为了增加安全性以及为了允许多台电脑使用同一个网络地址。

NAT会话穿透工具(STUN)

STUN是双方建立稳定连接的第一步,它有助于在互联网上识别对方,同时在创建对等连接时常被其他协议使用,首先发一个请求给服务器,以开启STUN协议,之后服务器识别发出请求的客户端的IP地址,并将其返回给客户端,客户端之后可以通过返回的IP地址来识别自己。

使用中继穿透NAT技术(TURN)

在一些情况下,受防火墙限制,可能不允许任何基于STUN的访问,这种情况可能存在与企业级NAT中,它利用端口随机化来让数以千计的设备连接,你无法使用通用的方法找到用户,在这种情况下,我们需要使用不同的方法来连接另一个用户,这个标准叫TURN。

它的工作原理是代表客户端在对等连接的双方增加一个转播,客户端之后从TURN服务器得到信息,这有些类似于向服务器秦秋从热门视频网站加载,这就要求TURN服务器去下载、处理并重定向每一个用户发送过来的数据包。

交互式连接建立

STUN和TURN,将他们结合在一起的一个标准叫ICE,这个过程利用STUN和TURN为对等连接提供正确的路由,寻找一系列对方可用的地址并按张顺序测试每一个地址,直到找到一个双方都可用的组合。

ICE过程开始并不知道每一个用户的网络配置。它通过一些步骤来一步步发现双方的网络是怎么建立的,这个过程将会使用不同的技术,其目的发现双方网络足够多的信息,以此来建立一个成功的连接。

创建一个基本的WEBRTC应用

  • 创建一个RTCPeerConnection

    主要目标是连接一个浏览器窗口,从用户的摄像头加载视频数据,最终目的是在页面上获得两个视频流,一个直接来自摄像头,另一个来自浏览器在本地创建的webrtc连接。

  • 建立SDP OFFER和返回

    我们执行offer和返回answer这个过程以构成对等连接。

  • 寻找ICE候选路径

    建立对等连接的最后一部分是在双方之间传递ICE候选路径,以使他们可以互相连接。

  • 监听加入数据流

    API负责流的建立和发送,当另一对等连接中加入流时,会发送提醒,告诉第一个用户有变更,浏览器通过调用onaddstream来通知用户,流已经被加入。

创建信令服务器

创建一个完整的webrtc应用,需要转而进行服务器端的开发,创建一个由基本功能的信令服务器,需要进行以下操作:

  • 搭建Nodejs的开发环境
  • 使用websockets连接客户端
  • 识别用户
  • 发起和应答webrtc通话
  • 处理ICE候选路径的传送
  • 挂断通话

构建信令服务器

即将创建的服务器能帮助我们将不在同一个电脑中的两个用户连接起来,此服务器的目的是通过网络传输替代原来的信令机制。

我们的实现将对多个用户做出回应,这将通过一个简单的双向通信系统实现,它允许一方用户呼叫另一个用户从而在双方间建立webrtc连接,一旦用户呼叫了另一方,服务器会在双方传递请求,应答和ICE后端路径,这将让用户成功建立一个webrtc连接。

每一方都将从登陆服务器开始,登陆仅仅只是向服务器端发送一个字符串形式的用户标识,并确保此标识码没有被使用,一旦双方都登陆到服务器,他们便可以呼叫另一方,通过使用对方的标识码发送请求即可,另一方应答后,双方会发送候选地址直到他们能成功建立连接为止,它主要用来作为互相发送信息的通道。

获得一个连接

建立webrtc连接所需的步骤必须都是实时的,这意味着客户端不能使用webrtc对等连接在双方间实时传输信息,这就需要使用另一个HTML5的强大功能—websockets。

websockets听起来是在两个终端间—浏览器和网络服务器间的一个双向socket连接,你可以利用socket以字符串和二进制码方式双向发送信息。浏览器和网络服务器都需要实现此功能方可以在不使用ajax请求的情况下实现双方间的沟通。

websocke协议和webrtc协议最大的不同是在tcp堆栈的使用上,websocket被设计为是一个客户端到服务器端使用TCP传输协议来建立可靠连接的协议。这意味着它有许多webrtc没有的瓶颈,由于它的可靠性,信令很少会丢失,这让我们可以获得稳定的连接

识别用户

服务器需要一种方法来识别连接的用户,让每一个用户有一个字符串形式的标识,即用户名。

发起通话

offer处理器是登录后的首批通话之一,它意味着有用户想要呼叫另一方,将呼叫的初始化过程与webrtc的offer步骤分开

呼叫应答

应答就跟发送offer一样容易,让客户端做大部分工作,服务器仅将消息作为answer传递给另一方。

处理ICE候选路径

webrtc信令的最后一部分是在用户间处理ICE候选路径,这里,我们使用之前的技术在用户间传递信息,此类消息的不同在于每一个用户可能都需要发送多次且在双方用户间会以任何顺序发送,服务器可以以一种简单的方式解决这个问题,在文件里加上此candidate处理器。

websockets的困境

websockets的好处是它为浏览器带来了双向通信,很多人认为websockets是他们所有问题的解决方案,直接连接服务器让socket连接更快,但仍然有很多问题需要解决,其中一个便是网络防火墙,在理想情况下,websocket是可靠的,但不像http副本那样,websocket在代理设置的情况下很容易变得不稳定,虚拟专用网络(VPN)的额外开销或复杂防火墙系统可导致连接的成功率急剧下降,这意味着需要回到使用其他技术,比如HTTP流,来完成同样的工作

连接其他服务

webrtc最令人激动的特点之一就是它不但可以作为一个单独的解决方案,还可以与其他技术一起使用,在webrtc出现之前已经有许多对等连接应用,由于它的出现,人们做了许多努力,来让webrtc做向后兼容

XMPP

XMPP是一个即时通信协议,这个协议的目的在于定义一个常用的方法来实现即时通信、用户在线和通讯录,它是一个开源的标准,所有人都可以使用并将其合成到他们的应用当中,有许多大型即时通信平台在某一时刻将XMPP集成到了它们的服务当中。

会话初始协议

会话初始协议(SIP)室内另一个20世纪90年代使用的协议,它是一个致力于移动网络和电话系统的信令协议,它是一个被大部分移动网络和网络设备提供者使用的定义严格的支持广泛的协议。

SIP和webrtc集成的目的是为不支持webrtc的基于SIP的电话设备提供通信支持,如果我们与一个可以翻译我们信息的服务器连接,与移动电话或其他通信设备的连接也非常容易,如果它使用SDP,它也会支持现今电话拥有的许多功能。

把客户端连接到一起

现在信令服务器已经开发好,是时候利用它来创建一个应用了,我们将创建一个客户端应用,实现让两个用户通过webrtc来进行实时通信,需要包含以下四个步骤:

  • 从客户端获取到服务器的连接
  • 识别各个连接端的用户
  • 两个远程用户发起通话
  • 结束通话

客户端应用

客户端应用的目标是让不同地方的用户互相连接并进行通信。

获取一个连接

第一件要做的就是与信令服务器创建连接,之前创建的信令服务器完全基于websocket协议,我们不需要依赖其他的类库去连接服务器,它仅使用现在大部分最新的浏览器都支持的websock功能。

登录到应用程序

使用唯一的用户名登录是与服务器的首次交互行为,它用来识别我们的身份,同时给别的用户一个唯一的标识来呼叫我们,要这样做,我们只需要发送一个用户名给服务器,它会告诉我们这个用户名是否已经被使用。

开始一个对等连接

startConnection方法是任何webrtc连接的第一步,由于真个过程不依赖任何其他用户的连接,在用户试图和其他用户进行通话之前可以提前设置这一步,包含步骤如下:

  • 从相机中获取视频流
  • 验证用户的浏览器是否支持webrtc
  • 创建RTCPeerConnection对象

发起通话

首先发送offer给另一个用户来开始整个过程,一旦用户得到这个offer,他将创建一个响应并开始交换ICE候选,直到成功连接到服务器。

检测通信

可以使用chrome浏览器,查看每一个发送的包。还可以使用网络代理和抓包工具拦截浏览器发送的数据包,这种设置起来比较麻烦,但是可以得到服务器和客户端发送的数据的更多信息。

使用webrtc发送数据

webrtc擅长进行数据传输,不仅仅是音频和视频流,还包括我们希望的任意数据类型。

流控制传输协议和数据传输

在用户之间发送数据,目前通常的做法是使用严格的TCP连接,即会用如AJAX和WebSockets技术将数据发送到服务端,并在另一端进行接收,这种缓慢而笨重的方式对于高性能的应用是一个瓶颈。在webrtc模型中,已经实现了用户之间高速、低延时的连接,通过这个连接,我们可以快读发送音频和视频数据,目前使用的协议是专为视频和音频流的帧设计的,这就是为什么webrtc在刚建立的对等连接中使用流控制传输协议(SCTP)作为数据传输的方式。

SCTP同样也是一种术语,位于独立的webrtc堆栈中,它给javascript开发者提供了许多新的方法进行数据传输,SCTP位于数据传输层安全协议(DTLS)之上,每个webrtc连接都实现了它并且为数据传输提供出口绑定到数据通道上,所有这些都位于UDP上,它为WebRTC数据提供基本的传输方法。

以下是SCTP的特点:

  • 传输层的安全性,基于DTLS层
  • 传输层可以运行在可靠的或不可靠的模式中
  • 传输层可以担保或者无担保数据包顺序
  • 数据时面向消息 进行传播的,允许消息分解传输,在接收端重组
  • 传输层支持流量和阻塞协议

SCTP规范定义了使用多个端点,把消息分解成多个块进行发送数据,以下是这些术语解释:

  • 端点:在两个ip位置之间定义任意数据的连接
  • 消息:任意从应用发送到SCTp层的数据
  • 块:正准备通过电缆传输的数据包,表示消息的一部分

协议总体跨越16个部分,在浏览器中,数据通道采用完全不同的渠道,而不像其他是基于数据的传输层所使用的通道,它是可配置的并且高效地控制数据传输。

RTCDataChannel对象

数据通道会存在于以下几种状态中:

  • 连接中:这是默认状态,当数据通道等待一个链接
  • 开启:这种状态下,链接已经被建立。可以进行通信
  • 关闭中:通道正在被销毁
  • 关闭:这种状态下,通道关闭,无法进行通信。

数据通道选项

SCTP在发送数据给另一端时,可以进行不同配置,这些配置选项已经提供给开发人员,传入的配置项是可选的,并且是一个普通JavaScript对象。

这些配置项可以使应用在UDP或者TCP的优势之间进行变化,一些选项使得通道更加稳定可靠,另外一些使得应用运行更加快。

发送数据

数据通道的send方法像websockets上的send方法进行了重载,这样允许在传输层上发送不同的javascript数据类型,使用不同的数据类型有助于提升应用的性能,这是由于大部分基于字符串编码的数据过于庞大,需要发送的数据包。

加密与安全

使消息能安全地进行传输引起webrtc协议的设计者高度重视,背后的原因是许多大公司由于webrtc应用没有正常的安全保障而不考虑使用它,为了能增加被采用的概率,在设计API接口必须考虑安全性能被保障。

webrtc运行时,对于所有协议的实现,都会强制执行加密功能,这意味浏览器间的每一个对等连接,都自动处于高的安全级别中。

TCP和UDP最大的区别是前者能够保证信息到达另一边,这也是TLS和DTLS的主要区别,DTLS有能力处理消息丢失和接收消息时顺序不正确的能力,它能够在UDP协议基础上使用,这使DTLS满足像WEBRTC这类应用程序的加密要求,它是非常不错的选择。

打赏一瓶冰阔落,马上继续又创作