3

我正在尝试通过考虑以下页面中的示例为我的小型视频会议应用程序实现完美的 WebRTC 协商:

https://blog.mozilla.org/webrtc/perfect-negotiation-in-webrtc/

不幸的是,我没有设法让它完全工作,特别是移动 safari 似乎以自己的方式处理回滚行为,这里是处理回滚行为的代码:

      if (description) {
        const offerCollision = description.type == 'offer' && (makingOffer || pc.signalingState != 'stable');
        this.ignoreOffer = !this.polite && offerCollision;
        if (this.ignoreOffer) {
          return;
        }
        if (offerCollision) {
          await Promise.all([pc.setRemoteDescription({ type: 'rollback' }), pc.setRemoteDescription(description)]);

因此,当在移动 safariofferCollision === true上检测到报价冲突 () 并pc.setRemoteDescription({ type: 'rollback' })在我的代码中实现时调用它,它会引发类型错误InvalidStateError。仔细查看 MDN 中有关此类错误的文档(https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription#Browser_compatibility)显示:

“RTCPeerConnection 已关闭,或者处于与指定描述类型不兼容的状态。例如,如果类型为回滚且信令状态为稳定、具有本地-pranswer 或具有-远程- pranswer,抛出此异常,因为您无法回滚已完全建立或处于连接的最后阶段的连接。”

在回滚之前检查对等连接信号状态表明它处于“have-local-offer”状态,这应该没问题,因为 MDN 说InvalidStateError在状态稳定的状态下回滚是不可能的(抛出), have-local-pranswer,或有-远程-pranswer。

对于另一种情况,当我的桌面 Chrome 浏览器在报价冲突中运行时,一切都在启动回滚之前以相同的信号状态按预期工作。

这里的人是否知道移动 Safari 可能存在什么问题或需要以不同方式处理。

4

3 回答 3

3

正如评论中提到的,Safari(iOS/移动和 macOS)有一个已知的错误{ type: 'rollback' }。它还不支持setLocalDescription/setRemoteDescription中的可选描述,这是规范中最新的完美协商建议。

这可以通过丢弃冲突的对等连接并重试(如建议的那样)来解决。为此,请在设置远程描述时通过以下步骤处理错误:

  1. 重置任何状态变量(例如makingOffer, isSettingRemoteAnswerPending
  2. 通过调用关闭对等连接peerConnection.close()
  3. 拆除任何对等连接事件侦听器(例如negotiationneeded, icecandidate, track
  4. 向其他对等方发出信号以执行相同的操作,例如通过 websocket 消息传递
  5. 对方收到重启信号后,可以通过相同的步骤,最终创建一个新的报价,重新开始谈判过程。

在这个演示中可以看到这个流程的一个例子。

于 2021-02-25T19:19:47.033 回答
1

好消息:Safari 技术预览版 (15.4)直接支持setRemoteDescription中的隐式回滚¹ ,这似乎也修复了您在更向后兼容的 polyfill 中使用的显式方法(尽管我已在错误{type: 'rollback'}中要求澄清)。

坏消息:在撰写本文时,它仍然无法在常规 Safari(现在为 15.3)或 iOS 版 Safari 中使用。但这应该只是时间问题。

隐式回滚专为完美协商而设计,让您直接使用标准模式。这是一个使用它的小提琴。


1. 我已提交PR以更新MDN以反映这一点。

于 2022-01-28T00:52:54.897 回答
0

万一有人发现自己回到这里,我发现如果我进行 2 项更改,我可以与 Safari 进行完美的协商:

  1. in onnegotiationneeded:如果我们在 safari 上,不要这样做,createOffer()或者setLocalDescription()如果实例是礼貌的。

  2. 对于传入的消息,除了现有的“忽略报价”功能外,type=='offer'如果实例不礼貌并且我们在 safari 上运行,则忽略消息。

我的假设是 Safari webkit 不喜欢在向同行提供报价时收到报价。除了它似乎有效的事实之外,我没有任何东西可以支持它 - 错误消失了,我得到了视频。

于 2022-01-27T13:49:09.037 回答