下面我们稍稍介绍一下WebRTC。WebRTC 是google 2010年6800多万美金收购了瑞典一家音频技术非常强的公司——GIPS,这家公司当时做音频技术是全球领先的。谷歌收购以后没有商业化,而是结合了谷歌收购的另外一家做视频技术的公司,叫ON2。这就是VP8、VP9音视频引擎的出处。我们看到谷歌在做一件非常伟大的事,而且这件事在当时看来很难做成。他的想法是通过浏览器把所有音视频通讯打通。那个时候各个浏览器厂商很强势,当时微软的IE占大头,他的IE市场份额最高,他自己搞了一个ORTC标准,跟WebRTC不一样。谷歌这些年,一直在致力于推动WebRTC成为行业标准,同时利用自己Chrome浏览器的优势,不停提升自己在浏览器市场的份额。其中也包括音视频引擎的进化,除了VP8,又进化VP9,甚至到AV1。VP9国内用得不多,但是用过Youtube的应该知道,VP9的清晰度和流畅度还是非常好的。

 

WebRTC把浏览器端尤其是客户端关于音视频和通讯方面比较难处理的一些东西,比如说红线框起来的,像iSAC、AEC、NR,还有ICE的“打洞“等网络传输的控制都标准化了,而且固化到浏览器内部,紫色的部分提供了JS的API,非常方便大家基于此做自己逻辑,也方便调用。虚线的地方是开放给各个浏览器厂商,他们自己实现相应的硬件相关的控制接口。

 

640?wx_fmt=png

 

比较好的消息,WebRTC从2011年诞生,到2017年开始被W3C纳入草案,不到十年的发展,WebRTC项目已经成为事实上的W3C的国际标准。主流浏览器必须要支持,所以看微软新推出的edge浏览器内核已经从ORTC换成了WebRTC,Apple的Safari等厂商也都在积极支持,WebRTC最初的目标已经实现。

 

下面是WebRTC的协议栈,左边的部分是基于TCP协议,音视频系统尤其是实时的,跟普通的WEB应用不一样,通讯中会大量采用UDP的协议,是下图右边的部分。

 

640?wx_fmt=png

 

WEB2.0以后像XHR、SSE的这样的技术已经很少应用了,因为需要不停的和Server做重新连接。而WebSocket连接以后直接就upgrade成稳定的TCP连接,并且发数据了,所以整个效率大大提升,目前音视频的指令服务基本以WebSocket为主。

 

这是一个最简单的WebRTC的图,我们看看主要是通过Signaling服务器做主要通讯Server,两个浏览器之间通过PeerConnection打通。

 

640?wx_fmt=png

 

这个是WebSocket和Http的比较,比传统的“轮询“的方式优势是传输会更高高效。考虑大部分的Web应用还是走HTTP,所以他对于HTTP做了兼容。当HTTP连接上以后,做upgrade就可以建立稳定的TCP连接了,显然,下图右侧的部分会更加高效。             

 

640?wx_fmt=png

 

这个是WebRTC最简单的流程图,已经比较简化,如果要是把它比较完整的画下来,这个可能得好几页,步骤会比较多。先是请求Html5文件,本地搜索好的SDP的信息,或者做一个穿透,最右侧的是Server,也可以理解成浏览器B,相当于下图还有一半建立连接的流程没有画出来。如果两个浏览器打通就比较简化一些,类似于这张图描述的。我把SDP发过去,那边回一个answer。这样整个媒体通讯建立起来了。

 

刚才讲了SDP相当于纯文本的协议,这个协议也有他的一些规则。比如说他都是用字母标识,我传的协议内容是什么。如果是A就是关于媒体信息的,这个协议为什么这么设计呢?为什么不用XML,那个主要是为了兼容老的通讯设备,让它们可以纳入整个体系里面,所以这个协议这样一个纯文本结构。如果感兴趣,大家可以详细研究每一个字符代表什么意思,这个协议怎么运作的。刚才我举的例子是一个普通的WebRTC自己测试的Demo,这个东西没有办法在线上作为一个产品运行的,如果想成为一个规模化、产品化的实时音视频的应用,还有很多的事情要做。

 

比如说我怎么保证整个连通率和可靠性,同时比如说我的房间如果人多的话,我怎么样把压力平摊,网络节点采用分布式,包括流的管理,智能路由,实时的监控系统等,还有很多额外工作要做。

 

640?wx_fmt=png

 

接下来,我介绍一些开源的WebRTC Server的项目给大家。

 

第一个是Licode,也是很多年的一个开源项目了,主要是C++开发,在因特尔公司他们开源版本早期也是基于Licode构建的,影响力比较大。包括我们目前有一些做音视频Saas云的厂商,很多也都选了Licode方案。

Licode是C++开发,然后提供了基于JS的接口,包括服务端也引入了NodeJS,方便大家做一些扩展,但是整体代码量还是非常大的,他的功能比较完善,但是也是会有一些扩展性或者性能上的问题,需要做一些比较深度的优化和改造才能达到工业级的产品标准。

 

第二个项目是关于Meetecho,之后改名叫Janus,这个项目也是非常有名的。他们是属于学院派,教授带着博士生一起搞的,代码质量也很好,主要是用C,是一个非常不错的WebRTC的网关。

 

Jitsi历史比较悠久了,超过十年了。里面有很多处理XMPP的东西,legacy 的代码比较多,后期对移动App的支持比较好。

 

Kurento我们也用过,TM+ 1.0的早期版本就是基于Kurento的。Kurento是比较好的WebRTC Server,功能比较丰富,它也是支持Java,支持NodeJS的API。但是Kurento因为基于GStream,所以最大的问题是性能始终上不来。当你并发量一大,音视频有多路的时候,CPU的损耗就会比较大。

 

我们自己在搭建的时候,结合之前搞CCTalk的一些经验,我们有一些特别的想法。比如说我们采用了动态分区的技术。比如说我们在系统的最前面自建了一个路由层,在路由层下面我们在部署的时候实际上是可以把整个一套的WebRTC Server不同分区的部署方式。比如说当我们做发布的时候,可以单独更新一个区。可以先调动一部分流量做小规模的验证和跟踪,如果OK可以继续扩大比例,一直到新服务的比例超过50%以上,而且稳定运行的一两个完整周期之后。我们再把其他的区全部更新,采用这样一种方式,方便我们发布,同时我们的新区和老区之间也可以做比较好的AB TEST。

 

WebRTC的前端HTML5和JS样例

 

640?wx_fmt=png

 

640?wx_fmt=png

 

WebRTC的后端Go代码样例

 

640?wx_fmt=png

 

640?wx_fmt=png

 

WebRTC的debug工具

 

640?wx_fmt=png

 

WebRTC的Demo Result

 

640?wx_fmt=png

 

我们的API层叫做Actiniae,统一配置用的Consul,服务端采用的gRPC,前端用Websocket和TCP。

 

640?wx_fmt=png

 

这张图更直观,对于我们来说,比如说学生、还有监控的角色还有老师,就是通过Beacon(Router)进行就近分配,可以做到让用户就近接入。老师在国外比较多,有来自美洲、欧洲等地区的老师为我们提供7X24小时的授课服务。学生是大陆地区比较多,也有东南亚地区的,为了更好的上课体验,我们的整个的部署一定要保证低延时和就近接入。

 

640?wx_fmt=png

 

 

Media Server是比较独立的,彼此之间没有形成资源竞争关系。Media Server首选是SFU,相当于只做转发,一路流进来以后不做任何处理,直接转发出去,这个对于服务端来说最省CPU的策略。当我们需要录制,或者是推流的时候这个时候会用到MCU,就把前端多路流Merge起来合流,再转码推出去。        

 

这是我们用的Go Lib,比如说我们用的gRPC、TCP等等,我们觉得Go语言发展比较快,但是Go社区与Java相比,各种模块和支持还需要不断的完善。像Socket.IO库我们就遇到很多的问题,刚开始的时候几乎找不到一个比较好的比Socket.IO库。当然,社区发展靠大家,之后我们也会多为社区做一些贡献,也期望我们整个Go社区的社区生态能够变得越来越好。

 

640?wx_fmt=png