WebRTC介紹及簡單應用
轉自:https://www.cnblogs.com/vipzhou/p/7994927.html
WebRTC介紹及簡單應用
WebRTC,即Web Real-Time Communication,web實時通訊技術。簡單地說就是在web瀏覽器裡面引入實時通訊,包括音視訊通話等。
WebRTC實時通訊技術介紹
如何使用
媒體介紹
信令
STUN和TURN介紹
對等連線和提議/應答協商
資料通道
NAT和防火牆穿透
簡單應用
其它
WebRTC實時通訊技術介紹
WebRTC實現了基於網頁的語音對話或視訊通話,目的是無外掛實現web端的實時通訊的能力。
WebRTC提供了視訊會議的核心技術,包括音視訊的採集、編解碼、網路傳輸、展示等功能,並且還支援跨平臺,包括linux、windows、mac、android等。
-
WebRTC三角形
image -
WebRTC梯形
image -
WebRTC的多方會話
WebRTC支援多個瀏覽器參與的多方會話或會議會話,要建立這類會話有如下兩種模式:
image
image
- WebRTC新功能特性
image
如何使用WebRTC
WebRTC易於使用,只需極少步驟便可建立媒體會話。有些訊息在瀏覽器和伺服器之間流動,有些則直接在兩個瀏覽器(成為對等端)之間流動。
1、建立WebRTC會話
建立WebRTC連線需要如下幾個步驟:
獲取本地媒體(getUserMedia(),MediaStream API)
在瀏覽器和對等端(其它瀏覽器或終端)之間建立對等連線(RTCPeerConnection API)
將媒體和資料通道關聯至該連線
交換會話描述(RTCSessionDescription)
image
瀏覽器M從Web伺服器請求網頁
Web伺服器向M返回帶有WebRTC js的網頁
瀏覽器L從Web伺服器請求網頁
Web伺服器向L返回帶有WebRTC js的網頁
M決定與L通訊,通過M自身的js將M的會話描述物件(offer,提議)傳送至Web伺服器
Web伺服器將M的會話描述物件傳送至L上的js
L上的js將L的會話描述物件(answer,應答)傳送至Web伺服器
Web伺服器轉發應答至M上的js
M和L開始互動,確定訪問對方的最佳方式
完成後,M和L開始協商通訊金鑰
M和L開始交換語音、視訊或資料
WebRTC三角形會話具體的呼叫流程:
image
說明:
SDP物件的傳輸可能是一個來回反覆的過程,並且該過程採用的協議並未標準化
WebRTC梯形會話方式具體的呼叫流程:
image
說明:
此場景中,瀏覽器M和L直接交換媒體,只是它們執行的Web伺服器不用而已。每個瀏覽器的會話描述物件都會對映至Jingle[XEP-0166]session-initiate訊息和session-accept方法。
媒體介紹
先來看下WebRTC中的本地媒體:
1、WebRTC中的媒體
軌道(MediaStreamTrack,代表裝置或錄製內容可返回的單一型別的媒體,唯一關聯一個“源”,WebRTC不能直接訪問或控制“源”,對“源”的一切控制都通過軌道實施;一個“源”可能對應多個軌道物件)
流(MediaStream,軌道物件的集合)
軌道和流的示意如下:
image
2、捕獲本地媒體
如下程式碼展示了本地媒體的簡單獲取,並展示:
// 注意getUserMedia()在各瀏覽器中的區別
// Opera --> getUserMedia
// Chrome --> webkitGetUserMedia
// Firefox --> mozGetUserMedia
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// 只獲取video:
var constraints = {audio: false, video: true};
var video = document.querySelector("video");
function successCallback(stream) {
// Note: make the returned stream available to console for inspection
window.stream = stream;
if (window.URL) {
// Chrome瀏覽器
video.srcObject = stream;
} else {
// Firefox和Opera: 可以直接把視訊源設定為stream
video.src = stream;
}
// 播放
video.play();
}
function errorCallback(error){
console.log("navigator.getUserMedia error: ", error);
}
navigator.getUserMedia(constraints, successCallback, errorCallback);
執行效果如下:
image
完整程式碼檢視:https://github.com/caiya/webrtc-demo.git
信令
在WebRTC中,信令起著舉足輕重的作用。但實現沒有標準化,比如http、websocket、xmpp等。
1、信令的作用
協商媒體功能和設定
標識和驗證會話參與者的身份(交換SDP物件中的資訊:媒體型別、編解碼器、頻寬等元資料)
控制媒體會話、指示進度、更改會話、終止會話
雙佔用分解
簡單地說,信令就是協調通訊的過程,一旦信令服務建立好了,兩個客戶端之間建立了連線,理論上它們就可以進行點對點通訊了。
2、信令的傳輸
WebRTC要求在兩個對等端建立雙向的信令通道,通常有三種方式來傳輸WebRTC信令:http、websocket、資料通道
http方式如下:
image
websocket代理信令傳輸:
image
3、WebRTC中的伺服器
WebRTC提供了瀏覽器端的P2P通訊,但並不意味著WebRTC不需要伺服器。撇開應用伺服器不說,至少以下兩種伺服器是必須的:
瀏覽器之間建立通訊前交換各種元資料(信令)的伺服器(信令服務)
穿越NAT和防火牆的伺服器(stun、turn、rsip等)
說明:
元資料是通過信令伺服器中轉發給另一個客戶端,但是對於流媒體資料,一旦會話建立,首先嚐試使用點對點連線。簡單一點說就是:每個客戶端都有一個唯一的地址,他能用來和其他客戶端進行通訊和資料交換。
STUN伺服器:用來取外網地址的。(見下節)
TURN伺服器:在P2P失敗時進行轉發的。(見下節)
ICE:*Interactive Connectivity Establishment*,即互動式連通建立方式。並非一種新的協議,它通過綜合利用現有NAT穿透協議,以一種更有效的方式來組織會話建立過程,使之在不增加任何延遲同時比STUN等單一協議更具有健壯性、靈活性。
4、信令互動和RTCPeerConnection的建立
WebRTC使用RTCPeerConnection建立連線傳送流資料,在建立RTCPeerConnection例項之後,想要建立點對點的通道,需要做兩件事:
確定本機上的媒體流的特性,比如解析度、編解碼能力啥的(SDP描述符)
連線兩端的主機的網路地址(ICE Candidate)
通過offer和answer交換SDP描述符:
甲和乙各自建立一個PC例項
甲通過PC所提供的createOffer()方法建立一個包含甲的SDP描述符的offer信令
甲通過PC所提供的setLocalDescription()方法,將甲的SDP描述符交給甲的PC例項
甲將offer信令通過伺服器傳送給乙
乙將甲的offer信令中所包含的的SDP描述符提取出來,通過PC所提供的setRemoteDescription()方法交給乙的PC例項
乙通過PC所提供的createAnswer()方法建立一個包含乙的SDP描述符answer信令
乙通過PC所提供的setLocalDescription()方法,將乙的SDP描述符交給乙的PC例項
乙將answer信令通過伺服器傳送給甲
甲接收到乙的answer信令後,將其中乙的SDP描述符提取出來,呼叫setRemoteDescripttion()方法交給甲自己的PC例項
通過ICE框架建立NAT/防火牆穿越的連線:
WebRTC使用ICE框架來獲得這個外界可以直接訪問的地址,RTCPeerConnection在創立的時候可以將ICE伺服器的地址傳遞進去,如:
var iceServer = {
"iceServers": [{
"url": "stun:stun.l.google.com:19302"
}]
};
var pc = new RTCPeerConnection(iceServer);
甲、乙各建立配置了ICE伺服器的PC例項,併為其新增onicecandidate事件回撥
當網路候選可用時,將會呼叫onicecandidate函式
在回撥函式內部,甲或乙將網路候選的訊息封裝在ICE Candidate信令中,通過伺服器中轉,傳遞給對方
甲或乙接收到對方通過伺服器中轉所傳送過來ICE Candidate信令時,將其解析並獲得網路候選,將其通過PC例項的addIceCandidate()方法加入到PC例項中
這樣連線就創立完成了,可以向RTCPeerConnection中通過addStream()加入流來傳輸媒體流資料。
STUN和TURN介紹
瀏覽器位於網路地址轉換裝置(NAT)之後是一種極為普遍的設計。舉個栗子:
image
再來看個圖,瞭解下“公共地址”和“私有地址”:
image
NAT主要負責維護內部ip地址和埠號與外部ip地址和埠號之間的對映表。
1、STUN伺服器
STUN,Session Traversal Utilities for NAT,稱為NAT會話遍歷實用工具伺服器。簡單地說,就是獲取內網裝置的最外層NAT(公共ip地址)資訊。
image
2、TURN伺服器
TURN,Traversal Using Relay around NAT,稱為中繼型NAT遍歷伺服器。
image
說明:
媒體中繼地址是一個公共地址,用於轉發接收到的包,或者將收到的資料包轉發給瀏覽器。如果兩個對等端因為NAT型別等原因不能直接建立P2P連線的話,那麼可以使用中繼地址。
ps:相比較直接使用web伺服器提供媒體中繼理想點。
對等連線和提議/應答協商
上一節中有簡單介紹對等連線和offer/answer互動流程,這節再說明下。
其實WebRTC定義了兩組主要的功能,分別是:媒體捕獲(getUserMedia(),前面已介紹)、媒體傳輸。對等連線和提議/應答協商的概念是媒體傳輸的核心。
1、對等連線
RTCPeerConnection介面是WebRTC的主要API,用來在P2P端建立媒體連線及資料連線路徑。RTCPeerConnection物件的建構函式有一系列屬性,最主要的是iceServers屬性,表示伺服器地址列表。用於幫助透過NAT和防火牆建立會話。
var pc = new RTCPeerConnection({
iceServers: [{
url: 'stun:stun.l.google.com:19302'
},{
url: 'turn:[email protected]',
credential: 'test'
}]
})
getUserMedia({
audio: true,
video: true
}, successCB, failureCB)
function successCB(stream) {
// 告知瀏覽器,我要傳送MediaStream
pc.addStream(stream) // removeStream()
}
2、提議/應答協商
要在二者之間建立連線,必須在二者之間建立會話。offer/answer是一種“一次性通過”型協商機制。實際中該過程可能會反覆多次。
WebRTC使用RTCSessionDescription物件表示提議和應答。每個瀏覽器都將生成一個該物件。
3、JavaScript提議/應答協商控制
本地瀏覽器只關注兩個特定的呼叫:
// 將我的會話描述告知我的瀏覽器
pc.setLocalDescription(mySessionDescription)
...
// 將對等端的會話描述告知我的瀏覽器
pc.setRemoteDescription(yourSessionDescription)
生成提議、應答:
// 生成提議
pc.createOffer(gotOffer, didntGetOffer)
function gotOffer(aSessionDescription) {
setLocalDescription(aSessionDescription)
...
// 現在可以將會話描述(提議offer)傳送給對等端,以便對等端
// a)、將提議傳遞給setRemoteDescription
// b)、呼叫createAnswer
}
// 生成應答
pc.createAnswer(gotAnswer, didntGetAnswer)
function gotAnswer(aSessionDescription) {
setLocalDescription(aSessionDescription)
...
// 現在將會話描述(應答answer)傳送給對等端,以便對等端
// a)、將應答傳遞給setRemoteDescription
}
4、測試demo說明
以下測試demo展示在兩個瀏覽器中進行實時視訊通話,原始碼地址:https://github.com/caiya/webrtc-p2p.git
image
資料通道
RTCDataChannel,資料通道是瀏覽器之間建立的非媒體的互動連線。即不傳遞媒體訊息,繞過伺服器直接傳遞資料。相比WebSocket、http訊息,資料通道支援流量大、延遲低。
注意:
單個對等連線中的多個數據通道底層共享一個流,所以只需一次offer、answer即可建立首個數據通道。之後再建立資料通道無需再次進行offer、answer交換。
典型應用:遊戲實時狀態更新。
資料通道的使用
只有在建立完RTCPeerConnection例項之後才能建立資料通道,如下:
pc = new RTCPeerConnection()
dc = pc.createDataChannel('')
一端建立完資料通道後,另一端只需要監聽ondatachannel事件即可:
pc = new RTCPeerConnection()
pc.ondatachannel = function(e) {
dc = e.channel
}
此時,兩個對等端已經彼此建立資料通道,可以直接相互發送訊息:
dc.send('i am a text string for sending')
dc.send(new Blob(['i am a blob object'], {type: 'text/plain'}))
dc.send(new arrayBuffer(32)) // 傳送arrayBuffer
dc.onmessage = function(e) {
console.log('收到訊息:', e.data)
}
加入資料通道後的測試demo
專案原始碼地址:https://github.com/caiya/webrtc-p2p-datachannel
部分截圖:
image
作者 @晁州
2017 年 11月 27日
作者:西安-晁州
出處:https://vipzhou.cn
本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線。如有問題,可以郵件:[email protected] QQ:1419901425 聯絡我
轉載