媒体能力协商过程
RTCPeerConnection(核心类)
- 基本格式
pc = new RTCPeerConnection([configiration]);
RTCPeerConnection方法分类
- 媒体协商
- Stream/Track
- 传输相关方法
- 统计相关方法
媒体协商过程

协商状态变化

媒体协商方法
- createOffer
- createAnswer
- setLocalDescription
- setRemoeteDescription
createOffer
- 基本格式
aPromise = myPeerConnection.createOffer([options]);
createAnswer
- 基本格式
aPromise = myPeerConnection.createAnswer([options]);
setLocalDescription
- 基本格式
aPromise = myPc.setLocalDescription(sessionDescription);
setRemoeteDescription
- 基本格式
aPromise = myPc.setRemoeteDescription(sessionDescription);
Track方法
- addTrack
- removeTrack
addTrack
- 基本格式
rtpSender = myPc.addTrack(track, stream...); - 参数
track: 添加到RTCPeerConnection中的媒体轨
stream:指定track所在的stream
removeTrack
- 基本格式
myPc.removeTrack(rtpSender);
重要事件
- onnegotiationneeded
- onicecandidate
1:1连接的基本流程

实战:本机内的1:1音视频互通
index.html
html
<html>
<head>
<title>WebRTC PeerConnection</title>
</head>
<body>
<div>
<video id="localvideo" autoplay playsinline></video>
<video id="remotevideo" autoplay playsinline></video>
<div>
<button id="start">Start</button>
<button id="call">Call</button>
<button id="hangup">HangUp</button>
</div>
</div>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="js/main.js"></script>
</body>
</html>
main.js
js
'use strict'
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 localStream;
var pc1;
var pc2;
function gotMediaStream(stream){
localVideo.srcObject = stream;
localStream = stream;
}
function handleError(err){
console.log("Failed to call getUserMedia", err);
}
function start(){
var constraints = {
video: true,
audio: false
}
if(!navigator.mediaDevices ||
!navigator.mediaDevices.getUserMedia){
return;
}else {
navigator.mediaDevices.getUserMedia(constraints)
.then(gotMediaStream)
.catch(handleError);
}
}
function gotAnswerDescription(desc){
pc2.setLocalDescription(desc);
//send sdp to caller
//recieve sdp from callee
pc1.setRemoteDescription(desc);
}
function gotLocalDescription(desc){
pc1.setLocalDescription(desc);
//send sdp to callee
//receive sdp from caller
pc2.setRemoteDescription(desc);
pc2.createAnswer().then(gotAnswerDescription)
.catch(handleError);
}
function gotRemoteStream(e){
if(remoteVideo.srcObject !== e.streams[0]){
remoteVideo.srcObject = e.streams[0];
}
}
function call(){
var offerOptions = {
offerToReceiveAudio: 0,
offerToReceiveVideo: 1
}
pc1 = new RTCPeerConnection();
pc1.onicecandidate = (e) => {
// send candidate to peer
// receive candidate from peer
pc2.addIceCandidate(e.candidate)
.catch(handleError);
console.log('pc1 ICE candidate:', e.candidate);
}
pc1.iceconnectionstatechange = (e) => {
console.log(`pc1 ICE state: ${pc.iceConnectionState}`);
console.log('ICE state change event: ', e);
}
pc2 = new RTCPeerConnection();
pc2.onicecandidate = (e)=> {
// send candidate to peer
// receive candidate from peer
pc1.addIceCandidate(e.candidate)
.catch(handleError);
console.log('pc2 ICE candidate:', e.candidate);
}
pc2.iceconnectionstatechange = (e) => {
console.log(`pc2 ICE state: ${pc.iceConnectionState}`);
console.log('ICE state change event: ', e);
}
pc2.ontrack = gotRemoteStream;
//add Stream to caller
localStream.getTracks().forEach((track)=>{
pc1.addTrack(track, localStream);
});
pc1.createOffer(offerOptions)
.then(gotLocalDescription)
.catch(handleError);
}
function hangup(){
pc1.close();
pc2.close();
pc1 = null;
pc2 = null;
}
btnStart.onclick = start;
btnCall.onclick = call;
btnHangUp.onclick = hangup;