什么是webRTC
webRTC(web Real Time Communations)是一个开源的,提供各种终端(浏览器,android/ios客户端)实时音视频通信的项目!
对上层来说,就是一些接口调用。如果是浏览器,那就是java script API,如果是客户端,也有相应的库支持。
webRTC的应用场景:
- 音视频通话/多人会议
- 桌面共享/协助
- 云游戏
- 直播/在线教育
那么,两个webRTC应用终端之间,如何通信?这需要中间商(放心,不赚差价^^)。
中间商就包括,信令服务器+STUN/TURN服务器。
什么是信令服务器
信令服务器是用户终端之间交换信息的服务器,起到中介的作用。传递的信息,包括业务信息,媒体信息,网络信息!
信令服务器,可以自己基于socket.io开发,也可以基于开源的项目做二次开发,如Janus。
1.1 业务信息
业务信息指的是,终端A & B加入视频聊天,退出视频聊天,禁言等。
业务信息,根据不同的信令服务器实现,协议可以不一样,webRTC并没有要求这一块内容。比如用Janus作为信令服务器,那初始化时传递业务信息,有create / attach等,下面截取2个日志作为例子。
2020-12-11 19:18:44.864 12645-13059/com.chenxf.janusandroiddemo D/WebSocketChannel: send==>>{"janus":"create","transaction":"TIxrdwKc7dwu"}
2020-12-11 19:18:44.883 12645-13059/com.chenxf.janusandroiddemo D/WebSocketChannel: onMessage {
"janus": "success",
"transaction": "TIxrdwKc7dwu",
"data": {
"id": 1392174141034435
}
}
2020-12-11 19:18:44.891 12645-13059/com.chenxf.janusandroiddemo D/WebSocketChannel: send==>>{"janus":"attach","transaction":"skQJw5akDw7i","plugin":"janus.plugin.echotest","session_id":1392174141034435}
2020-12-11 19:18:44.897 12645-13059/com.chenxf.janusandroiddemo D/WebSocketChannel: onMessage {
"janus": "success",
"session_id": 1392174141034435,
"transaction": "skQJw5akDw7i",
"data": {
"id": 4936362724574777
}
}
1.2 媒体信息
媒体信息指的是,终端A & B互相要知道,对方用什么编解码器,音视频是否支持等。比如B总要知道A是用什么编码的,自己又能支持什么编码格式的流,互相沟通好了,才能定下最后A & B实际用什么编解码器。
在WebRTC中用来描述 网络信息的术语叫SDP(Session Description Protocol)。终端之间互相沟通媒体信息,称为媒体协商。
SDP的内容,其实就是一堆文本,例子如下:
v=0
o=- 7049085445648665932 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video data
a=msid-semantic: WMS
m=audio 63903 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:RL5z
a=ice-pwd:VTPrN9NhJ3SpT9CXZ1/VljlA
a=ice-options:trickle
a=fingerprint:sha-256 AF:E9:20:E1:00:0D:87:EE:F5:8F:35:9F:8E:70:71:3E:EC:CA:60:02:0E:61:9C:30:36:23:E1:24:67:E6:15:A9
a=setup:active
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
m=video 9 UDP/TLS/RTP/SAVPF 107 108
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:RL5z
a=ice-pwd:VTPrN9NhJ3SpT9CXZ1/VljlA
a=ice-options:trickle
a=fingerprint:sha-256 AF:E9:20:E1:00:0D:87:EE:F5:8F:35:9F:8E:70:71:3E:EC:CA:60:02:0E:61:9C:30:36:23:E1:24:67:E6:15:A9
a=setup:active
a=mid:video
a=extmap:4 urn:3gpp:video-orientation
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=recvonly
a=rtcp-mux
a=rtpmap:107 H264/90000
a=rtcp-fb:107 goog-remb
a=rtcp-fb:107 transport-cc
a=rtcp-fb:107 ccm fir
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:108 rtx/90000
a=fmtp:108 apt=107
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
b=AS:30
a=ice-ufrag:RL5z
a=ice-pwd:VTPrN9NhJ3SpT9CXZ1/VljlA
a=ice-options:trickle
a=fingerprint:sha-256 AF:E9:20:E1:00:0D:87:EE:F5:8F:35:9F:8E:70:71:3E:EC:CA:60:02:0E:61:9C:30:36:23:E1:24:67:E6:15:A9
a=setup:active
a=mid:data
a=sctpmap:5000 webrtc-datachannel 1024
上面的内容有点多,关键的点有,指定opus编码:
a=rtpmap:111 opus/48000/2
视频H264编码
a=rtpmap:107 H264/90000
1.3 网络信息
网络信息指的是,终端A & B把自己的网络信息(特别是外网IP&端口)告知信令服务器,服务器帮通知到对端,如果是同一个局域网,直接通过P2P传输,如果不是,则尝试NAT穿越,再不行,就中转。外网IP端口如何获取?通过向另一个服务器获取。该服务器基于STUN协议(Session Traversal Utilities for NAT),返回给终端一个外网IP&端口。具体下面将介绍。
在WebRTC中用来描述 网络信息的术语叫candidate。
ICE信息例子:
candidate: 684218068 1 udp 2122260223 192.168.199.185 54095 typ host generation 0 ufrag XwBf network-id 1 network-cost 10
从上面可见,有IP/端口
什么是STUN/TURN服务器?
STUN和TURN都是网络协议。基于这个协议搭建的服务器,就简单称STUN/TURN服务器。
STUN(Session Traversal Utilities for NAT)用于得到终端的外网IP&端口!让终端之间,尝试能否根据外网IP&端口直接通信。当然了,STUN并不是每次都能成功的为需要NAT的通话设备分配IP地址,如果失败了,则需要下面的TURN做辅助。
TURN(Traversal Using Relays around NAT)用于终端之间,无法直接P2P通信的时候,做一个中继服务!简单的说,终端A把音视频传递给TURN服务器,终端B从TURN服务器读取A的音视频数据。
实现了两个协议,并整合到一起的,是一个ICE框架(Interactive Connectivity Establishment:交互式连通建立方式)。在linux下,就是一个库。github源码:https://github.com/libnice/libnice
所以,这个服务器,也可以叫做,ICE服务器。
基于库实现的一个linux服务程序,也有开源的,叫做coturn。github源码:https://github.com/coturn/coturn
我们可以直接把coturn安装在服务器上,直接就能用!开源真好^^
上一张图,非常能说明服务器之间的关系。
2个终端,首先跟信令服务器建立链接,传递各自的信息。然后,向STUN获取自己的外网IP/端口。获取不到,没法P2P了,但不怕,还是可以继续建立链接,只不过,各自音视频的流,通过TURN服务器帮忙转发一下(实际应用中,TURN/STUN可以是一个服务器)。
参考
https://medium.com/av-transcode/what-is-webrtc-and-how-to-setup-stun-turn-server-for-webrtc-communication-63314728b9d0
https://zhuanlan.zhihu.com/p/79489847
https://www.jianshu.com/p/37007fe05215
https://webrtc.org/
https://www.jianshu.com/p/1257cc7d6eed