我一直在尝试实现WebRTC“完美协商”,正如这篇博客文章中所解释的那样。不幸的是,我经常在谈话的礼貌方面触发错误(在下面的链接代码中,这是最后一次加入)。
两个最常见的错误是由InvalidStateError: Cannot rollback local description in stable
引起的这条线和ONN DOMException: "Cannot set local offer in state have-remote-offer"
触发的这里和由这条线引起的。第二个错误对我来说是非常令人费解的,因为在检查我们应该处于stable
状态之前的行,这是之后的第一个异步调用。
如果您想自己尝试,我的代码是托管在GitHub上。它可以直接部署在Heroku上:
heroku create
git push heroku master
或者可以通过更改server.js的第1、7-10和15行在本地测试自签名证书。
当我在76、73版的桌面火狐、80版的桌面浏览器以及Android上最新的移动版本上进行测试时,我遇到了这些问题。如果能在这方面提供任何帮助,我们将不胜感激。我也希望能在iPads (Safari >= 11)上可靠地工作,这是我无法亲自测试的。
发布于 2020-05-23 16:29:32
TL;DR:浏览器在火狐77和规格中的固定和Chrome中的分离虫。
ONN DOMException: "Cannot set local offer in state have-remote-offer"
...第二个错误对我来说是非常令人费解的,因为在检查我们是否应该处于稳定状态之前的行,这是之后的第一个异步调用。
WebRTC协商代码具有将同步信令消息转换为RTCPeerConnection对象上的异步操作的棘手任务。为了确保顺序,这些异步方法在内部是链子,所以一次只运行一个,因为状态机。
在信令压力下,这个内部链可能会被填满,这会使事情复杂化,因为您调用的方法会在稍后运行,而不是立即处于您刚刚同步观察到的状态。
发生“第二个错误”是因为浏览器错误地触发了negotiationneeded
事件,而RTCPeerConnection对象的内部作业链是非空的。规范现在是固定,所以不会发生这种情况。
因为浏览器控制触发negotiationneeded
事件的时间,所以它会处理它。
InvalidStateError: Cannot rollback local description in stable
不礼貌方面的“第一个错误”类似地是重载链的症状:同步状态检查,如果我们处于不稳定状态,然后是:
if (offerCollision) { // pc.signalingState != "stable"
await Promise.all([
pc.setLocalDescription({ type: "rollback" }),
pc.setRemoteDescription(description),
]);
}
我怀疑在这个时候,还有其他谈判方法在运行setLocalDescription
回滚之前将我们带回到“稳定”状态。
为了解决这个问题,规范添加了隐式回滚,因此您可以用以下方法替换上面的内容:
await pc.setRemoteDescription(description); // implicit rollback only if needed
这样做更好,因为是否需要回滚的决定是在链式方法中进行的,在那个时候(可能以后)查看正确的信令状态。
不幸的是,这不是那么容易填充。你可以尝试这样的方法:
if (offerCollision) { // pc.signalingState != "stable"
await Promise.all([
pc.setLocalDescription({type: "rollback"}).catch(() => {}), // ignore failure
pc.setRemoteDescription(description),
]);
}
或者等待浏览器实现隐式回滚。
https://stackoverflow.com/questions/61956693
复制