webrtc實現視訊群聊系列文章(一)之基礎入門
前言
1.本文首先會介紹webrtc中的一些基本概念,並通過示例程式碼一步步完成一個簡單的本地視訊模擬通話,不通過網路轉接。
2.示例程式碼及其重要,是完整實踐配合基礎概念的分部介紹。
3.每一段話請注意仔細理解,我會盡可能簡單的介紹基礎概念。
4.請確保你的電腦是有攝像頭的,桌上型電腦沒有攝像頭外接一個就可以
媒體裝置
在開發Web時,WebRTC標準提供了API,用於訪問連線到計算機或智慧手機的相機和麥克風。這些裝置通常稱為媒體裝置,可以通過實現MediaDevices
介面的navigator.mediaDevices
物件使用JavaScript進行訪問。通過該物件,我們可以列舉所有已連線的裝置,偵聽裝置更改(連線或斷開裝置時),並開啟裝置以檢索媒體流
呼叫getUserMedia()
將觸發許可權請求。如果使用者接受許可,則通過包含一個視訊和一個音軌的MediaStream
來解決承諾。如果許可權被拒絕,則丟擲PermissionDeniedError
。如果沒有連線匹配的裝置,則會丟擲NotFoundError
。
- 獲取媒體流示例程式碼
// createMedia async createMedia() { let streamTep = null; // 儲存本地流到全域性 streamTep = await navigator.mediaDevices.getUserMedia({audio: true, video: true}) console.log("streamTep",streamTep) return streamTep; },
著重點:navigator.mediaDevices.getUserMedia()
函式
- 本地播放媒體流
<div style="float: left">
<video id="sucA"></video>
</div>
// 本地攝像頭開啟 async nativeMedia(){ const that = this; that.localStream = await this.createMedia() let video = document.querySelector('#sucA'); // 舊的瀏覽器可能沒有srcObject if ("srcObject" in video) { video.srcObject = that.localStream; } else { video.src = window.URL.createObjectURL(that.localStream); } // eslint-disable-next-line no-unused-vars video.onloadedmetadata = function(e) { video.play(); }; that.initPeer(); // 獲取到媒體流後,呼叫函式初始化 RTCPeerConnection },
著重點:播放本地媒體流實質就是將上一步拿到的媒體流賦值
到對應的媒體標籤元件,在這裡就是給video
標籤
- 媒體裝置約束條件
//比如設定視訊視窗的範圍
{
"video": {
"width": {
"min": 640,
"max": 1024
},
"height": {
"min": 480,
"max": 768
}
}
}
//獲取手機端前置攝像頭
{ audio: true, video: { facingMode: "user" } }
//後置攝像頭
{ audio: true, video: { facingMode: { exact: "environment" } } }
//具有頻寬限制的WebRTC傳輸,可能需要較低的幀速率
{ video: { frameRate: { ideal: 10, max: 15 } } }
著重點:通俗的講就是對音訊或者視訊進行約束,約束條件引數入口就是上面示例中的獲取媒體流的函式 getUserMedia({audio: true, video: true})
名詞:ICE,STUN,NAT,TURN,SDP解釋
互動式連線建立(ICE)是允許您的Web瀏覽器與對等方連線的框架。A到B兩個客戶端能夠點對點通訊的基礎就是建立通訊,但是很多情況下兩個裝置之間並沒有公網IP,而且還有防火牆這些阻斷資料傳輸,這個時候就需要STUN來為你提供一個獨一無二的地址和TURN伺服器中繼資料。
更詳細的介紹請看 MDN,具體不再介紹
RTCPeerConnection
該RTCPeerConnection介面表示本地計算機和遠端對等方之間的WebRTC連線。它提供了連線到遠端對等方,維護和監視連線以及在不再需要連線時關閉連線的方法。
RTCPeerConnection之間如何建立
- 本地流獲取(上述已解釋)
- 全域性引數初始化
--------------------全域性初始化PeerConnection--------------------------
var PeerConnection = window.RTCPeerConnection ||
window.mozRTCPeerConnection ||
window.webkitRTCPeerConnection;
-----------------------iceServers stun和turn伺服器配置-------------------------------------------
var iceServers = {
iceServers: [
{ url: "stun:stun.l.google.com:19302"},// 谷歌的公共服務
{
url: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: '[email protected]'
}
]
};
- 初始化兩個模擬客戶端
//以下pc和pc2 分別代表兩個模擬客戶端的連結服務簡寫 ( pc: 代表pc->pc2連結 pc2:代表pc2->pc連結 )
const that = this;
that.pc = new PeerConnection(iceServers);
that.pc2 = new PeerConnection(iceServers);
//將全域性視訊流賦給pc連結服務
that.pc.addStream(this.localStream);
//監聽ice候選資訊 具體下面會說明
that.pc.onicecandidate = function(event) {
console.log("pc onicecandidate",event)
if (event.candidate) {
//一般來說這個地方是通過第三方(socket後面會將網路端點對點)傳送給另一個客戶端,但是現在本地演示直接將候選資訊傳送到pc2連結服務
that.pc2.addIceCandidate(event.candidate.toJSON());
}
};
//監聽遠端視訊 pc充當呼叫端,所以只要監聽pc2有無視訊流資訊進來
that.pc2.onaddstream = (event) => {
console.log("onaddstream",event)
//監聽到流後將視訊流賦給另一個video標籤
let video = document.querySelector('#sucB');
video.srcObject = event.stream;
video.onloadedmetadata = function(e) {
console.log(e)
video.play();
};
};
onicecandidate
: 候選ICE描述了WebRTC能夠與遠端裝置進行通訊所需的協議和路由。在啟動WebRTC對等連線時,通常在連線的每一端都建議多個候選物件,直到他們相互同意描述他們認為最好的連線的候選物件為止。
- 呼叫端模擬呼叫(pc充當呼叫端)
//建立offer
async createOffer() {
const that = this;
//建立offer
let offer_tep = await that.pc.createOffer(this.offerOption);
console.log("offer_tep",offer_tep)
//設定本地描述
await that.pc.setLocalDescription(offer_tep)
//接收端設定遠端 offer 描述
await that.pc2.setRemoteDescription(offer_tep)
// 接收端建立 answer
let answer = await that.pc2.createAnswer();
// 接收端設定本地 answer 描述
await that.pc2.setLocalDescription(answer);
// 傳送端 設定遠端 answer 描述
await that.pc.setRemoteDescription(answer);
},
//呼叫
async callA() {
const that = this;
//建立offer 並儲存本地描述
await that.createOffer()
},
為何呼叫會有這麼麻煩的步驟呢?這就又涉及到webrtc的會話
了,具體看下面一條
webrtc會話
“當用戶(上述pc)向另一個使用者(上述pc2)發起WebRTC呼叫時,會建立一個特殊的描述,稱為offer。此描述包括有關呼叫者為呼叫建議的配置的所有資訊。然後,接收者用一個答案來回應,這是他們通話結束的描述。以此方式,兩個裝置彼此共享為了交換媒體資料所需的資訊。這種交換是使用互動式連線建立(ICE)處理的,該協議允許兩個裝置使用中介程式交換要約和答覆,即使兩個裝置之間都被網路地址轉換(NAT)隔開。然後,每個對等方都保留兩個描述:本地描述(描述自己)和遠端描述(描述呼叫的另一端)”
上面的話簡單來說就是 A呼叫B,A建立offer,在本地保留offer,然後傳送給B,B建立應答,之後本地保留應答,再將應該傳送給A,A拿到後將B的應該設定為本地的遠端描述。
- 圖示
後續
- 本文是webrtc實現群聊系列文章的第一篇,持續更新中
- 關注我的公眾號及時獲取最新文章更新