WebRTC 是一個支持網頁瀏覽器進行實時語音對話或視頻對話的技術,谷歌 2010 年以 6820 萬美元收購 Global IP Solutions 公司而獲得的一項技術。2011 年 5 月開放了工程的源代碼,在行業(yè)內得到了廣泛的支持和應用,成為下一代視頻通話的標準,該項目的最終目的主要是讓 Web 開發(fā)者能夠基于瀏覽器 (Chrome\FireFox\…)輕易快捷開發(fā)出豐富的實時多媒體應用,而無需下載安裝 任何插件,Web 開發(fā)者也無需關 s 注多媒體的數字信號處理過程,只需編寫簡單 的 Javascript 程序即可實現(xiàn),W3C 等組織正在制定 Javascript 標準 API,目前是 WebRTC 1.0 版本,Draft 狀態(tài);另外,WebRTC 還希望能夠建立一個多互聯(lián)網瀏 覽器間健壯的實時通信的平臺,形成開發(fā)者與瀏覽器廠商良好的生態(tài)環(huán)境。同時, Google 也希望和致力于讓 WebRTC 的技術成為 HTML5 標準之一。
介紹完 webRTC 的歷史,那么我們如何在 HTML 頁面中建立一個 RTC 應用呢?
首先,向瀏覽器申請調用瀏覽器的權限,使用navigator.webkitGetUserMedia()或 MediaDevices.getUserMedia()。比較尷尬的一點是,javascript 接口由 Mozilla 社區(qū)開發(fā)的,所以火狐瀏覽器跟進的比較快,而谷歌還在沿用上一套接口,前者 在 Mozilla 社區(qū)已經標記為不建議使用的接口,不過鑒于目前 webkit 內核的瀏覽 器比較多,所以本文以前者的接口為主,并且 webkit 內核版本要在 36 以上,但 在 webkit47 以上的版本調用媒體設備的時候必須用 https 協(xié)議,用來保證安全, 而 firefox 要求相對沒有那么嚴格,由于 firefox 瀏覽器在國內是不需要翻墻更新 的,所以只需要更新到最新版本,那么支持就沒有什么問題。
navigator.webkitGetUserMedia()方法需要四個參數,第一個參數直接傳入 navigator 對象,第二個參數為調用的硬件{audio: true,video:true},如果不需要調用 攝像頭,則 video 為 false,不寫則默認為 false。第三第四個為正確和錯誤回調函數。
如: getUserMedia.call(navigator, {audio: true,video:true}, resolve, reject);
第二個參數為成功回調函數,第三個參數為失敗回調函數。失敗回調會傳入 一個參數,為失敗信息。
成功回調函數會將一個媒體流作為參數傳入進來,此時創(chuàng)建一個 RTCPeerConnection 來存放流傳輸的通道,創(chuàng)建 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)創(chuàng)建一個 offer,創(chuàng) 建成功后,觸發(fā)成功回調,傳入一個 description(簡寫為 desc),將這個 desc 作 為參數設置為本地描述,此外這個 desc 還有一個作用,它有一個 sdp 對象,存 放的 sdp 串,需要將這個傳發(fā)送到接收方用以作為溝通的協(xié)議。
如:pc.setLocalDescription(desc,callback,error);
當 pc.iceGatheringState == "complete"時,設置成功,至此,發(fā)送方的已經完成。
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 串作為協(xié)議,設置遠程描述,也就是發(fā)送 方的信息,需要的參數則是 RTCSessionDescription 對象,RTCSessionDescription 對象需要一個對象參數,對象包含 type 類型“offer”,另一個就是發(fā)送方發(fā)來的 sdp 串。
即:var sessionDescription = new RTCSessionDescription({type: "offer",sdp: receiveSdp} pc.setRemoteDescription(sessionDescription,callback,error); 設置完遠程描述后,需要將此消息告訴發(fā)送方,所以在成功回調中發(fā)送一個answer 請求,有些不同的是,pc.createAnswer 的前兩個參數都是回調函數,第 三個才是參數:{mandatory: {OfferToReceiveAudio: true,OfferToReceiveVideo: isVideo}};表示回復發(fā)送方,接受你的 audio 和 video 流。
即:var sessionDescription = new RTCSessionDescription({type: "offer",sdp: receiveSdp} pc.setRemoteDescription(sessionDescription,callback,error); 設置完遠程描述后,需要將此消息告訴發(fā)送方,所以在成功回調中發(fā)送一個answer 請求,有些不同的是,pc.createAnswer 的前兩個參數都是回調函數,第 三個才是參數:{mandatory: {OfferToReceiveAudio: true,OfferToReceiveVideo: isVideo}};表示回復發(fā)送方,接受你的 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 規(guī)范的的 RTC 應用目前重點還是以適配這 2 款瀏覽器為主。