上一篇说到了视频,视频技术中未来非常有希望的一个就是谷歌发明的WebRTC,它能在网络环境不怎么好的时候也能达到较好的视频播放效果。

webrtc.jpg

WebRTC是基于Web的视频技术,可以直接在browser的js环境里使用。它本质上属于点对点(P2P)的通信协议,想一想你的web browser和另一个人的web browser直接点对点实时视频通话,酷不酷,香不香?

当然你也可以用WebRTC来做直播,多人对话在线会议室,或者引入client-server的模式这样server可以同时服务许多client,这些都和WebRTC的P2P本质不冲突。P2P的两端还可能是不同的device,等等。

为了掌握WebRTC的基本概念,我们先从通信专业的角度来考虑问题。如果你读过通信专业你就知道通信界有两个术语,一个叫媒体面(media plane),一个叫控制面(signal plane)。

媒体面可以理解为数据是怎么样在这个通信中传输的,传输数据依据的是什么样的具体协议。然而在WebRTC中,所有数据传输的细节它都能自己处理,如果我们只是使用WebRTC的API,而不是要做个WebRTC视频流分发处理的服务器,那么根本就不需要考虑媒体面的任何事情。

控制面可以理解为把通信双方的连接建立起来的协议,通信双方是怎么建立连接的,毕竟如果连接都没建立的话,那么媒体面的数据也根本无法传输。控制面还有个作用是在媒体面的数据传输中对数据传输的过程进行一些控制。所以在控制面,通信双方交流的是一些建立或影响媒体面数据通信的信号(signal)。举个例子,比如之前的华为高通5G标准之争,华为的Polar编码方案最后成为了5G标准里的控制面协议方案,然而因为控制面传输的数据量远远少于媒体面,所以实际上对性能造不成什么影响。当然也可能我的理解不对因为毕竟这一块我也不懂,哈哈哈。

WebRTC因为要达成自己比较general,适配各种网络环境的目标,对控制面的双方通过什么渠道进行互通并没有做出什么规定,基本上我们需要自力更生借助现有技术实现控制面信息交换,不过这个也很简单。但是,对于控制面的信息的具体格式,它是有规定的。

接下来我们来看WebRTC的双方的连接建立过程。第一步双方需要有一个握手过程,这个握手过程里主要是要交换双方支持的视频编码格式,视频分辨率等和视频相关的参数信息。因为双方的device可能不一样,所以对视频的支持可能都不一样,比如我发给你一个h.264编码的视频流,但你那里不能解码h.264,这样就会有问题了。

这个握手的过程是通过SDP(Session Description Protocol)来实现的,其实就是一方先发送一个SDP报文(offer),另一方收到这个offer报文之后再回复一个同样是SDP的响应报文(answer)。

sdp.jpg

那么现在问题来了,学挖掘机哪家强,哦不,问题是如果我要握手的另一方在一个局域网里怎么办,此时我连对方的IP地址都不知道,这个SDP offer我怎么发的出去呢。

在这种情况下必须借助signal server,局域网必须有一个暴露在公网下的signal server,我往这个server发SDP offer,然后server转发给局域网里的另一方,另一方再把他的SDP answer发给这个signal server,signal server再把这个answer转发给我。

所以现在可以看到,WebRTC的P2P不是一个纯粹的只有两方的P2P,它的P2P建立过程是一定至少需要一个第三方来做signal server的。

然而WebRTC对于我怎么把SDP offer发给signal server,signal server怎么转发给另一方,answer又怎么转回来,这整个流程是完全没有定义的。这就是我上面说的WebRTC因为要达成自己比较general,适配各种网络环境的目标,对控制面的双方通过什么渠道进行互通并没有做出什么规定。

所以这个过程和signal server的逻辑都需要我们自己写,可以通过WebSocket,HTTP,RPC,SIP(Session Initiation Protocol) 或者任何技术,来把SDP封装到自己的消息格式里,只要能唯一找到局域网中的另一方就可以了。幸运的是,很多开源框架这一套都已经帮你定义好了。

OK,现在双方都收到了对方发来的SDP。但也仅此而已,对方仍然在局域网里面,我的媒体面数据仍然没有办法直接发到对方。难道让我的视频流数据也走signal server中转吗?但signal server只是处理signal的。事实上WebRTC解决这个问题的标准办法是使用ICE(Interactive Connectivity Establishment) server。

ice.jpg

ICE server有两种不同协议的实现,一种是STUN(Session Traversal Utilities for NAT),还有一种是TURN(Traversal Using Relays around NAT),后一种比前一种更强大因为后一种能处理NAT里限制最强的Symmetric NAT这种配置。STUN和TURN的原理过于复杂,其实我并不懂,哈哈哈,所以我们只要知道用他们可以穿透NAT就行了。

stun.jpg

turn.jpg

终于,P2P连接建起来了。但在传输视频数据之前,在控制面还需要做一些事情。比如,我们是用UDP还是TCP传媒体面数据,目前网络的拥塞情况是什么样的,我传数据的bps设置成多少比较适合你当前的网络状况,我大概要缓冲多少数据才能播放的比较流畅,不至于在我缓冲区空了以后还没有收到你的数据导致播放暂停,卡顿。

这些个信息的交换,也是使用的ICE这个框架,搭载这些信息的报文,就被叫做ICE Candidate。双方不断交换ICE Candidate,直到达成一致,才能开始传输媒体面数据。而且即便媒体面数据传输已经建立了,双方还必须不时的交换ICE Candidate,因为网络情况千变万化,可能本来下载速度有20M过了一会儿只有5M了,这样这个视频数据传输也需要根据网络情况不停做出调整。幸而在下一篇的code里可以看到,这些调整的细节WebRTC内部都帮我们handle了,我们的code只要能把ICE Candidate正确的传输给对方就行了,其他的任何东西都无需关心。

icecandidate.jpg

注意,注意。这里ICE candidate的交换和传输走的是signal server,而不是ICE server,前面的ICE server只是负责穿透NAT,我更希望它叫STUN/TURN server,叫ICE server这个名字是比较confuse的。而ICE candidate怎么通过signal server传送给对方,这个在WebRTC里又是完全没有定义了,我们需要用whatever technology能实现这个就行了。

终于,至此关于WebRTC的最关键的基本概念就讲解完毕了。总结一下,最关键的其实就是P2P,SDP offer & answer,signal server,ICE server & candidate。当然这里signal server和ICE server在同一个机器上也没问题。下一篇主要是贴code流程,只要把概念讲清楚了,剩下的就都简单了。

上一篇 下一篇