webRTC是Google在2010年收購GIP公司以後得到的一項技術。以下圖所示,它提供了音視頻的採集、處理(降噪,回聲消除等)、編解碼、傳輸等技術。html
webRTC的目標是實現無需安裝任何插件就能夠經過瀏覽器進行P2P的實時音視頻通話及文件傳輸,來看看Google的demo,是否是很酷?本文將帶你分析webRTC的原理,並逐步編寫一個簡單的demo。前端
固然,鏈接創建的過程不會這麼簡單。首先,提到P2P就繞不開NAT(Network Address Translation),webRTC使用ICE(Interactive Connectivity Establishment)框架,ICE是一種綜合性的NAT穿越技術,它整合了STUN、TURN。當穿越網絡時,ICE會先嚐試STUN,查出本身位於哪一種類型的NAT以後以及NAT爲某一個本地端口所綁定的Internet端端口從而創建UDP鏈接,若是失敗了ICE就會再嘗試TCP(先嚐試HTTP,再嘗試HTTPS),若是仍然失敗就使用中繼的TURN服務器。 html5
再來看看創建鏈接過程當中的具體步驟:ios
var constraints = {
audio: false,
video: true
};
navigator.mediaDevices.getUserMedia(constraints)
.then(gotStream)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
function gotStream(stream) {
localVideo.srcObeject = stream;
localStream = stream;
}
複製代碼
getUserMedia存在兼容性問題,須要在項目中引用webRTC官方給出的adapter.js。constraints還能夠配置video的分辨率、幀率、對移動端還能夠選擇先後攝像頭: var constraints = { video: { width: { min:640, ideal: 1280, max: 1920 }, height: { min: 480 ideal: 720, max: 1080 }, facingMode: 'user' // 前置攝像頭 } };git
var serverConfig = {
'iceServers': [{
'urls': 'stun:stun.l.google.com:19302'
}]
};
function createPeerConnection() {
var pc = new RTCPeerConnection(serverConfig);
pc.onicecandidate = function(e) {
if (e.candidate) {
pc.addIceCandidate(e.candidate);
}
};
// 添加對方的媒體流
pc.onaddstream = function(e) {
remoteVideo.srcObeject = e.stream;
remoteStream = stream;
};
}
複製代碼
由STUN、TURN配置生成對應的RTCPeerConnection實例,再定義相關的事件處理函數,如onicecandidate、onaddstream、onremovestream等。github
function start() {
pc.addstream(localStream);
if (isCaller) {
pc.createOffer(function(sessionDescription) {
pc.setLocalDescription(sessionDescription);
send(sessionDescription); // 根據不一樣的Signaling方式實現
});
if (receiveAnswer) {
pc.setRemoteDescription(answer.sessionDescription);
}
} else {
if (receiveOffer) {
pc.setRemoteDescription(offer.sessionDescription);
}
pc.createAnswer(function(sessionDescription) {
pc.setLocalDescription(sessionDescription);
send(sessionDescription);
});
}
}
複製代碼
必須先getUserMedia後才能生成sessionDescription,而且只有在setLocalDescription後onicecandidate事件纔會觸發。上面代碼中的只是爲了說明大體流程,實際項目中結合socket.io的事件更容易實現。web
function stop() {
pc.stop();
pc = null;
}
複製代碼
關於socket.io有關的代碼本文沒有貼出,詳情可參考socket.io的用法。segmentfault
按照上面的步驟能夠成功地搭建webRTC的小demo,可是可否將webRTC運用到實際項目中去呢?下面從瀏覽器兼容性和webRTC自己的性能兩個方面去分析。promise
IOS: 只有最新的ios11支持webRTC,且僅限safari瀏覽器,微信內置瀏覽器尚不支持getUserMedia,不支持DataChannel,視頻編解碼格式爲H.264;瀏覽器
Android: 安卓4.4以上(不含4.4),經測試各大手機廠商自帶瀏覽器均不支持getUserMedia,但微信內置瀏覽器能夠正常運行,另外61版本以上的Chrome for Android也都支持;
PC: Chrome49以上,Firefox55以上,Edge支持,Safari只有11支持,IE不支持。
誠然webRTC在回聲消除,圖像編解碼等方面已經作得十分出色,但它在性能上的問題仍是不可忽視的:
綜上所述,雖然webRTC具備不需安裝插件或者客戶端,開源免費,強大的網絡穿透能力,出色的音視頻處理技術等等優勢,但因爲兼容性及性能上的問題,要投入到生產中還須要時間,主要是IOS11的普及以及CPU佔用率和延時的問題。