WebRTC 是一个支持网页浏览器进行实时语音对话或视频对话的技术,谷歌 2010 年以 6820 万美元收购 Global IP Solutions 公司而获得的一项技术。2011 年 5 月开放了工程的源代码,在行业内得到了广泛的支持和应用,成为下一代视频通话的标准,该项目的最终目的主要是让 Web 开发者能够基于浏览器 (Chrome\FireFox\…)轻易快捷开发出丰富的实时多媒体应用,而无需下载安装 任何插件,Web 开发者也无需关 s 注多媒体的数字信号处理过程,只需编写简单 的 Javascript 程序即可实现,W3C 等组织正在制定 Javascript 标准 API,目前是 WebRTC 1.0 版本,Draft 状态;另外,WebRTC 还希望能够建立一个多互联网浏 览器间健壮的实时通信的平台,形成开发者与浏览器厂商良好的生态环境。同时, Google 也希望和致力于让 WebRTC 的技术成为 HTML5 标准之一。
介绍完 webRTC 的历史,那么我们如何在 HTML 页面中建立一个 RTC 应用呢?
首先,向浏览器申请调用浏览器的权限,使用navigator.webkitGetUserMedia()或 MediaDevices.getUserMedia()。比较尴尬的一点是,javascript 接口由 Mozilla 社区开发的,所以火狐浏览器跟进的比较快,而谷歌还在沿用上一套接口,前者 在 Mozilla 社区已经标记为不建议使用的接口,不过鉴于目前 webkit 内核的浏览 器比较多,所以本文以前者的接口为主,并且 webkit 内核版本要在 36 以上,但 在 webkit47 以上的版本调用媒体设备的时候必须用 https 协议,用来保证安全, 而 firefox 要求相对没有那么严格,由于 firefox 浏览器在国内是不需要翻墙更新 的,所以只需要更新到最新版本,那么支持就没有什么问题。
navigator.webkitGetUserMedia()方法需要四个参数,第一个参数直接传入 navigator 对象,第二个参数为调用的硬件{audio: true,video:true},如果不需要调用 摄像头,则 video 为 false,不写则默认为 false。第三第四个为正确和错误回调函数。
如: getUserMedia.call(navigator, {audio: true,video:true}, resolve, reject);
第二个参数为成功回调函数,第三个参数为失败回调函数。失败回调会传入 一个参数,为失败信息。
成功回调函数会将一个媒体流作为参数传入进来,此时创建一个 RTCPeerConnection 来存放流传输的通道,创建 RTCPeerConnection 时需要两个参数,一个是 iceServer,即视频流传输地址,若没有特殊的代理则设置为空就可以。 另一个为可选项数组,这里只需要一个 DtlsSrtpKeyAgreement:true,将这两个参 数传入到 RTCPeerConnection 中,即可得到一个 peerConnection 对象
var pc = new peerConnection({"iceServers": []}, {optional:[{DtlsSrtpKeyAgreemen t:true}]});
然后,需要一个来播放此媒体流,
如:document.getElementById("myVideo").src = windowUrl.createObjectURL(stre am);,用来看到自己的视频,但同时还需要将媒体流通过 pc.addStrem(stream)传 给 peerConnection 对象,然后用 pc.createOffer(callback,error)创建一个 offer,创 建成功后,触发成功回调,传入一个 description(简写为 desc),将这个 desc 作 为参数设置为本地描述,此外这个 desc 还有一个作用,它有一个 sdp 对象,存 放的 sdp 串,需要将这个传发送到接收方用以作为沟通的协议。
如:pc.setLocalDescription(desc,callback,error);
当 pc.iceGatheringState == "complete"时,设置成功,至此,发送方的已经完成。
var pc = new peerConnection({"iceServers": []}, {optional:[{DtlsSrtpKeyAgreement:true}]}); getUserMedia.call(navigator,{audio: true,video:true},function(stream){pc.createOffer(function(desc){ pc.setLocalDescription(desc, function() {if(pc.iceGatheringState == "complete") {// 建立成功 }}, error);
}, error);},error);
接下来为应答方。
应答则是需要拿到对方使用的 SDP 串作为协议,设置远程描述,也就是发送 方的信息,需要的参数则是 RTCSessionDescription 对象,RTCSessionDescription 对象需要一个对象参数,对象包含 type 类型“offer”,另一个就是发送方发来的 sdp 串。
即:var sessionDescription = new RTCSessionDescription({type: "offer",sdp: receiveSdp} pc.setRemoteDescription(sessionDescription,callback,error); 设置完远程描述后,需要将此消息告诉发送方,所以在成功回调中发送一个answer 请求,有些不同的是,pc.createAnswer 的前两个参数都是回调函数,第 三个才是参数:{mandatory: {OfferToReceiveAudio: true,OfferToReceiveVideo: isVideo}};表示回复发送方,接受你的 audio 和 video 流。
即:var sessionDescription = new RTCSessionDescription({type: "offer",sdp: receiveSdp} pc.setRemoteDescription(sessionDescription,callback,error); 设置完远程描述后,需要将此消息告诉发送方,所以在成功回调中发送一个answer 请求,有些不同的是,pc.createAnswer 的前两个参数都是回调函数,第 三个才是参数:{mandatory: {OfferToReceiveAudio: true,OfferToReceiveVideo: isVideo}};表示回复发送方,接受你的 audio 和 video 流。
pc.setRemoteDescription(new sessionDescription({type: "offer",sdp: receiveSdp}), function() {
pc.createAnswer(function() {if(pc.iceGatheringState == "complete"){// 建立功}},error,constraints)}, remoteError)
至此,一次单程的 webrtc 就完成了,但是作为视频应用,单方面接通是不行 的,双方都看到对方的画面的话,就让被叫方也完成一次完整的视频呼叫就可以 了。
最后关于浏览器的兼容性,我们看两组数据:


从市场占有率和技术成熟度来看,前两名还是分属 Chrome 和Firefox。因此,基于 H5 规范的的 RTC 应用目前重点还是以适配这 2 款浏览器为主。