上一篇介绍可能是整体的流程,可能表述的太简单,不过实现的时候还是需要一步一步的来实现,技术点有两部分 [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>
不要走开还有后续 ,增加信令版本
文章来源: webRTC【二】单机实现方案无信令版本