本DEMO中,發(fā)送端和接收端都在本地,暫時省略了信令服務器
和真正的遠端視頻傳輸實現(xiàn)邏輯是一樣的,只是缺少信令服務器,后續(xù)會加上,實現(xiàn)真正的端到端視頻傳輸
let localVideo = document.querySelector('video#localvideo')
let remoteVideo = document.querySelector('video#remotevideo')
let btnStart = document.querySelector('button#start')
let btnCall = document.querySelector('button#call')
let btnHangup = document.querySelector('button#hangup')
let localStream
let pc1
let pc2
btnStart.onclick = () => {
if(!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
console.log('the getUserMedia is not supported!')
return
}else {
let constraints = {
video: true,
audio: true
}
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
localVideo.srcObject = stream
localStream = stream
})
.catch((err) => {
console.log(`Failed to get Media Stream! - ${err}`)
})
}
}
btnCall.onclick = () => {
// 創(chuàng)建兩個連接 pc1 是調用者 pc2 是被調用者
pc2 = new RTCPeerConnection()
pc1 = new RTCPeerConnection()
// 收到候選者時觸發(fā)的事件, 收到事件后交給對方,讓對方插入自己的 candidate列表中
pc1.onicecandidate = (e) => {
pc2.addIceCandidate(e.candidate)
}
pc2.onicecandidate = (e) => {
pc1.addIceCandidate(e.candidate)
}
// 因為pc2是被調用者,當有數(shù)據(jù)時,它可以觸發(fā)ontrack事件
pc2.ontrack = (e) => {
// 從streams中取第一個值,賦值給remoteVide,這樣就可以顯示遠端的視頻
remoteVideo.srcObject = e.streams[0]
}
// 將本地采集的流添加到pc1中
localStream.getTracks().forEach(track => {
pc1.addTrack(track, localStream)
});
let offerOptions = {
offerToRecieveAudio: 1,
offerToRecieveVideo: 1
}
// 媒體協(xié)商
pc1.createOffer(offerOptions)
.then((desc) => {
// desc.sdp 打印出來是offer的sdp信息
// 將desc放到自己遠端的描述信息的槽
pc1.setLocalDescription(desc)
// send desc to signal 信令服務器
// receive desc from signal
pc2.setRemoteDescription(desc)
pc2.createAnswer()
.then((desc) => {
// desc.sdp 打印出來是answer的sdp信息
pc2.setLocalDescription(desc)
// send desc to signal
// receive desc from signal
pc1.setRemoteDescription(desc)
})
.catch((err) => {
console.log(`Failed to create answer! - ${err}`)
})
})
.catch((err) => {
console.log(`Failed to create offer! - ${err}`)
})
}
btnHangup.onclick = () => {
pc1.close()
pc2.close()
pc1 = null
pc2 = null
}
<html>
<head>
<title>PeerConnection</title>
</head>
<body>
<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>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> -->
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="./js/client.js"></script>
</body>
</html>
實現(xiàn)效果

點擊start,打開本地視頻(左側視頻)
點擊call,呼叫對端(右側視頻)
點擊hangup,掛斷對端(右側視頻)