A,B,C三人群聊,首先各自都要创建一个不包含本身的peers例如A:peers=[{name:“b”,peer:null,id:***},{name:“c”,peer:null,id:***}],B:peers=[{name:“a”,peer:null,id:***},{name:“c”,peer:null,id:***}],当建立连接时就是A的b对象和B的a对象之间发送offer,ice并建立连接,每个连接都是在一个单独的对象进行操作的
setLocalDescription()会触发 onicecandidate 事件
setRemoteDescription() 会触发 addStream 事件
根据群聊人数向peers添加房间内会存在的所有用户
that.peers.push({id:v.id,perr:null,name:v.name,img:v.img})
给每个peer创建 new RTCPeerConnection(),根据已进入房间人数给每个人发送一个单独的offer
ws.onmessage = (data) => {
const message = JSON.parse(data.data)
if (message.type == "searchRooom") {
//给已进入房间所有人发送一个单独的offer
that.room = message.room.users
//判断peers的用户是否已进入房间
that.peers.forEach((v)=>{
for (let j of that.room ){
if(j.id==v.id){
const iceServer = {
"iceServers": [
{
"urls": "stun:stun.l.google.com:19302"
}
],
};
v.peer = new RTCPeerConnection(iceServer);
v.peer.onicecandidate = (evt) => {
//发送ice
ws.send(JSON.stringify({
type: 1,
candidate: evt.candidate,
chatType: "video",
roomID: that.isAnswerVideo.roomID,
}))
}
v.peer.onaddstream = (evt) => {
console.log("offer添加视屏")
document.getElementById("localVideo").srcObject = evt.stream
}
navigator.mediaDevices.getUserMedia({"audio": true, "video": true}).then(stram => {
v.peer.addStream(stram)
that.localStream = stram
localVideo.srcObject = stram
//创建并发送offer
v.peer.createOffer({
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
}).then(offer => {
v.peer.setLocalDescription(offer, () => {
ws.send(JSON.stringify({
type: 1,
sdp: v.peer.localDescription,
chatType: "video",
id: that.userData.id,
roomID: that.isAnswerVideo.roomID,
}))
})
})
})
}else
{
// peers的用户未进入房间创建peer,等待后进入房间的人给你发送offer
const iceServer = {
"iceServers": [
{
"urls": "stun:stun.l.google.com:19302"
}
],
};
v.peer = new RTCPeerConnection(iceServer);
v.peer.onicecandidate = (evt) => {
ws.send(JSON.stringify({
type: 1,
candidate: evt.candidate,
chatType: "video",
roomID: that.isAnswerVideo.roomID,
name: that.userData.name,
id: that.userData.id,
}))
}
v.peer.onaddstream = (evt) =>{
// 你的逻辑
}
navigator.mediaDevices.getUserMedia({"audio": true, "video": true}).then(stram => {
v.peer.addStream(stram)
})
}
}
})
}
收到 ice
if (message.candidate && message.candidate !== null) {
//遍历peers给对应的peer添加ice
that.peers.forEach(v=>{
if(v.id==message.id){
v.peer.addIceCandidate(new RTCIceCandidate(message.candidate))
}
})
}
收到 offer
//收到offer遍历peers给对应的peer发送answer
if (message.webtype == "video-offer") {
// 创建
this.videoSession(message)
}
videoSession(message) {
const that = this
const ws = that.$store.getters.wsChat
that.peers.forEach(v=>{
if(v.id==message.id){
v.peer.setRemoteDescription(new RTCSessionDescription(message.sdp), () => {
v.peer.createAnswer().then((desc) => {
v.peer.setLocalDescription(desc, () => {
ws.send(JSON.stringify({
name: that.userData.name,
type: 1,
sdp: v.peer.localDescription,
chatType: "video",
webtype: "video-answer",
id: that.userData.id,
offerID: message.id,
offerName: message.name,
roomID: message.roomID
}))
});
})
})
}
})
},
收到 answer
//收到answer遍历peers给对应的peer添加远端描述
if (message.webtype = "video-answer") {
that.peers.forEach(v=>{
if(v.id==message.id){
v.peer.setRemoteDescription(new RTCSessionDescription(message.sdp))
}
})
}