这个问题以前也问过几次,但我一直无法使任何解决方案发挥作用。我正在创建一个多对等的视频聊天。然而,每当一个对等体试图连接时,我都会收到这个错误。
DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: 调用错误的状态:kStable
奇怪的是,如果用户重新加载页面,我就不会出现这个错误,视频也会显示。两个客户端都需要进行重新加载。我猜浏览器已经缓存了 东西 并在第二次尝试时重新使用。
// When a remote user joins, an object of this class is created.
// Its job is to create am RTCPeerConnection between the local user
// and the remote user.
class VideoChat
{
constructor(name, remoteView)
{
this.remoteName = name; // ID of remote peer used by signal server
this.remoteView = remoteView; // html video object to display remote video
var configuration = {"iceServers": [
{urls: "stun:stun.l.google.com:19302"}
{urls: "turn:numb.viagenie.ca", username: "xxx", credential: "xxx"}
]};
this.pc = new RTCPeerConnection(configuration);
// 'onicecandidate' notifies us whenever an ICE agent needs to deliver a
// message to the other peer through the signaling server
this.pc.onicecandidate = event => {
if (event.candidate) {
ChatRoom.relay("signal", this.remoteName, event.candidate);
console.log(`onicecadidate (${this.remoteName}): ${event.candidate}`);
}
};
// let the 'negotiationneeded' event create the offer
this.pc.onnegotiationneeded = async () => {
try {
await this.pc.setLocalDescription();
ChatRoom.relay("signal", this.remoteName, {desc: this.pc.localDescription})
} catch (err) {
console.error(err);
}
}
// When a remote stream arrives display it in the #remoteView element
this.pc.ontrack = (track, streams) => {
log("adding remote TRACK to video element");
// don't set srcObject again if it is already set.
if (this.remoteView.srcObject) return;
this.remoteView.srcObject = event.streams[0];
};
}
// This is called by main program when a remote user has signed on
// This initiates everything....
// localVideo is html video element connected to local camera
// stream is the main (local) user's mediaStream
async start(localVideo, stream) {
try {
for (const track of stream.getTracks()) {
this.pc.addTrack(track, stream);
}
localVideo.srcObject = stream;
} catch (err) {
console.error(err);
}
}
// A message from the signal server
async onmessage(message) {
try {
if (message.desc) {
await this.pc.setRemoteDescription(message.desc);
if (message.desc.type == "offer") {
await this.pc.setLocalDescription();
ChatRoom.relay("signal", this.remoteName, {desc: this.pc.localDescription});
}
}
else if (message.candidate) {
await this.pc.addIceCandidate(message);
}
} catch (err) {
console.error(err);
}
}
}
注意这个功能。ChatRoom.relay("signal", this.remoteName, something)
向信号服务器发送一个消息,只转发到远程的id为: this.remoteName
.
另外,我使用的是我自己用Java创建的信号服务器。
如果你在同一个peerconnection上设置不同对等体的远程描述,那是行不通的。正如 "peerconnection "这个名字所暗示的那样,它是针对一个对等体的。
调用 this.pc.setLocalDescription()
在不创建报价的情况下,一些浏览器可能会支持,但要小心。而且你从来没有创建一个答案,只是标志着本地描述。你也没有对答案做任何事情。
https:/webrtc.github.iosamplessrccontentpeerconnectionmultiple 是如何做好事情的典范。