因此,这是我第一次在WebRTC工作,我正在尝试将this教程纳入我的网站。此后,仅根据我希望它的工作方式进行了一些更改。我将“通话”按钮更改为“就绪”按钮,在该按钮中,两个连接的用户都必须按下“准备就绪”,然后才能建立通话。另外,我目前正在使用React和Firestore,所以我认为我将使用firestore作为我的信令服务器,并且我做了一些更改以尝试使其在React组件中起作用。
无论出于何种原因,除非第二个人按下“就绪”,否则视频通话不会为我建立。这是有问题的代码:
readMessage = (data) => {
console.log("Reading message..")
console.log("readMessage | yourId: " + this.yourId);
var msg = JSON.parse(data.message);
console.log("readMessage | msg: ");
console.log(msg);
console.log("readMessage | sender: " + data.sender)
var sender = data.sender;
console.log("Comparing senderId and yourId")
console.log(sender + " | " + this.yourId)
if (sender != this.yourId) {
console.log("senderId is not equal to currentUserId")
console.log(this.pc)
if (msg.ice != undefined){
console.log("Adding ice candidate...")
console.log("msg.ice: ");
console.log(msg.ice);
this.pc.addIceCandidate(new RTCIceCandidate(msg.ice));
}
else if (msg.sdp.type == "offer"){
console.log("Msg type is offer");
console.log("Setting pc's remote description")
this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
.then(() => {
console.log("Creating answer on pc")
return this.pc.createAnswer()
})
.then(answer => {
console.log("Answer created. Setting pc's local description to answer.")
console.log("Answer: ")
console.log(answer)
this.pc.setLocalDescription(answer);
})
.then(() => {
console.log("Sending answer message to server.")
this.sendMessage(JSON.stringify({'sdp': this.pc.localDescription}))
})
.catch(err => console.log(err))
}
else if (msg.sdp.type == "answer"){
console.log("Msg type is answer");
console.log("Setting pc's remote description to the answer from the server.");
this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
}
} else {
console.log("IDs are similar. Data was sent by this client.")
}
}
showMyFace = () => {
navigator.mediaDevices.getUserMedia({audio:true, video:true})
.then((stream) => {
console.log("Adding current user's webcam stream to yourVideo")
console.log(stream)
this.yourVideo.srcObject = stream;
{/* for (const track of stream.getTracks()) {
pc.addTrack(track);
} */}
this.pc.addStream(stream);
}).catch(function(err) {
console.log(err);
});
}
establishCall = () => {
this.pc.createOffer()
.then(offer => this.pc.setLocalDescription(offer) )
.then(() => this.sendMessage(JSON.stringify({'sdp': this.pc.localDescription})) )
.catch(err => {
console.log(err)
});
}
componentDidMount(){
console.log("Component mounted.")
this.showMyFace();
this.pc.onicecandidate = (event => event.candidate?this.sendMessage(JSON.stringify({'ice': event.candidate})): console.log("Sent All Ice"));
this.pc.ontrack = (event => {
console.log("onAddStream called. Adding stream object to friendsVideo.")
console.log(event.streams[0])
console.log(this.friendsVideo)
this.friendsVideo.srcObject = event.streams[0]
if (this.friendsVideo.srcObject != null){
console.log("Stream connected.")
}
console.log("Logging state of friendsVideo.srcObject:")
console.log(this.friendsVideo.srcObject)
});
this.countPlayersAndAssignNumber();
}
当两个用户都首次按下“就绪”时,最后一个人会创建一个要击中“就绪”的要约,然后发送他们的候选冰。被叫方收到要约并发送答案,它就是ICE候选人。但是,原始呼叫者没有收到答复,而且我似乎无法弄清楚原因。但是,只要报价创建者再次按下“就绪”按钮,就会再次发送报价和答案,这一次似乎没有发送ICE候选人,但是电话建立了。
从构造函数调用的Firestore监听器
this.firestore.collection("games").doc(this.gameId).collection('connection').doc('data')
.onSnapshot((doc) => {
if(doc.exists){
console.log(doc)
console.log("Current data: ", doc.data());
this.readMessage(doc.data())
}
}, error => {
console.log("Firestore listener on game connection data has failed. Error log: ")
console.log(error)
});
另外请注意,这是我在Stackoverflow上的第一篇文章。我仍在学习Javascript,React,尤其是WebRTC。欢迎提供有关编码甚至我如何格式化问题的任何建议。预先感谢您抽出宝贵时间在这里帮助我的人。
我尝试通过在调用setRemoteDescription之前不调用getUserMedia来实现here中的逻辑。
readMessage函数:
readMessage = (data) => {
console.log("Reading message..")
console.log("readMessage | yourId: " + this.yourId);
var msg = JSON.parse(data.message);
console.log("readMessage | msg: ");
console.log(msg);
console.log("readMessage | sender: " + data.sender)
var sender = data.sender;
console.log("Comparing senderId and yourId")
console.log(sender + " | " + this.yourId)
if (sender != this.yourId) {
console.log("senderId is not equal to currentUserId")
console.log(this.pc)
if (msg.ice != undefined){
console.log("Adding ice candidate...")
console.log("msg.ice: ");
console.log(msg.ice);
this.pc.addIceCandidate(new RTCIceCandidate(msg.ice));
}
else if (msg.sdp.type == "offer"){
console.log("Msg type is offer");
console.log("Setting pc's remote description")
this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
.then(() => {
console.log("Creating answer on pc")
return this.pc.createAnswer()
})
.then(answer => {
console.log("Answer created. Setting pc's local description to answer.")
console.log("Answer: ")
console.log(answer)
this.pc.setLocalDescription(answer);
})
.then(() => navigator.mediaDevices.getUserMedia({audio: true, video: true}))
.then(stream => {
this.pc.addStream(stream)
this.yourVideo.srcObject = stream
})
.then(() => {
console.log("Sending answer message to server.")
this.sendMessage(JSON.stringify({'sdp': this.pc.localDescription}))
})
.catch(err => console.log(err))
}
else if (msg.sdp.type == "answer"){
console.log("Msg type is answer");
console.log("Setting pc's remote description to the answer from the server.");
this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
.then(() => navigator.mediaDevices.getUserMedia({audio: true, video: true}))
.then(stream => {
this.pc.addStream(stream)
this.yourVideo.srcObject = stream
})
}
} else {
console.log("IDs are similar. Data was sent by this client.")
}
}
现在,其他客户端得到了答案,但是没有发送ICE候选人。
事实证明,问题出在我的Firestore。我尝试恢复到上面链接的教程中使用的旧的实时数据库代码,并且按预期建立了调用。但是,一旦我将实现交换到Firestore上,就开始出现问题。
我制作了另一种方法将冰候选者发送到与SDP数据不同的单独文档中,并从我的peerconnection.onicecandidate中调用此函数:
const sendIceCandidates = (data) => {
console.log("SenderId: " + yourId);
console.log("Message: " + data);
// database.child("games").child(gameId).child("connection").set({ sender: senderId, message: data });
firestore.collection('games').doc(gameId).collection('connection').doc('ice').set({
sender: yourId,
message: data
}, err => {
console.log("Error ocurred inserting data into firestore. Logging error: ")
console.log(err)
})
}
然后,我将Firestore侦听器更改为集合侦听器,并指定当对集合添加或修改某些内容时,它会执行相同的操作:
const sendIceCandidates = (data) => {
console.log("SenderId: " + yourId);
console.log("Message: " + data);
// database.child("games").child(gameId).child("connection").set({ sender: senderId, message: data });
firestore.collection('games').doc(gameId).collection('connection').doc('ice').set({
sender: yourId,
message: data
}, err => {
console.log("Error ocurred inserting data into firestore. Logging error: ")
console.log(err)
})
}