上一篇介紹可能是整體的流程,可能表述的太簡單,不過實現的時候還是需要一步一步的來實現,技術點有兩部分 [M] = method [E] = event
- navigator.mediaDevices.getUserMedia
- RTCPeerConnection
- [M] addStream
- [M] setLocalDescription
- [M] setRemoteDescription
- [M] createOffer
- [M] createAnswer
- [E] icecandidate
- [M|E] addstream
首先html部分
<div id="main">
<div>
<video id="local" autoplay></video>
</div>
<div>
<video id="remote" autoplay></video>
</div>
</div>
js部分
async function initMedia() {
let stream = await navigator.mediaDevices.getUserMedia({
video: true
});
let video = document.querySelector('#local');
video.srcObject = stream;
}
以上的應該是比較基礎的也不難理解,如果有不明白的地方可以自行解決
RTCPeerConnection
重點來說說 這個
一開始需要實例化下,因爲本次就介紹兩個端,就需要初始化兩個簡寫本地 和遠程
var local = new RTCPeerConnection(null);
var remote = new RTCPeerConnection(null);
實例化完成後本地端需要添加 本地的stream, 同時偵聽時間 icecandidate
// 本地
local.addstream(stream) //通過getUserMedia獲取
local.addEventListener('icecandidate', handleLocalConnection, false);
function handleLocalConnection(e){
const iceCandidate = e.candidate;
if (iceCandidate) {
remote.addIceCandidate(new RTCIceCandidate(iceCandidate))
}
};
//遠端
remote.addEventListener('icecandidate', handleRemoteConnection, false)
remote.addEventListener('addstream', function(){
let video = document.querySelector('#remote')
video.srcObject = e.stream;
}, false);
function handleRemoteConnection(e){
const iceCandidate = e.candidate;
if (iceCandidate) {
local.addIceCandidate(new RTCIceCandidate(iceCandidate))
}
}
上面可能要注意 handleRemoteConnection , handleLocalConnection 這裏可以先思考下,因爲是無信令版本的, remote, local都能取到,如果真正兩個對端來調試需要怎麼配置信令服務器。
添加完成之後本地測開始呼叫 createOffer, 遠端並偵聽事件
let offer = await local.createOffer();
local.setLocalDescription(offer); //本地設置
remote.setRemoteDescription(offer); //遠端設置
設置好之後遠程端開始應答 createAnswer
let answer = await remote.createAnswer();
remote.setLocalDescription(answer); //遠端設置
local.setRemoteDescription(answer); //本地設置
寫到這裏基本上算完成了可以,
一下是整體代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>webrtc_base</title>
<style>
#main{ overflow: hidden;}
#main>div{
width: 100px; height: 100px;
margin: 10px;
border:1px solid #ccc;
float: left;
}
video{width: 100%; height: 100%; filter: grayscale(90%);}
</style>
</head>
<body>
<div id="main">
<div>
<video id="local" autoplay></video>
</div>
<div>
<video id="remote" autoplay></video>
</div>
</div>
<a href="javascript:;" onclick="initMedia()">開始</a>
<script>
var local = new RTCPeerConnection(null);
var remote = new RTCPeerConnection(null);
async function initMedia() {
let stream = await navigator.mediaDevices.getUserMedia({
video: true
});
let video = document.querySelector('#local');
video.srcObject = stream;
local.addEventListener('icecandidate', handleLocalConnection,false)
local.addStream(stream);
remote.addEventListener("addstream",function(e){
let video = document.querySelector('#remote')
video.srcObject = e.stream;
console.log('onaddstream', e);
}, false)
remote.addEventListener('icecandidate', handleRemoteConnection,false)
let offer = await local.createOffer({offerOptions: 1});
console.log('createOffer', offer);
local.setLocalDescription(offer);
remote.setRemoteDescription(offer);
let answer = await remote.createAnswer();
console.log('createAnswer', answer);
remote.setLocalDescription(answer);
local.setRemoteDescription(answer);
}
function handleLocalConnection(e){
const iceCandidate = e.candidate;
if (iceCandidate) {
remote.addIceCandidate(new RTCIceCandidate(iceCandidate))
}
}
function handleRemoteConnection(e){
const iceCandidate = e.candidate;
if (iceCandidate) {
local.addIceCandidate(new RTCIceCandidate(iceCandidate))
}
}
</script>
</body>
</html>
不要走開還有後續 ,增加信令版本