WebRTC(十二) Web端媒體協商


本文以同一個瀏覽器的RTCPeerConnection爲例,來說明媒體協商的過程。多個瀏覽器的流程也是一樣的,只不過媒體協商的信息以消息的形式發送到對端,而且還要包括p2p連接的建立等。

1 媒體協商流程

1 首先發起端要創建一個offer,並調用setLocalDescription設置本地的SDP
2 然後通過信令服務器將含有SDP的offer設置給對端
3 對端拿到此offer以後調用setRemoteDescription將此SDP信息保存
4 對端創建一個answer,並調用setLocalDescription設置本地的SDP
5 通過信令服務器將含有SDP的answer發送給發起端
6 發起端調用setRemoteDescription將此SDP信息保存
在這裏插入圖片描述
在這裏插入圖片描述

2 代碼示例

效果演示
在這裏插入圖片描述
首先初始化控件,定義成員變量,給控件添加點擊事件

var localVideo = document.querySelector('video#localvideo');
var remoteVideo = document.querySelector('video#remotevideo');

var btnStart = document.querySelector('button#start');
var btnCall = document.querySelector('button#call');
var btnHangup = document.querySelector('button#hangup');

var offerSdpTextarea = document.querySelector('textarea#offer');
var answerSdpTextarea = document.querySelector('textarea#answer');

var localStream;
var pc1;
var pc2;

btnStart.onclick = start;
btnCall.onclick = call;
btnHangup.onclick = hangup;

點擊start按鈕開始獲取視頻流並顯示

function start(){
	if(!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia){
		console.error('the getUserMedia is not supported!');
		return;
	}else {
		var constraints = {
			video:true,
			audio:false
		}

		navigator.mediaDevices.getUserMedia(constraints)
		.then(getMediaStream)
		.catch(handleError);

		btnStart.disabled = true;
		btnCall.disabled = false;
		btnHangup.disabled = true;
	}
}

獲取到視頻流則賦值給顯示控件,獲取失敗則打印日誌

function getMediaStream(stream){
	localVideo.srcObject = stream;
	localStream = stream;
}

function handleError(err){
	console.error('Failed to get Media Stream!', err);
}

點擊call按鈕,執行call方法。

function call(){
	//1 首先創建本地和對端的RTCPeerConnection對象pc1和pc2,
	pc1 = new RTCPeerConnection();
	pc2 = new RTCPeerConnection();
	
	//2 然後給pc1和pc2添加接收ice的回調監聽,當收到對端的ice後添加到各自的ice中
	pc1.onicecandidate = (e) =>{
		pc2.addIceCandidate(e.candidate);
	}

	pc2.onicecandidate = (e) =>{
		pc1.addIceCandidate(e.candidate);
	}
	
	//3 p2接收到視頻流以後顯示視頻
	pc2.ontrack = getRemoteStream;

	//4 本地流遍歷所有軌track,並添加到pc1的track中。
	localStream.getTracks().forEach((track)=>{
		pc1.addTrack(track, localStream);
	});

	//5 配置offer選項 
	var offerOptions = {
		offerToRecieveAudio:0,
		offerToRecieveVideo:1
	}

	//6 本地創建offer 並設置offer創建成功的回調
	pc1.createOffer(offerOptions)
		.then(createOfferSuc)
		.catch(handleOfferError);

	btnCall.disabled = true;
	btnHangup.disabled = false;
}

遠端接收到視頻流以後播放視頻

function getRemoteStream(e){
	remoteVideo.srcObject = e.streams[0];
}

pc1 offer創建成功的回調

function createOfferSuc(desc){
	//1 首先調用pc1的setLocalDescription
	pc1.setLocalDescription(desc);
	offerSdpTextarea.value = desc.sdp;
	
	//2 調用pc2的setRemoteDescription 
	pc2.setRemoteDescription(desc);
	
	//3 遠端創建answer, 並設置answer創建成功的回調
	pc2.createAnswer()
		.then(createAnswerSuc)
		.catch(handleAnswerError);
}

pc2 answer創建成功的回調

function createAnswerSuc(desc){
	//1 首先調用pc2的setLocalDescription
	pc2.setLocalDescription(desc);
	answerSdpTextarea.value = desc.sdp;

	//2 調用
	pc1.setRemoteDescription(desc);
}

此時pc1和pc2都已經調用了setLocalDescription和setRemoteDescription。完成了媒體協商的過程。本地和遠端的視頻都能正常顯示。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章