https://www.agora.io/cn/blog/%E5%9F%BA%E4%BA%8Ewebrtc%E6%8A%80%E6%9C%AF%E7%9A%84%E5%A4%9A%E4%BA%BA%E9%9F%B3%E8%A7%86%E9%A2%91%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/
本文主要讨论如何使用WebRTC技术来实现可扩展的,高效的多人音视频解决方案,介绍现有的多人音视频通讯模型 ,给出一种在Agora.io中使用的网页端技术方案。
WebRTC是一种基于点对点(peer to peer, P2P)的用于交换音视频媒体流以及数据流的技术,基于WebRTC的技术我们可以很容易的实现一对一场景的音视频通话以及数据流的传输并且有着不错的质量控制。但是如果要实现多人的音视频通话或者是一对多的直播应用,那么使用WebRTC就会面临一些困难和挑战,下面我们讨论两种常见的多方通讯模型。
1、网状模型
网状解决方案如图1所示,音视频数据流只在终端用户之间相互传输,不经过任何的服务器节点,不做混流或转发。打个比方,如果要实现四个人之间的音视频通话,那么每个人与其它三个人都需要建立P2P连接,每一个P2P连接都有自己的媒体传输通道,负责音视频数据流的传输。网状模型是基于WebRTC技术的原生实现,每一个点对点连接有独立的传输策略控制,通讯质量有一定的保障。但是,这种架构对于客户端系统是一种浪费,一方面需要分配更多的端口,消耗更多的系统资源;另一方面,由于要向其它三个客户端发送本地音视频数据,增加了上行网络带宽的消耗,在同等带宽条件下,支持的多人通话路数就相对有限,视频质量(码率)也比较低,尤其是对于1对多的直播场景,这种情况更加明显。而且这种实现方式也不利于其它非WebRTC客户端的接入。
2、混流或者转发模型
混流或转发模型如图2所示,借助于中央服务器节点,WebRTC用户无须直接与其它客户端建立P2P,而只须与服务器建立点对点连接。服务器在接收到客户端的音视频流之后负责转发给其它客户端,也可以将多个用户的音视频流做混合或者转码后再传输。甚至可以在服务器上做媒体流协议的转换,方便接入其它流媒体服务系统。总之,利用混流/转发架构,可以很容易地在服务器端做不同的定制化需求。
混流/转发架构中的服务器实现通常可分为MCU(Multipoint Control Unit)和SFU(Selective Forwarding Unit)两种。MCU是传统视频会议系统中的核心控制单元,在WebRTC的系统实现中, 适合于多人音视频通话场景,MCU可以对接收到的多路流进行转码和混合,输出为一路流,这样做的好处是节省终端用户的下行带宽,并且还能够对不同网络条件的用户,订制不同码率的输出视频流,让多人场景有更好的用户体验。当然,MCU的能力不止于此,现在流行的MCU中,还可以对视频流进行视频分析,做人脸检测和前景识别等,实现比较炫酷的功能。相比于MCU,SFU的功能相对单一,它以最低的开销来转发各路媒体流,典型的应用场景是1对多的直播服务,SFU从发布客户端复制音视频流的信息,然后分发到多个订阅客户端。目前在开源社区有免费的WebRTC 服务器实现,比较著名的有Licode和Kurento,使用它们可以很方便的进行服务部署并且实现多人的音视频互通功能。
从两种模型的介绍中可以发现,混流/转发模型更高效,也更易于扩展,但是在实际应用中,也会遇到很多问题。它不是WebRTC的原生实现,现有的实现在质量控制上缺乏优化,在处理多方通讯时质量很难保证,特别是在公网复杂网络条件下,用户体验可能相差很大。
公网上的音视频传输是声网Agora.io的技术优势,结合WebRTC技术,我们实现了网页端多方音视频通讯技术。正如图3的Agora.io Web通讯模型中所示,网页端用户通过Web SDK接入,由接入服务节点将数据分发到路由节点进行传输。
WebRTC用户的音视频数据经由Agora.io的媒体云传输,可以最大程度上保证公网的传输质量,结合WebRTC自有的丢包/丢帧重传,以及带宽预测,动态码率调整等策略,可以达到非常良好的多方通话用户体验,同时也适用于直播应用场景。此外,我们也对现有的MCU/SFU实现进行了改进,比如说在P2P通道的使用上,现有的实现是,在一个聊天室内,每增加一个流的发布者,流的订阅者都需要新建一个新的P2P通道来完成流的接收,而并不复用已有的P2P连接。不仅增加了客户端的开销,同时服务器端也要消耗更多的资源,需要创建更多的线程。而在Agora.io实现中,同一个频道内的用户,只与MCU建立一个P2P的连接,这一个P2P的连接既负责发送本地音视频的数据到MCU,同时也负责接收频道内其它用户的音视频数据。当频道内的数据发生改变时,通过更新建立P2P的SDP(会话描述协议)即可完成发布流以及订阅流的更新。
除了技术实现以及传输通道上的优势外,Agora.io的网页端SDK使用也相当简单,下面概括了典型的客户端与服务器交互接口。
/*
* 加入到名为channelName的频道中
*/
client.joinChannel(channelName)
/*
* 发布本地的音视频流到MCU
*/
client.publish(localStream)
/*
* 取消发布本地的音视频流到MCU
*/
client.unpublish(localStream)
/*
* 新的音视频流加入到频道中
*/
client.on(‘stream-added’, function (evt) { remoteStream = evt.stream; });
/*
* 从MCU订阅远端的音视频流
*/
client.subscribe(remoteStream)
/*
* 取消从MCU订阅远端的音视频流
*/
client.unsubscribe(remoteStream)
本文作者:
陈功 声网Agora.io 首席音视频RTC科学家
毛玉洁