WebRTC 怎么用

2015 年 01 月 11 日

背景就不多说了,无非是程序员的无聊吐槽,大家用手指头想想也知道是怎么回事。

问:WebRTC是什么? 答:是浏览器实现的一套用于p2p连接的接口。

看到主谓宾了吧。WebRTC是......接口(也可以说是标准啦)。所以不要以为它是架构,或者是工具库(当然它包含native接口库),或者是什么万能灵药。

问:WebRTC包含什么? 答:三个接口。getUserMedia负责获取多媒体流;RTCPeerConnection负责点对点连接;RTCDataChannel负责数据传输。

有点程序员常识的看明白了吧。就这三个接口,而且还都是前端用的,就只能干这三个接口的事。光用前端就搞出一套基于Web的即时通讯软件,还不建服务器。拜托,在这个年代,这不是计算机软件,这是神迹。

问:那好吧,做一套基于Web的即时通讯软件还需要什么? 答:那得看你真正需要什么。架构是为了需求服务的,又想灵活,又想强大,还又想少写代码,只能等会编程的人工智能出现了。

不吐槽了,还是实务一点。 问:用WebRTC接口,如何建立RTCPeerConnection? 答:这是一系列动作

  • 首先,发起方需要createOffer,得到自己的SDP(Session Description Protocol会话描述符),然后将SDP交给接收方。
  • 接收方用createAnswer得到自己的SDP,交还给发送方。
  • 然后双方将两个SDP分别设置到RTCPeerConnection对象的setLocalDescription和setRemoteDescription
  • 接下来就等着onicecandidate回调,将各自得到的icecandidate对象交到对方手里
  • 然后收到icecandidate的一方需要调用自己的addIceCandidate,将得到的icecandidate对象加入,直到连接建立。
graph TB
  subgraph 接收者
  B1["new PeerConnection()"] --> B2["onicecandidate=gotLocalIceCandidate(event)"]
  B2 -.- B3["setRemoteDescription(description)"]
  B3 --> B4["createAnswer(gotAnswerDescription)"]
  B4 --> B5["gotAnswerDescription(description)"]
  B5 --> B6["setLocalDescription(description)"]
  B6 --> B7["sendMsg(JSON.stringify(description))"]
  B7 -.- B8["gotLocalIceCandidate(event)"]
  B8 --> B9["sendMsg(JSON.stringify(event.candidate))"]
  B9 -.- B10["addIceCandidate()"]
  end
  subgraph 发起者
  A1["new PeerConnection()"] --> A2["onicecandidate=function"]
  A2 --> A3["createOffer(gotLocalDescription)"]
  A3 --> A4["gotLocalDescription(description)"]
  A4 --> A5["setLocalDescription(description)"]
  A5 --> A6["sendMsg(JSON.stringify(description))"]
  A6 -.- A7["setRemoteDescription(description)"]
  A7 -.- A8["gotLocalIceCandidate(event)"]
  A8 --> A9["sendMsg(JSON.stringify(event.candidate))"]
  A9 -.- A10["addIceCandidate()"]
  end
  A6 --> B3
  B7 --> A7
  A9 --> B10
  B9 --> A10

很明显,要建立P2P连接,先得有一个机制,让双方可以双向通信(如图中的sendMsg),这就是所谓信令服务。现在很多sample都是用socket.io建立一个service,通信双方通过同一个url进入同一个room,然后通过这个room中转信息。只是这种做法不适合商用。因为url也是需要通讯的。

理解上面的流程之后,就可以发现,实际上问题已经转化了。先有鸡还是先有蛋?或者说,先有信令服务还是先有WebRTC。

答案是明显的,信令服务是必须的。哪怕是像例子程序一样凑合一个不完整的信令服务器出来。html5rocks网站上有一篇文章讲的比较明白。信令服务现在有几种做法:

  • 基于XMPP构建即时消息通讯服务器,用strophe等js访问
  • 基于类似ZeroMQ的开源库自行构建,如TokBox的Rumour服务
  • 使用支持WebSocket的商用云消息平台,如Pusher/Kaazing/PubNub
  • 直接使用商用WebRTC平台,如vLine

对于个人而言,我觉得第一条路子比较容易搭起来,资源比较多。

有了信令服务,配合比较新的browser,按照上面的流程图,局域网里面的WebRTC通讯基本就没什么问题了。对于Internet,需要STUN/TURN服务。找一台有公网IP的机器,配好rfc-5766-turnserver,并将url加入web应用即可。

总而言之,要做Web的视频通讯,只有WebRTC是不够的。至少还要有信令服务器和STUN/TURN服务器。WebRTC只关心视频通讯的部分。真正的通讯,是从信令服务开始的。

Top