本文由ELab技術(shù)團隊分享,原題“淺談WebRTC技術(shù)原理與應用”,有修訂和改動。
1圃酵、基本介紹
WebRTC(全稱 Web Real-Time Communication)球恤,即網(wǎng)頁即時通信辜昵。 是一個支持網(wǎng)頁瀏覽器進行實時語音對話或視頻對話的技術(shù)方案。從前端技術(shù)開發(fā)的視角來看咽斧,是一組可調(diào)用的API標準堪置。
在WebRTC發(fā)布之前,開發(fā)實時音視頻交互應用的成本是非常昂貴张惹,需要考慮的技術(shù)問題很多舀锨,如音視頻的編解碼問題,數(shù)據(jù)傳輸問題宛逗,延時坎匿、丟包、抖動、回音的處理和消除等替蔬,如果要兼容瀏覽器端的實時音視頻通信告私,還需要額外安裝插件。
2010年5月:Google以6820萬美元收購VoIP軟件開發(fā)商Global IP Solutions的GIPS引擎承桥,并改為名為“WebRTC”(見《了不起的WebRTC:生態(tài)日趨完善驻粟,或?qū)崟r音視頻技術(shù)白菜化》)。旨在建立一個互聯(lián)網(wǎng)瀏覽器間的實時通信的平臺凶异,讓 WebRTC技術(shù)成為 H5標準之一蜀撑。
2012年1月:谷歌已經(jīng)把這款軟件集成到Chrome瀏覽器中,Opera初步集成WebRTC剩彬。
2013年 6月:Mozilla Firefox[5]發(fā)布22.0版本正式集成及支持WebRTC酷麦。
2017年11月:W3C WebRTC 1.0 草案正式定稿。
2021年1月:WebRTC 被 W3C 和 IETF 發(fā)布為正式標準(見《WebRTC 1.0: Real-Time Communication Between Browsers》)喉恋。
2沃饶、重要意義
WebRTC的出現(xiàn)、發(fā)展和被業(yè)內(nèi)標準組織(如W3C)等普遍認可瀑晒,對于當下和未來大前端技術(shù)發(fā)展具有重要的意義绍坝。
降低在web端的音視頻交互開發(fā)門檻:
1)以往的音視頻交互開發(fā)對于Web開發(fā)者而言具有一定技術(shù)門檻徘意;
2)現(xiàn)在借助于WebRTC苔悦,Web開發(fā)者通過調(diào)用JS接口,可快速的實現(xiàn)音視頻交互應用椎咧。
避免依賴玖详、插件造成的次生問題:
1)以往的音視頻交互應用構(gòu)建依賴于各種插件、軟件和服務器等勤讽;
2)現(xiàn)在借助于主流瀏覽器即可形成端到端的音視頻交互蟋座。
統(tǒng)一化和標準化對傳統(tǒng)音視頻交互環(huán)境差異性的規(guī)避:
1)以往音視頻交互需要面對不同的 NAT 、防火墻對媒體 P2P 的建立帶來了很大的挑戰(zhàn)脚牍;
2)現(xiàn)在WebRTC 中有P2P 打洞的開源項目 libjingle ,支持 STUN向臀,TURN 等協(xié)議。
更高效優(yōu)化的算法诸狭、技術(shù)對于音視頻交互性能的提升:
1)WebRTC 通過NACK券膀、FEC技術(shù),避免了經(jīng)過服務端路由中轉(zhuǎn)驯遇,減少了延遲和帶寬消耗芹彬;
2)還有 TCC + SVC + PACER + JitterBuffer 等技術(shù)對于音視頻流暢性進行了優(yōu)化。
3叉庐、技術(shù)特征
WebRTC內(nèi)容豐富舒帮,主要的技術(shù)特征包含以下幾點。
1)實時通訊:
WebRTC是一項實時通訊技術(shù),允許網(wǎng)絡應用或者站點玩郊,在不借助中間媒介的情況下肢执,建立瀏覽器之間點對點(Peer-to-Peer)的連接,實現(xiàn)視頻流和(或)音頻流或者其他任意數(shù)據(jù)的傳輸译红。
2)無依賴/插件:
WebRTC包含的這些標準使用戶在無需安裝任何插件或者第三方的軟件的情況下蔚万,創(chuàng)建點對點(Peer-to-Peer)的數(shù)據(jù)分享和電話會議成為可能。
3)協(xié)議棧 眾多:
WebRTC并不是單一的協(xié)議临庇,包含了媒體反璃、加密、傳輸層等在內(nèi)的多個協(xié)議標準以及一套基于 JavaScript的 API假夺,它包括了音視頻的采集淮蜈、編解碼、網(wǎng)絡傳輸已卷、顯示等功能梧田。通過簡單易用的 JavaScript API ,在不安裝任何插件的情況下侧蘸,讓瀏覽器擁有了 P2P音視頻和數(shù)據(jù)分享的能力裁眯。
WebRTC依賴眾多協(xié)議棧圖:
同時WebRTC 并不是一個孤立的協(xié)議,它擁有靈活的信令讳癌,可以便捷的對接現(xiàn)有的SIP 和電話網(wǎng)絡的系統(tǒng)穿稳。
4、兼容覆蓋
目前大部分主流瀏覽器都正常兼容WebRTC:
▲ 上圖引用自《WebRTC實時音視頻技術(shù)的整體架構(gòu)介紹》
更詳細的瀏覽器及版本兼容情況晌坤,可以看看下圖:
▲ 上圖引用自《https://caniuse.com/rtcpeerconnection》
主流瀏覽器都支持 WebRTC 標準 API 逢艘,因此也讓瀏覽器之間無插件化的音視頻互通成為可能, 大大降低了音視頻開發(fā)的門檻骤菠,開發(fā)者只需要調(diào)用 WebRTC API 即可快速構(gòu)建出音視頻應用它改。
5、技術(shù)框架
如下圖所示:的技術(shù)框架描述了WebRTC的核心內(nèi)容和面向不同開發(fā)者的API設計商乎。
WebRTC技術(shù)框架圖:
▲ 上圖引用自《零基礎(chǔ)入門:基于開源WebRTC央拖,從0到1實現(xiàn)實時音視頻聊天功能》
從圖中可看到,WebRTC主要面向三類開發(fā)者的API設計:
1)對于Web開發(fā)者的API:框架包含了基于JavaScript 鹉戚、 經(jīng)過W3C認證了的一套API標準鲜戒,使得web開發(fā)者可以基于這套API開發(fā)基于WebRTC的即時通訊應用;
2)對于瀏覽器廠商的API:框架同樣包含了基于C++的底層WebRTC接口崩瓤,對于瀏覽器廠商底層的接入十分友好袍啡;
3)瀏覽器廠商可自定義的部分:框架中還包含瀏覽器廠商可自定義的音視頻截取等擴展部分。
6却桶、技術(shù)核心
從上節(jié)框架中可以看到境输,WebRTC主要有音頻蔗牡、視頻引擎和傳輸三部分組成,其中又包含眾多的協(xié)議和方法等嗅剖。
1)Voice Engine(音頻引擎):
a辩越、Voice Engine包含iSAC/iLBC Codec(音頻編解碼器,前者是針對寬帶和超寬帶信粮,后者是針對窄帶)黔攒;
b、NetEQ for voice(處理網(wǎng)絡抖動和語音包丟失)强缘;
c督惰、Echo Canceler(回聲消除器)/ Noise Reduction(噪聲抑制)。
2)Video Engine(視頻引擎):
a旅掂、VP8 Codec(視頻圖像編解碼器)赏胚;
b、Video jitter buffer(視頻抖動緩沖器商虐,處理視頻抖動和視頻信息包丟失)觉阅;
c、Image enhancements(圖像質(zhì)量增強)秘车。
3)Transport典勇。
7、技術(shù)原理
7.1 基本情況
WebRTC主要的技術(shù)特征:
1)SRTP:安全的實時傳輸協(xié)議叮趴,用于音視頻流傳輸割笙;
2)Multiplexing:多路復用;
3)P2P:STUN+TURN+ICE疫向,用于NAT網(wǎng)絡和防火墻穿越咳蔚;
4)DTLS:安全傳輸可能還會用到DTLS(數(shù)據(jù)報安全傳輸)豪嚎,用于加密傳輸和密鑰協(xié)商搔驼;
5)UDP:整個WebRTC通信是基于UDP的。
限于篇幅侈询,本文以下章節(jié)將不細致介紹音視頻采集舌涨、編碼和處理等內(nèi)容,僅介紹實時通訊的建立過程原理的核心內(nèi)容扔字。
7.2 公網(wǎng)IP映射:明確網(wǎng)絡定位信息
WebRTC是基于瀏覽器端到端的連接(P2P)實現(xiàn)的.
由于不需要服務器中轉(zhuǎn),所以獲取連接對象的網(wǎng)絡地址的方式,是借助于ICE奏窑、STUN糕簿、TURN等輔助內(nèi)網(wǎng)穿透技術(shù)(NAT)得到對應主機的公網(wǎng)網(wǎng)絡地址和端口等網(wǎng)絡定位信息。
明確網(wǎng)絡定位是建立端與端直接通訊的基礎(chǔ)震檩。
NAT穿透原理圖:
STUN服務器用于輔助內(nèi)網(wǎng)穿透得到對應主機的公網(wǎng)網(wǎng)絡地址和端口信息圖:
▲ 上圖引用自《WebRTC實時音視頻技術(shù)的整體架構(gòu)介紹》
7.3 信令服務器:網(wǎng)絡協(xié)商與信息交換
信令服務器的作用是基于雙工通信來中轉(zhuǎn)信息琢蛤。
中轉(zhuǎn)信息包括公網(wǎng)IP映射后的網(wǎng)絡定位信息蜓堕,比如:公網(wǎng)IP、端口和媒體數(shù)據(jù)流等博其。
概念圖:
信令服務器信息交互過程圖:
7.4 會話描述協(xié)議SDP:統(tǒng)一的媒體協(xié)商方式
SDP的作用:
1)不同端/瀏覽器對于媒體流數(shù)據(jù)的編碼格式各異套才,如VP8、VP9等慕淡,參與會話的各個成員的能力不對等背伴、用戶環(huán)境與配置不一致等;
2)WebRTC通訊還需要確定和交換本地和遠程音頻和視頻媒體信息峰髓,例如分辨率和編解碼器功能傻寂。交換媒體配置信息的信令通過使用會話描述協(xié)議 (SDP) 交換Offer和Anwser來進行;
3)SDP的交換一定是先于音視頻流交換的携兵。其內(nèi)容包括會話基本信息崎逃、媒體信息描述等。
//SDP的結(jié)構(gòu)體
Session description(會話級別描述)
?????????v=? (protocol version)
?????????o=? (originator and session identifier)
?????????s=? (session name)
?????????c=* (connection information -- not required ifincluded inall media)
?????????One or moreTime descriptions ("t="and "r="lines; see below)
?????????a=* (zero or moresession attribute lines)
?????????Zero or moreMedia descriptions
Time description
?????????t=? (timethe session is active)
Media description(媒體級別描述), ifpresent
?????????m=? (media name and transport address)
?????????c=* (connection information -- optional ifincluded at session level)
?????????a=* (zero or moremedia attribute lines)
一個SDP例子如下:
v=0 //代表版本眉孩,目前一般是`v=0`.
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0 //會話處于活動狀態(tài)的時間
a=group:BUNDLE audio video //:描述服務質(zhì)量个绍,傳輸層復用相關(guān)信息
m=audio 1 RTP/SAVPF103 104 0 8 106 105 13 126 //...
a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh81
7.5 一對一連接建立過程
以建立一對一的Web RTC連接過程為例來簡要講解。
一對一過程圖:
簡要過程圖:
如上圖所示浪汪,解釋一下:
1)交換SDP巴柿,獲取各自媒體配置信息;
2)STUN服務器交換網(wǎng)絡地址和端口等網(wǎng)絡信息死遭;
3)Turn中轉(zhuǎn)音視頻媒體流數(shù)據(jù)广恢。
工作流程圖:
如上圖所示,解釋一下:
1)A和B雙方先調(diào)用 getUserMedia 打開本地攝像頭呀潭,作為本地待輸出媒體流钉迷;
2)向信令服務器發(fā)送加入房間請求;
3)Peer B 接收到 Peer A 發(fā)送的 offer SDP 對象钠署,并通過PeerConnection的SetLocalDescription方法保存 Answer SDP 對象并將它通過信令服務器發(fā)送給 Peer A糠聪;
4)在 SDP 信息的 offer/answer 流程中,Peer A 和 Peer B 已經(jīng)根據(jù) SDP 信息創(chuàng)建好相應的音頻 Channel 和視頻 Channel谐鼎,并開啟Candidate 數(shù)據(jù)的收集舰蟆,Candidate數(shù)據(jù)(本地IP地址、公網(wǎng)IP地址狸棍、Relay服務端分配的地址)身害;
5)當 Peer A 收集到 Candidate 信息后通過信令服務器發(fā)送給 Peer B。同樣的過程 Peer B 對 Peer A 也會再發(fā)送一次草戈。
7.6 多對多的建立
多對多建立點到點連接概念圖塌鸯,以三個用戶點對點的連接為例:
7.7 WebRTC的主要JavaScrip接口
getUserMedia():訪問數(shù)據(jù)流,例如來自用戶的相機和麥克風
//請求媒體類型
const constraints = {
??video: true
??audio:true
};
const video = document.querySelector('video');
//掛載流到相應dom展示本地媒體流
function handleSuccess(stream) {
??video.srcObject = stream;
}
function handleError(error) {
??console.error('getUserMedia error: ', error);
}
//利用攝像頭捕獲多媒體流
navigator.mediaDevices.getUserMedia(constraints).
??then(handleSuccess).catch(handleError);
RTCPeerConnection:通過加密和帶寬管理工具啟用音頻或視頻通話
// 允許 RTC 服務器配置唐片。
const server = {
????"iceServers":
????????????[{ "urls": "stun:stun.stunprotocol.org"}]
};
// 創(chuàng)建本地連接
const localPeerConnection = newRTCPeerConnection(servers);
// 收集Candidate 數(shù)據(jù)
localPeerConnection.onicecandidate=function(event){
????...
}
// 監(jiān)聽到媒體流接入時的操作
localPeerConnection.ontack=function(event){
????...
}
RTCDataChannel:支持通用數(shù)據(jù)的點對點通信丙猬,常用于數(shù)據(jù)點到點的傳輸
const pc = newRTCPeerConnection();
const dc = pc.createDataChannel("my channel");
//接受數(shù)據(jù)
dc.onmessage = function(event) {
??console.log("received: "+ event.data);
};
//打開傳輸
dc.onopen = function() {
??console.log("datachannel open");
};
//關(guān)閉傳輸
dc.onclose = function() {
??console.log("datachannel close");
};
8丢习、應用案例
這里以WebRTC的多人視頻案例為實踐來大致演示一下。
8.1 設計框架
多人視頻基本框架圖:
8.2 關(guān)鍵代碼
8.2.1)媒體捕獲:
獲取瀏覽器視頻權(quán)限淮悼,捕獲本地視頻媒體流咐低,在Video元素中附加媒體流,顯示本地視頻結(jié)果袜腥。代碼如下见擦。
//攝像頭兼容性處理
navigator.getUserMedia = ( navigator.getUserMedia ||
???????????????navigator.webkitGetUserMedia ||
???????????????navigator.mozGetUserMedia ||
???????????????navigator.msGetUserMedia);
// 獲取本地音頻和視頻流
navigator.mediaDevices.getUserMedia({
????????????????"audio": false,
????????????????"video": true
}).then( (stream)=> {
//顯示自己的輸出流,掛到頁面Video元素上
????document.getElementById("myVido").srcObject=stream
})
捕獲本地視頻媒體流的顯示結(jié)果截圖:
為每個新的客戶端連接創(chuàng)建RTCPeerConnection對象:
// stun和turn服務器? const iceServer = {
????"iceServers": [{
????????urls:"stun:stun.l.google.com:19302"
????}]
};
//為點到點的連接創(chuàng)建RTCPeerConnection
const peerRTCConn=newRTCPeerConnection(iceServer);
8.2.2)網(wǎng)絡協(xié)商:
主要任務就是:創(chuàng)建對等連接羹令,收集ICE候選鲤屡,等待媒體流接入時掛載到dom。
交互式連通性建立(Interactive Connectivity Establishment — ICE)是一個允許實時對等端發(fā)現(xiàn)對方并且彼此連接的框架福侈。此技術(shù)允許對等方發(fā)現(xiàn)有關(guān)彼此拓撲的足夠信息酒来,從而有可能在彼此之間找到一條或多條通信路徑。ICE 代理負責:收集本地IP肪凛,端口元組候選堰汉、在同級之間執(zhí)行連接檢查和發(fā)送連接保持活動。(關(guān)于ICE的介紹伟墙,見《P2P技術(shù)之STUN翘鸭、TURN、ICE詳解》)
// 發(fā)送ICE候選到其他客戶端 peerRTCConn.onicecandidate = function(event){
????if(event.candidate) {
????????//向信令服務器轉(zhuǎn)發(fā)收集到的ICE候選????????? socket.send(JSON.stringify({
????????????"event": "relayICECandidate",
????????????"data": {
????????????????'iceCandidate': {
????????????????????'sdpMLineIndex': event.candidate.sdpMLineIndex,
????????????????????'candidate': event.candidate.candidate
????????????????}
????????????},
????????????"fromID":signalMsg['data']['peerId']
????????}));
????}
}
//有媒體流介入就掛載dom peerRTCConn.ontrack=function(event){
????let v=document.createElement("video")
????v.autoplay=true
????v.style="width:200px"
????document.getElementById("peer").appendChild(v)
????v.srcObject=event.streams[0]
}
8.1.3)媒體協(xié)商:
發(fā)起時創(chuàng)建Offer戳葵。peer利用setLocalDescription方法將會話信息加到RTCPeerConnection()就乓,并由信令服務器中轉(zhuǎn)。其他Peer會返回相應的Answer拱烁。SDP過程:
//新加入節(jié)點發(fā)起offer? if(canOffer){
????peerRTCConn.createOffer(
????????function(localDescription) {
?????????????peerRTCConn.setLocalDescription(localDescription,
????????????????function() {
????????????????????//發(fā)送描述信息給信令服務器???????????????????????? socket.send(JSON.stringify({
????????????????????????"event":"relaySessionDescription",
????????????????????????"data":localDescription,
????????????????????????"fromID":peerId
????????????????????}))
?????????????????},
????????????????function() { alert("offer failed"); }
????????????);
????????},
????????function(error) {
????????????console.log("error sending offer: ", error);
????????}
????)
}
響應時創(chuàng)建Answer生蚁。會話描述包括音視頻信息等內(nèi)容,當發(fā)起者向響應者發(fā)出offer類型的描述后戏自,響應者會返回answer類型的描述:
//創(chuàng)建Answer會話
peer.createAnswer(
function(_remoteDescription) {
?????peer.setLocalDescription(_remoteDescription,
????????function() {
???????????????//發(fā)送描述信息給信令服務器????????????????? socket.send(JSON.stringify({
????????????????????"event":"relaySessionDescription",
????????????????????"data":_remoteDescription,
????????????????????"callerID":signalMsg['fromId'],
????????????????????"fromID":signalMsg['fromId']
????????????????}))??????? },
????????function() { alert("answer failed"); }
????);
},
function(error) {
????console.log("error creating answer: ", error);
});
當收到ICE候選共享后邦投,會把ICE候選添加到遠程對等點描述中:
//對應的RTCPeerConnection
const peer = peers[signalMsg["fromID"]];
//ICE候選添加到遠程對等點描述
peer.addIceCandidate(newRTCIceCandidate(signalMsg["data"].iceCandidate));
多人視頻結(jié)果截圖<本地模擬效果>:
8.2.4)信令中轉(zhuǎn):
信令服務部分關(guān)鍵代碼:
wss.on('connection', function(ws) {
????ws.on('message', function(message) {
????????let meeageObj=JSON.parse(message)
????????//交換ICE候選???????? if (meeageObj['event'] =='relayICECandidate') {???????????? wss.clients.forEach(function (client) {
????????????????console.log("send iceCandidate")
????????????????????client.send(JSON.stringify({
????????????????????????"event": "iceCandidate",
????????????????????????"data": meeageObj['data'],
????????????????????????"fromID": meeageObj['fromID']
????????????????????}));?????????
????????????});
????????}
????????//交換SDP
???????? if (meeageObj['event'] =='relaySessionDescription') {
????????????console.log(meeageObj["fromID"],meeageObj["data"].type)
????????????wss.clients.forEach(function(client) {
????????????????if(client!=ws) {
????????????????????client.send(JSON.stringify({
????????????????????????"event": "sessionDescription",
????????????????????????"fromId":meeageObj["fromID"],
????????????????????????"data": meeageObj["data"],
????????????????????}));
????????????????}
????????????});
????????}
????})
})
9、小結(jié)一下
WebRTC的優(yōu)點主要是:
1)方便:對于用戶來說浦妄,在WebRTC出現(xiàn)之前想要進行實時通信就需要安裝插件和客戶端尼摹,但是對于很多用戶來說,插件的下載剂娄、軟件的安裝和更新這些操作是復雜而且容易出現(xiàn)問題的,現(xiàn)在WebRTC技術(shù)內(nèi)置于瀏覽器中玄呛,用戶不需要使用任何插件或者軟件就能通過瀏覽器來實現(xiàn)實時通信阅懦。對于開發(fā)者來說,在Google將WebRTC開源之前徘铝,瀏覽器之間實現(xiàn)通信的技術(shù)是掌握在大企業(yè)手中耳胎,這項技術(shù)的開發(fā)是一個很困難的任務惯吕,現(xiàn)在開發(fā)者使用簡單的HTML標簽和JavaScript API就能夠?qū)崿F(xiàn)Web音/視頻通信的功能。
2)免費:雖然WebRTC技術(shù)已經(jīng)較為成熟怕午,其集成了最佳的音/視頻引擎废登,十分先進的codec,但是Google對于這些技術(shù)不收取任何費用郁惜。
3)強大的打洞能力:WebRTC技術(shù)包含了使用STUN堡距、ICE、TURN兆蕉、RTP-over-TCP的關(guān)鍵NAT和防火墻穿透技術(shù)羽戒,并支持代理。
WebRTC的缺點主要是:
1)缺乏服務器方案的設計和部署虎韵。
2)傳輸質(zhì)量難以保證易稠。WebRTC的傳輸設計基于P2P,難以保障傳輸質(zhì)量包蓝,優(yōu)化手段也有限驶社,只能做一些端到端的優(yōu)化,難以應對復雜的互聯(lián)網(wǎng)環(huán)境测萎。比如對跨地區(qū)衬吆、跨運營商、低帶寬绳泉、高丟包等場景下的傳輸質(zhì)量基本是靠天吃飯逊抡,而這恰恰是國內(nèi)互聯(lián)網(wǎng)應用的典型場景。
3)WebRTC比較適合一對一的單聊零酪,雖然功能上可以擴展實現(xiàn)群聊冒嫡,但是沒有針對群聊,特別是超大群聊進行任何優(yōu)化四苇。
4)設備端適配孝凌,如回聲、錄音失敗等問題層出不窮月腋。這一點在安卓設備上尤為突出蟀架。由于安卓設備廠商眾多,每個廠商都會在標準的安卓框架上進行定制化榆骚,導致很多可用性問題(訪問麥克風失斊摹)和質(zhì)量問題(如回聲、嘯叫)妓肢。
5)對Native開發(fā)支持不夠捌省。WebRTC顧名思義,主要面向Web應用碉钠,雖然也可以用于Native開發(fā)纲缓,但是由于涉及到的領(lǐng)域知識(音視頻采集卷拘、處理、編解碼祝高、實時傳輸?shù)龋┹^多栗弟,整個框架設計比較復雜,API粒度也比較細工闺,導致連工程項目的編譯都不是一件容易的事乍赫。
10、參考資料
[1]?開源實時音視頻技術(shù)WebRTC的現(xiàn)狀
[2]?簡述開源實時音視頻技術(shù)WebRTC的優(yōu)缺點
[3]?訪談WebRTC標準之父:WebRTC的過去斤寂、現(xiàn)在和未來
[4]?良心分享:WebRTC 零基礎(chǔ)開發(fā)者教程(中文)[附件下載]
[5]?WebRTC實時音視頻技術(shù)的整體架構(gòu)介紹
[6]?新手入門:到底什么是WebRTC服務器耿焊,以及它是如何聯(lián)接通話的?
[7]?WebRTC實時音視頻技術(shù)基礎(chǔ):基本架構(gòu)和協(xié)議棧
[8]?淺談開發(fā)實時視頻直播平臺的技術(shù)要點
[9]?基于開源WebRTC開發(fā)實時音視頻靠譜嗎遍搞?第3方SDK有哪些罗侯?
[10]?開源實時音視頻技術(shù)WebRTC在Windows下的簡明編譯教程
[11]?網(wǎng)頁端實時音視頻技術(shù)WebRTC:看起來很美,但離生產(chǎn)應用還有多少坑要填溪猿?
[12]?了不起的WebRTC:生態(tài)日趨完善钩杰,或?qū)崟r音視頻技術(shù)白菜化
[13]?零基礎(chǔ)入門:基于開源WebRTC,從0到1實現(xiàn)實時音視頻聊天功能
[14]?P2P技術(shù)詳解(一):NAT詳解——詳細原理诊县、P2P簡介
[15]?P2P技術(shù)詳解(二):P2P中的NAT穿越(打洞)方案詳解(基本原理篇)
(本文已同步發(fā)布于:http://www.52im.net/thread-3804-1-1.html?)