阅读本文章前需要先有conturn服务器和信令服务器,conturn服务器在网上可以找到好多,这里就不赘述了,详细参数说明在代码里有,上代码 源代码地址https://github.com/excuse-li/live
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WEBRTC</title>
<script src="js/adapter.min.js"></script>
<script src="js/jquery-3.4.1.min.js"></script>
<script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.css">
<script>
var ws;
var localStream;
//
var rtcPeerConnection = new RTCPeerConnection({
"iceServers": [{
"url": "stun服务器地址"
}, {
"url": "turn服务器地址",
"username": "服务器用户名",
"credential": "turn服务器域名",
"password" : "turn服务器密码"
}]
});
ws = new WebSocket('ws://localhost:8080/ws')
ws.onopen = function (ev) {
alert('服务器已连接')
// ws.send('{}')
}
ws.onmessage = function (ev) {
console.log(ev.data)
// 将传输过来的文字转换成对象
var parse = JSON.parse(ev.data);
// 当传来的信息为提示时直接弹出
if (parse.type === 'notice') {
alert(parse.value)
}
// 当传来的信息为offer时 进行本地设置
if (parse.type === 'offer') {
// 设置远程的连接信息
rtcPeerConnection.setRemoteDescription(parse.value)
// 创建answer
rtcPeerConnection.createAnswer().then(function (answer) {
// 设置本地的连接信息
rtcPeerConnection.setLocalDescription(answer)
// 将本地连接信息发送到其他客户端
ws.send('{"type": "answer","value":'+JSON.stringify(answer)+'}')
})
}
// 当传回的信息为answer时,进行本地设置
if (parse.type === 'answer') {
// 设置远程连接信息
rtcPeerConnection.setRemoteDescription(parse.value)
}
// 当传回的信息为候选者的时候, 把候选者添加到本地候选者里边
if( parse.type === 'candidate' ){
rtcPeerConnection.addIceCandidate(parse.value)
}
}
ws.onerror = function (ev) {
console.log(ev)
alert('服务器连接错误')
}
ws.onclose = function (ev) {
alert('服务器连接已断开')
}
// 当收到候选者的时候,把候选者发送到对端
rtcPeerConnection.onicecandidate = function (ev) {
// pc1.addIceCandidate(ev.candidate);
ws.send('{"type": "candidate","value":'+JSON.stringify(ev.candidate)+'}')
}
// 当收到远程的音视频轨的时候把视频类放入本地存放远程端视频的窗口
rtcPeerConnection .ontrack = function (e) {
$('#remote')[0].srcObject = e.streams[0]
}
$(document).ready(function () {
if (!navigator || !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
alert('浏览器不支持多媒体信息');
return;
} else {
var config ={
video: true,
audio: {
echoCancellation: false, // 回音消除
noiseSuppression: true // 降噪
}
};
// 获取本地音视频流
navigator.mediaDevices.getUserMedia(config)
.then(function (stream){
// 把本地视频流声明为全局
localStream = stream;
//
// local.srcObject = steam;
// 把本地媒体流放入本地视频的窗口
$('#local')[0].srcObject = stream
// 遍历本地的媒体流
localStream.getTracks().forEach(function (value) {
// 把本地的媒体流传入到远程流
rtcPeerConnection.addTrack(value, localStream)
})
}).catch(function (e) {
alert('错误:' + e );
})
// 连接事件
$('#call').click(function () {
// 创建offer
rtcPeerConnection.createOffer({
offerToRecieveAudio: 0, // 是否接收音频
offerToRecieveVideo: 1 // 是否接收视频
}).then(function (offer) {
// 设置本地连接信息
rtcPeerConnection.setLocalDescription(offer)
// 将offer 发送到对端
ws.send('{"type": "offer","value":'+JSON.stringify(offer)+'}')
}).catch(function (e) {
console.error(e)
})
})
}
})
</script>
</head>
<body>
<div class="row col-xs-8 col-xs-offset-2">
<div class="col-xs-5" >
<blockquote>本地视频</blockquote>
<video id="local" style="width: 100%;transform: rotateY(180deg)" autoplay playsinline></video>
</div>
<div class="col-xs-5 col-xs-offset-2" >
<blockquote>远程视频</blockquote>
<video id="remote" style="width: 100%;transform: rotateY(180deg)" autoplay playsinline></video>
</div>
</div>
<div class="row col-xs-8 col-xs-offset-2" style="text-align: center">
<button id="call" class="btn btn-success">呼叫</button>
<button id="ceancal" class="btn btn btn-danger">断开</button>
</div>
</body>
</html>