V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
wilddog
V2EX  ›  问与答

如何使用野狗搭建视频聊天室-WebRTC 的技术实践

  •  
  •   wilddog · 2016-04-23 15:31:58 +08:00 · 2778 次点击
    这是一个创建于 2929 天前的主题,其中的信息可能已经有所发展或是发生改变。

    131444466 (1).jpg

    作者:潘嘉明 野狗科技嵌入式工程师,曾在 TP-Link 从事相关工作,在嵌入式研究上经验丰富。

    一直以来,因为涉及音视频编解码、 P2P 穿越等许多复杂的技术,同时还需要客户端以及浏览器插件的支持,实时视频通信的开发成本很高,只有大公司才会去做。

    WebRTC ( http://webrtc.org/ ) 是 google 主推的一个项目,旨在使得浏览器能为实时通信( RTC )提供简单的 JavaScript 接口。有了它,直接通过浏览器的 Web 页面就可以实现音视频聊天功能,无需任何插件。

    从著名的浏览器兼容性查询网站 caniuse.com 可以查询到各浏览器对 WebRTC 的支持情况。其中, Edge 浏览器支持类似 WebRTC 的 ORTC 。可以说,从市场占有率来看,大部分场景下都能够使用 WebRTC 进行通信。

    嘉明 1.png

    下面我们从 webrtc 的基本原理开始介绍。

    基本概念

    嘉明 2_meitu_5.jpg

    上图是一个简单的 WebRTC 三角关系图。图中,两台电脑 A 和 B 想要建立实时音视频聊天。由于它们在不同的内网,因此无法直接建立音视频管道。它们首先连接到一个服务器, WebRTC 称之为信令服务器( signal server )。通过信令服务器,二者交换建立管道的一些必要信息(信令,采用 SDP 协议编码),如音视频格式、帧率,二者的 ip 地址等。

    收到对方信令后,它们分别将其交给 WebRTC 底层,由底层实现二者间管道的建立。管道建立完成后,数据直接通过管道交互,无需再经过信令服务器。

    交互过程

    嘉明 3_meitu_6.jpg

    它们之间交互的流程如上图:

    1. 电脑 A 获知自己的外网 ip 和端口,并通过信令服务器向电脑 B 发送请求( offer 信令)。

    2. 电脑 B 收到 A 的请求后,处理 A 的 offer 信令,并将结果( answer 信令)通过信令服务器返回给 A 。

    3. 在此过程中, WebRTC 底层同时会生成很多 candidate (候选项)信息, candidate 信息包括电脑的内网 IP ,外网 IP 等。电脑 A 和 B 将生成的 candidate 也通过信令服务器传递给对方。

    4. WebRTC 底层根据这些信息,建立管道。

    可以看出, A 和 B 之间的信令交换需要一个公网服务器来做中转。然而大部分技术爱好者自行搭建信令交换服务还是比较复杂的。

    我们注意到, A 和 B 的信令交换实质上就是二者数据同步的过程, Wilddog 的数据通信服务可以很好的解决数据同步的问题,那么通过 Wilddog 就可以轻松实现 A 和 B 的信令交换,非常简单快捷,还不需要服务器。

    使用 Wilddog 建立视频聊天室

    关于野狗实时后端云的使用,这里就不展开介绍了,有兴趣的朋友自行到 www.wilddog.com 去了解就好。为了方便处理,我们在野狗云端设计下图的数据结构:

    嘉明 4.png

    其中的 value 字段只是示意。真实的 value 字段是较长的,采用 SDP 协议编码的。 roomname 为房间名称,每个用户进入房间后,在房间下面根据自己的 userId 创建子节点,如果有向其他用户通信的需求,则向其他用户的 mailbox 发送信件。

    同时,用户会监听自身的 mailbox ,可以实时的发现 mailbox 中来了新的信件,则处理这封信件,需要回复的话则向对方的 mailbox 回信。

    我们将 offer 、 answer 、 candidate 这几种信令都抽象成信件,通过 Wilddog 的实时同步,将信件同步给对方。整体流程图如下:

    嘉明 5.png

    让我们以电脑 A 和 B 来举例:

    1. A 和 B 打开浏览器后都调用 getUserMedia 获取本地视频流,并在浏览器上播放;

    2. B 先进入房间,此时房间中没有其他用户, B 在房间下建立属于自己的节点,且监听自己的信箱;

    3. A 进入房间,发现 B 已存在,此时 A 调用 createOffer 生成 offer 信令,并使用 setLocalDescription 存储到本地,然后向 B 的节点下面的信箱发送 offer ,同时, A 也监听自己的信箱;

    4. B 发现信箱下有信件,查知此信为 A 的 offer , B 调用 setRemoteDescription 将其存储到本地,然后使用 createAnswer 生成 answer 信令,使用 setLocalDescription 存储到本地,然后向 A 的信箱发送 answer ;

    5. A 发现信箱下有信件,查知此信为 B 的 answer , A 调用 setRemoteDescription 将其存储到本地;

    6. 与此同时, A 和 B 都可能触发 onicecandidate 事件, WebRTC 底层会将收集的 candidate 信令报告给上层,这种信令也需要向对方的信箱发送,对方收到这类信件后,调用 addCandidate 将之保存到本地;

    7. 在收集足够多的信令后, WebRTC 底层会将 A 和 B 之间的管道打通, A 和 B 会触发 onaddstream 事件,事件的回调函数中,会收到对方的 stream 流,可以用来在浏览器端播放。

    实现源码

    上文描述的基于 webrtc 的音视频聊天室的实现源码在 github 上供大家参考: https://github.com/itolfh/demo-webrtc-onepeer 这段源码只实现了一对一视频聊天。要实现类似视频会议的多人聊天也很容易,在此基础上的改动也不会太大。

    需要注意的是,在 chrome 浏览器上调用 getUserMedia 接口,要求页面必须使用 https 服务,不能使用 http 或者本地打开。而使用 firefox 浏览器则无此限制,因此如果采用 firefox ,可以将网页传给好友并本地打开,两边输入相同房间号,即可以进行实时音视频聊天。而使用 chrome 则需要搭建 https 服务。

    总结

    使用 Wilddog ,我们轻松解决了信令服务器的问题,无需服务器,也能够搭建本地视频聊天室了。然而大家可能会好奇,两个在不同内网的电脑,是如何能够建立管道的? candidate 中的 ip 信息,包括什么?又是从哪获取的呢?这些疑问也就是本文开篇时提到的穿越(有的文章中也叫做穿透)的问题了,我们将在后续的文章中解答大家的疑惑。

    qrcode_for_gh_55dcc2c31752_258 (2).jpg

    关注野狗官方微信,获取更多技术干

    2 条回复    2016-04-24 15:07:59 +08:00
    SourceMan
        1
    SourceMan  
       2016-04-23 15:45:30 +08:00   ❤️ 1
    进来,第一件事:把滚动条拉到最后,嗯,然后关闭浏览器标签
    Akagi201
        2
    Akagi201  
       2016-04-24 15:07:59 +08:00
    感谢分享, 文章有干货.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1145 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:04 · PVG 02:04 · LAX 11:04 · JFK 14:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.