webRTC脫坑筆記(三)— webRTC API之RTCPeerConnection

RTCPeerConnection API是每個瀏覽器之間點對點連接的核心,RTCPeerConnectionWebRTC組件,用於處理對等體之間流數據的穩定和有效通信。

RTCPeerConnection可以保護Web開發人員免受潛伏在其中的無數複雜性的影響。WebRTC使用的編解碼器和協議可以進行大量工作,即使在不可靠的網絡上也可以進行實時通信:

  • 丟包隱藏
  • 回聲消除
  • 帶寬適應性
  • 動態抖動緩衝
  • 自動增益控制
  • 降噪和抑制
  • 圖像’清潔’。
// 創建實例
let pc = RTCPeerConnection(serverConfig);

根據你是發起者還是被髮起對象,在連接的每一邊會使用稍微不同的方式使用RtcPeerConnection對象。

serverConfigconfig配置參數中包含iceServers參數。它是包含有關STUNTURN服務器的信息的URL對象數組,在查找ICE候選時使用。可以在code.google.com找到可用的公共STUN服務器的列表。

現實中,無論你的應用如何見到那,webRTC都需要服務器,因爲:

  • 通信用戶發現彼此並交換自己的“真實世界”的詳細信息;
  • webRTC客戶端(對等方)交換網絡信息;
  • peers交換有關每天的數據,如視頻格式和分辨率
  • webRTC客戶端遍歷NAT網關和防火牆

換句話說,WebRTC需要四種類型的服務器端功能:

  • 發現用戶並溝通。
  • 使用STUN服務器連接用戶信號。
  • 使用NAT /防火牆遍歷。
  • 在對等通信失敗的情況下,使用中繼服務器。

ICE是用於連接對等體的框架,例如兩個視頻聊天客戶端。最初,ICE嘗試通過UDP直接連接對等端,以儘可能低的延遲。在此過程中,STUN服務器只有一個任務:使NAT後面的對等體能夠找到其公共地址和端口。

下面是調用流程

1.獲取本地媒體設備成功之後,創建一個新的RTCPeerConnection對象,初始化將本地音視頻軌道加入到RTCPeerConnection

 function createConn(stream) {
     localStream = stream
     // 顯示本地視頻流
    localVideo.srcObject = stream;
     //谷歌公共stun服務器
	let serverConfig = {
        "iceServers": [
            { "urls": ["turn:192.168.1.133:3478"], 
            "username": "webrtc", 
            "credential": "webrtc" 
            }
        ]
    };
     // 呼叫者
	let localPeer = new RTCPeerConnection(serverConfig)
    // 被呼叫者
    let remotePeer = new RTCPeerConnection(serverConfig)
    // 設置媒體流監聽,將本地流添加到RTCPeerConnection對象
    localStream.getTracks().forEach((track) => {
      localPeer.addTrack(track, localStream);
    });
	localPeer.addStream(stream)
	
 }

2.註冊onicecandidate處理程序,並監聽獲取自己的ICE協商信息,它將任何ICE候選發送給其他對等方

function createConn(stream) {
    ...
    // 當獲得到自己的公網地址後,發送給其它客戶端
    localPeer.onicecandidate = function(event) {
    console.log('I got my icecandidate info')
    if (event.candidate) {
        console.log(event.candidate.candidate)
    }
    	socket.emit('onicecandidate', event.candidate);
	}
    // 如果監測到本地媒體流連接到本地,將其綁定到一個video標籤上輸出
     localPeer.ontrack = function(e) {
         // 因爲媒體流是一個數組
        if (remoteVideo.srcObject !== e.streams[0]) {
        remoteVideo.srcObject = e.streams[0];
        console.log('received remote stream');
    }
    };
}

3.提前註冊消息處理程序。信令服務器還應該有一個處理來自遠程計算機的消息處理程序。如果消息包含RTCSessionDescription對象,則應該使用RTCSessionDescription()方法將其添加到RTCPeerConnection對象。如果消息包含RTCIceCandidate對象,則應該使用addIceCandidate()方法將其添加到RTCPeerConnection對象。

消息處理程序會根據誰是呼叫方和被呼叫方被調用。

//呼叫方收到對方回覆的SDP時調用的消息處理程序
    localPeer.setRemoteDescription(new RTCSessionDescription(answer));


//被呼叫方收到對方發送的SOP時調用的消息處理程序
    localPeer.addIceCandidate(new RTCIceCandidate(candidate));

4.撥通對方,發送自己的SDP信息,開始提供/回答協商過程,這是呼叫者的流量不同於被呼叫者的唯一步驟。呼叫者使用createoffer( )方法開始協商,並註冊一個收到RTCSessiondescription對象的回調。然後這個回調應該使用setlocaldescription( )將這個rtcsessiondescription對象添加到rtcpeerconnection對象中。最後,調用者應該使用信令服務器將這個rtcsessiondescription發送到遠程計算機。另一方面,被呼叫者,在createanswer()方法中註冊相同的回調。請注意,只有在從調用者收到通知後,纔會啓動流。

//當本地開始撥打對方的時候,發送自己的SDP信息
const offerOptions = {
    offerToReceiveAudio: 1,
    offerToReceiveVideo: 1
};
function call() {
    console.log('Starting call');

    try {
        console.log('localPeerConnection createOffer start');
        const offer = await pc1.createOffer(offerOptions);
        console.log(offer);
        localPeer.setLocalDescription(offer)
        socket.emit('offer', offer);
    } catch (e) {
        console.log(`Failed to create session description: ${e.toString()}`);
    }
}

// 當本地收到對方的撥號通知時 收到對方的SDP信息,然後生成回覆SDP信息
function handleOffer(offer, name) {
    connectedUser = name;
    console.log("I got offer: ");
    localPeer.setRemoteDescription(new RTCSessionDescription(offer));
    //create an answer to an offer 
    localPeer.createAnswer(function(answer) {
        localPeer.setLocalDescription(answer);
         console.log("I will reply a answer")
        send({
            type: "answer",
            answer: answer
        });
    }, function(error) {
        alert("Error when creating an answer");
    });
};
// 當撥號方收到對方回覆的SDP後,設置到連接中,調用消息處理程序
socket.on('answer', (desc) => {
    console.log("I got answer: ", desc.sdp);
    localPeerConnection.setRemoteDescription(desc);
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章