WebRTC 是什么技术?

webrtc讲解(音解决方案)(1)

WebRTC

玩转技术的我们都知道,浏览器本身不支持相互之间直接建立信道进行通信,都是通过服务器进行中转。比如现在有两个客户端,A和B,他们俩想要通信,首先需要A和服务器、B和服务器之间建立信道。A给B发送消息时,A先将消息发送到服务器上,服务器对A的消息进行中转,发送到B处,反过来也是一样。这样A与B之间的一次消息要通过两段信道,通信的效率同时受制于这两段信道的带宽。同时这样的信道并不适合数据流的传输,如何建立浏览器之间的点对点传输,一直困扰着每一个技术开发者,基于此,WebRTC应运而生。

webrtc讲解(音解决方案)(2)

WebRTC 视频通信

WebRTC是一个开源项目,旨在使得浏览器能为实时通信(RTC)提供简单的JavaScript接口。说的简单明了一点就是让浏览器提供JS的即时通信接口。这个接口所创立的信道并不是像WebSocket一样,打通一个浏览器与WebSocket服务器之间的通信,而是通过一系列的信令,建立一个浏览器与浏览器之间(peer-to-peer)的信道,这个信道可以发送任何数据,而不需要经过服务器。并且WebRTC通过实现MediaStream,通过浏览器调用设备的摄像头、话筒,使得浏览器之间可以传递音频和视频。

WebRTC 目前应用情况以及浏览器兼容情况?

在浏览器兼容性查询网站caniuse上查询知道,WebRTC已经可以在新版本的Chrome、Opera和Firefox等浏览器中使用;同时移动端Android也已经兼容。

webrtc讲解(音解决方案)(3)

WebRTC 视频聊天

WebRTC 提供了三个API接口:

(1)、MediaStream:通过MediaStream的API能够通过设备的摄像头及话筒获得视频、音频的同步流
(2)、RTCPeerConnection:RTCPeerConnection是WebRTC用于构建点对点之间稳定、高效的流传输的组件
(3)、RTCDatachannel:RTCDataChannel使得浏览器之间(点对点)建立一个高吞吐量、低延时的信道,用于传输任意数据

我们分别看下这几个接口的定义以及应用:

MediaStream(getUserMedia)

MediaStream API为WebRTC提供了从设备的摄像头、话筒获取视频、音频流数据的功能。

调用:

同门可以通过调用navigator.getUserMedia(),这个方法接受三个参数:
1. 一个约束对象(constraints object),这个后面会单独讲
2. 一个调用成功的回调函数,如果调用成功,传递给它一个流对象
3. 一个调用失败的回调函数,如果调用失败,传递给它一个错误对象

浏览器兼容性

由于浏览器实现不同,他们经常会在实现标准版本之前,在方法前面加上前缀,所以一个兼容版本就像这样:

var getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);

我们看个Demo:

webrtc讲解(音解决方案)(4)

MediaStream 应用Demo

感兴趣的小伙伴可以尝试下,注意要在新版的Chrome、Opera、Firefox浏览器中运行,有问题可以在评论区留言,我会一一回答。

这里使用getUserMedia获得流之后,需要将其输出,一般是绑定到video标签上输出,需要使用window.URL.createObjectURL(localMediaStream)来创造能在video中使用src属性播放的Blob URL,注意在video上加入autoplay属性,否则只能捕获到一张图片

流创建完毕后可以通过label属性来获得其唯一的标识,还可以通过getAudioTracks()和getVideoTracks()方法来获得流的追踪对象数组(如果没有开启某种流,它的追踪对象数组将是一个空数组)

约束对象(Constraints)

约束对象可以被设置在getUserMedia()和RTCPeerConnection的addStream方法中,这个约束对象是WebRTC用来指定接受什么样的流的,其中可以定义如下属性:
* video: 是否接受视频流
* audio:是否接受音频流
* MinWidth: 视频流的最小宽度
* MaxWidth:视频流的最大宽度
* MinHeight:视频流的最小高度
* MaxHiehgt:视频流的最大高度
* MinAspectRatio:视频流的最小宽高比
* MaxAspectRatio:视频流的最大宽高比
* MinFramerate:视频流的最小帧速率
* MaxFramerate:视频流的最大帧速率

RTCPeerConnection

WebRTC使用RTCPeerConnection来在浏览器之间传递流数据,这个流数据通道是点对点的,不需要经过服务器进行中转。但是这并不意味着我们能抛弃服务器,我们仍然需要它来为我们传递信令(signaling)来建立这个信道。WebRTC没有定义用于建立信道的信令的协议:信令并不是RTCPeerConnection API的一部分

信令

既然没有定义具体的信令的协议,我们就可以选择任意方式(AJAX、WebSocket),采用任意的协议(SIP、XMPP)来传递信令,建立信道,比如我写的demo,就是用的node的ws模块,在WebSocket上传递信令

需要信令来交换的信息有三种:
session的信息:用来初始化通信还有报错
网络配置:比如IP地址和端口啥的
媒体适配:发送方和接收方的浏览器能够接受什么样的编码器和分辨率

这些信息的交换应该在点对点的流传输之前就全部完成,一个大致的架构图如下:

通过服务器建立信道

这里再次重申,就算WebRTC提供浏览器之间的点对点信道进行数据传输,但是建立这个信道,必须有服务器的参与。WebRTC需要服务器对其进行四方面的功能支持:
1. 用户发现以及通信
2. 信令传输
3. NAT/防火墙穿越
4. 如果点对点通信建立失败,可以作为中转服务器

NAT/防火墙穿越技术

建立点对点信道的一个常见问题,就是NAT穿越技术。在处于使用了NAT设备的私有TCP/IP网络中的主机之间需要建立连接时需要使用NAT穿越技术。以往在VoIP领域经常会遇到这个问题。目前已经有很多NAT穿越技术,但没有一项是完美的,因为NAT的行为是非标准化的。这些技术中大多使用了一个公共服务器,这个服务使用了一个从全球任何地方都能访问得到的IP地址。在RTCPeeConnection中,使用ICE框架来保证RTCPeerConnection能实现NAT穿越

ICE,全名叫交互式连接建立(Interactive Connectivity Establishment),一种综合性的NAT穿越技术,它是一种框架,可以整合各种NAT穿越技术如stun、TURN(Traversal Using Relay NAT 中继NAT实现的穿透)。ICE会先使用STUN,尝试建立一个基于UDP的连接,如果失败了,就会去TCP(先尝试HTTP,然后尝试HTTPS),如果依旧失败ICE就会使用一个中继的TURN服务器。

我们可以使用Google的STUN服务器:stun:stun.l.google.com:19302,于是乎,一个整合了ICE框架的架构应该长这个样子

浏览器兼容

还是前缀不同的问题,采用和上面类似的方法:

var PeerConnection = (window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection || window.mozRTCPeerConnection);

创建和使用

webrtc讲解(音解决方案)(5)

RTCPeerConnection 实例Demo

RTCDataChannel

既然能建立点对点的信道来传递实时的视频、音频数据流,为什么不能用这个信道传一点其他数据呢?RTCDataChannel API就是用来干这个的,基于它我们可以在浏览器之间传输任意数据。DataChannel是建立在PeerConnection上的,不能单独使用

使用DataChannel

我们可以使用channel = pc.createDataCHannel("someLabel");来在PeerConnection的实例上创建Data Channel,并给与它一个标签

DataChannel使用方式几乎和WebSocket一样,有几个事件:
onopen
onclose
onmessage
onerror

同时它有几个状态,可以通过readyState获取:
connecting: 浏览器之间正在试图建立channel
open:建立成功,可以使用send方法发送数据了
closing:浏览器正在关闭channel
closed:channel已经被关闭了

两个暴露的方法:
close(): 用于关闭channel
send():用于通过channel向对方发送数据

通过Data Channel发送文件大致思路

JavaScript已经提供了File API从input[type='file']的元素中提取文件,并通过FileReader来将文件的转换成DataURL,这也意味着我们可以将DataURL分成多个碎片来通过Channel来进行文件传输

欢迎评论区技术交流,后续还会持续更新。

需要源码的小伙伴关注我,发给你。

,