具有完美协商的 WebRTC - 在移动 Safari 上回滚不起作用

WebRTC with perfect negotiation - Rollback on mobile Safari does not work

我正在尝试通过考虑以下页面中的示例为我的小型视频会议应用程序实现完美的 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)]);

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

"The RTCPeerConnection is closed, or it's in a state which isn't compatible with the specified description's type. For example, if the type is rollback and the signaling state is one of stable, have-local-pranswer, or have-remote-pranswer, this exception is thrown, because you can't roll back a connection that's either fully established or is in the final stage of becoming connected."

在回滚之前检查对等连接信号状态显示它处于状态 "have-local-offer" 这应该没问题,因为 MDN 表示在这些状态下回滚是不可能的(抛出 InvalidStateError)稳定,have-local-pranswer,或 have-remote-pranswer.

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

这里有人知道移动版 Safari 的潜在问题或处理方式不同吗?

, Safari (both iOS/mobile and macOS) has a known bug{ type: 'rollback' } 中所述。它还不支持 setLocalDescription/setRemoteDescription 中的可选描述,规范中最新的完美协商建议。

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

  1. 重置任何状态变量(例如makingOfferisSettingRemoteAnswerPending
  2. 通过调用 peerConnection.close()
  3. 关闭对等连接
  4. 拆除所有对等连接事件侦听器(例如 negotiationneededicecandidatetrack
  5. 向其他对等方发出信号以执行相同操作,例如通过 websocket 消息
  6. 收到重启的信号后,对方可以进行相同的步骤,最后创建一个新的offer,重新开始协商过程。

可以在 this demo.

中看到此流程的示例

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

  1. onnegotiationneeded中:如果我们在safari上,请不要做createOffer()setLocalDescription(),前提是要礼貌。

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

我的假设是 Safari webkit 不喜欢被提供给同行的报价。除了它似乎有效之外,我没有任何证据支持它 - 错误消失并且我得到了视频。

好消息:Safari 技术预览版 (15.4) supports implicit rollback in setRemoteDescription directly¹, which appears to also have fixed the explicit {type: 'rollback'} method you were using in the more backwards-compatible polyfill (though I've asked for clarification in the bug).

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

隐式回滚是专门为完美协商而设计的,让你standard pattern directly. Here's a fiddle使用它。


1.我已经提交了一份 PR to update MDN 来反映这一点。