众所周之,实时音视频聊天技术门槛很高,一般的公司要想在短时间内从零补齐这方面的技术短板相当困难,而开源音视频工程WebRTC提供了这样一个捷径(包括笔者公司的产品在内,同样是基于WebRTC技术才得以达成)。
本文将基于笔者公司开发的在线问诊产品中WebRTC技术的实践经验,讲述的如何基于WebRTC从零开发一个实时音视频聊天功能。文章会从WebRTC的基本知识、技术原理开始,基于开源技术为你演示如何搭建一个WebRTC实时音视频聊天功能。
WebRTC(Web Real-Time Communication)是 Google 在 2010 年以 6820 万美元收购 VoIP 软件开发商 Global IP Solutions 的 GIPS 引擎,并改名为“WebRTC”于 2011 年将其开源的旨在建立一个互联网浏览器之间的音视频和数据实时通信的平台。
那么 WebRTC 能做些什么呢?
除了我们大家每天都在用的微信、钉钉、qq这类传统的IM社交软件中的实时音视频通话以外,笔者公司产品中涉及医疗领域中的在线问诊/远程门诊/远程会诊,还有时下较为流行的互动直播、在线教育等场景。除此之外,伴随着 5G 的快速建设,WebRTC 也为云游戏提供了很好的技术支撑。
整个WebRTC大致可以分为以下 3 部分:
1)紫色提供给 Web 前端开发使用的 API;
2)蓝色实线部分提供各大浏览器厂商使用的 API;
3)蓝色虚线部分包含 3 部分:音频引擎、视频引擎、网络传输 (Transport),都可以自定义实现。
P2P通信的技术难点
P2P通信即点对点通信。
要实现两个不同网络环境(具有麦克风、摄像头设备)的客户端(可能是不同的 Web 浏览器或者手机 App)之间的实时音视频通信的难点在哪里、需要解决哪些问题?
总结一下,主要是下面这3个问题:
1)怎么知道彼此的存在也就是如何发现对方?
2)彼此音视频编解码能力如何沟通?
3)音视频数据如何传输,怎么能让对方看得自己?
怎么知道彼此的存在(也就是如何发现对方)?
对于问题 1:WebRTC 虽然支持端对端通信,但是这并不意味着 WebRTC 不再需要服务器。
在P2P通信的过程中,双方需要交换一些元数据比如媒体信息、网络数据等等信息,我们通常称这一过程叫做“信令(signaling)”。即时通讯聊天软件app开发可以即时通讯开发咨询加V:weikeyun24
对应的服务器即“信令服务器 (signaling server)”,通常也有人将之称为“房间服务器”,因为它不仅可以交换彼此的媒体信息和网络信息,同样也可以管理房间信息。
比如:
1)通知彼此 who 加入了房间;
2)who 离开了房间
3)告诉第三方房间人数是否已满是否可以加入房间。
为了避免出现冗余,并最大限度地提高与已有技术的兼容性,WebRTC 标准并没有规定信令方法和协议。在本文后面的实践章节会利用 Koa 和 Socket.io 技术实现一个信令服务器。
彼此音视频编解码能力如何沟通?
对于问题 2:我们首先要知道的是,不同浏览器对于音视频的编解码能力是不同的。
比如: Peer-A 端支持 H264、VP8 等多种编码格式,而 Peer-B 端支持 H264、VP9 等格式。为了保证双方都可以正确的编解码,最简单的办法即取它们所都支持格式的交集-H264。
在 WebRTC 中:有一个专门的协议,称为Session Description Protocol(SDP),可以用于描述上述这类信息。
因此:参与音视频通讯的双方想要了解对方支持的媒体格式,必须要交换 SDP 信息。而交换 SDP 的过程,通常称之为媒体协商。
音视频数据如何传输,怎么能让对方看得自己?
对于问题 3:其本质上就是网络协商的过程,即参与音视频实时通信的双方要了解彼此的网络情况,这样才有可能找到一条相互通讯的链路。
理想的网络情况是每个浏览器的电脑都有自己的私有公网 IP 地址,这样的话就可以直接进行点对点连接。
但实际上:出于网络安全和 IPV4 地址不够的考虑,我们的电脑与电脑之间或大或小都是在某个局域网内,需要NAT(“Network Address Translation,” 中文译为“网络地址转换”)。在 WebRTC 中我们使用 ICE 机制建立网络连接。
那么何为 ICE?
ICE (Interactive Connecctivity Establishment, 交互式连接建立),ICE 不是一种协议,而是整合了 STUN 和 TURN 两种协议的框架。
其中:STUN(Sesssion Traversal Utilities for NAT, NAT 会话穿越应用程序),它允许位于 NAT(或多重 NAT)后的客户端找出自己对应的公网 IP 地址和端口,也就是俗称的P2P“打洞”。
但是:如果 NAT 类型是对称型的话,那么就无法打洞成功。这时候 TURN 就派上用场了,TURN(Traversal USing Replays around NAT)是 STUN/RFC5389 的一个拓展协议在其基础上添加了 Replay(中继)功能。
简单来说:其目的就是解决对称 NAT 无法穿越的问题,在 STUN 分配公网 IP 失败后,可以通过 TURN 服务器请求公网 IP 地址作为中继地址。
在 WebRTC 中有三种类型的 ICE 候选者,它们分别是:
1)主机候选者:表示的是本地局域网内的 IP 地址及端口。它是三个候选者中优先级最高的,也就是说在 WebRTC 底层,首先会尝试本地局域网内建立连接;
2)反射候选者:表示的是获取 NAT 内主机的外网 IP 地址和端口。其优先级低于 主机候选者。也就是说当 WebRTC 尝试本地连接不通时,会尝试通过反射候选者获得的 IP 地址和端口进行连接;
3)中继候选者:表示的是中继服务器的 IP 地址与端口,即通过服务器中转媒体数据。当 WebRTC 客户端通信双方无法穿越 P2P NAT 时,为了保证双方可以正常通讯,此时只能通过服务器中转来保证服务质量了。
在非本地局域网内 WebRTC 通过 STUN server 获得自己的外网 IP 和端口,然后通过信令服务器与远端的 WebRTC 交换网络信息,之后双方就可以尝试建立 P2P 连接了。当 NAT 穿越不成功时,则会通过 Relay server (TURN)中转。
值得一提的是:在 WebRTC 中网络信息通常用candidate来描述,而上述图中的 STUN server 和 Replay server 也都可以是同一个 server。在文末的实践章节即是采用了集成了 STUN(打洞)和 TURN(中继)功能的开源项目 coturn。
简而言之:就是通过 WebRTC 提供的 API 获取各端的媒体信息 SDP 以及 网络信息 candidate ,并通过信令服务器交换,进而建立了两端的连接通道完成实时视频语音通话。