【问题标题】:Unable to construct RTCIceCandidate from candidate string无法从候选字符串构造 RTCIceCandidate
【发布时间】:2020-11-17 10:06:16
【问题描述】:

Chrome

计算机 A 上生成的 ICE 候选字符串(直接取自 SDP 属性“candidate”):

candidate:2999745851 1 udp 2122260223 192.168.X.1 65398 typ host generation 0 ufrag XBYY network-id 2

现在通过信令传递,在计算机 B 上接收。

收到计算机 B (iceStr):

candidate:2999745851 1 udp 2122260223 192.168.X.1 65398 typ host generation 0 ufrag XBYY network-id 2

并尝试let candidate = new RTCIceCandidate(iceStr)

这会导致

TypeError:无法构造“RTCIceCandidate”:无法转换为 字典。

计算机 B 这样做是为了执行

addIceCandidate(candidate) 

在 RTCPeerConnection 对象上。

但是,由于之前的错误,无法继续。

可重现的示例

 <script type="text/javascript">
 let c ='candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10';
 let candidate = new RTCIceCandidate(c);
</script>

想法?

所有官方代码示例和文档都指示将该参数发送到远程对等方。 https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onicecandidate

然后对弃用(似乎是由其他函数在后台构建)和 JSON 编码存在一些混淆,所以它是哪一个。

来自官方样本: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling

    function handleNewICECandidateMsg(msg) {
  var candidate = new RTCIceCandidate(msg.candidate);

  myPeerConnection.addIceCandidate(candidate)
    .catch(reportError);
}

该值似乎也直接传递给var candidate = new RTCIceCandidate(msg.candidate);,这最终成为徒劳的练习(同样的错误)。

更新: 看起来 API 只能理解 String OBJECT(考虑到 EVENT 包含原始类型,这有点可惜!)即 可重复的样品

    <script type="text/javascript">
 let c = new String('candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10');
 let candidate = new RTCIceCandidate(c);
</script>

但是,即使这样 Chrome 也会产生异常

TypeError: 无法构造 'RTCIceCandidate': sdpMid 和 sdpMLineIndex 均为空。

似乎还有其他“值得怀疑”的事情......比如 WebRTC 报价包含特定于平台的换行符。

RTCSessionDescription 不能直接从事件返回的 SDP 报价中实例化,因为它是 PRIMITIVE 类型并且 RTCSessionDescription() 需要 String OBJECT。此外,原始类型不能轻易转换为字符串,因为它包含特定于平台的换行符,因此简单的 new String(SDP) 会导致格式错误的字符串对象。

有人吗?

更新 在 WebRTC 报价的情况下,文档没有说明需要向 RTCSessionDescription 提供包含类型(蹩脚的“报价”字符串)和 SDP 字段的显式 JSON 对象。哪种类型的隐式强制在整个信令过程中首先使用 JSON(低效编码)。 (如果一个人不能自己重建跛脚的领域,但这与到处都是黑箱的态度相矛盾)

【问题讨论】:

    标签: javascript google-chrome webrtc


    【解决方案1】:

    您正在尝试仅使用候选字符串而不是包含 sdpMid 和 sdpMLineIndex 属性的完整对象,请参阅https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate

    您可以将 RTCIceCandidate 对象构造为

    new RTCIceCandidate({
      candidate: 'candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10',
      sdpMid: 'something', // don't make it up, you get this in onicecandidate
      sdpMLineIndex: 12345, // don't make it up, you get this in onicecandidate
    })
    

    或者你打电话

    pc.addIceCandidate({  
      candidate: 'candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10',
      sdpMid: 'something', // don't make it up, you get this in onicecandidate
      sdpMLineIndex: 12345, // don't make it up, you get this in onicecandidate
    })
    

    这同样适用于 RTCSessionDescription 对象。

    【讨论】:

    • 让我们牵着马。那么文档至少令人困惑。它以样本和书面形式声明:“(远程对等方在收到候选者后,将通过调用 addIceCandidate() 将候选者添加到其候选者池中,传入候选者 *string *您已使用信令服务器传递。 ) " 它甚至没有表明需要传递额外的字段。或者为了序列化这些字段而使用 toJSON() 是一种不喜欢 JSON 而不是 BER 的例子。
    • 虽然这可能有效,但官方示例/教程并没有做任何类型的“魔术”,也没有使用 toJSON() 来包含附加字段。他们也不建议将 JSON 对象传递给构造函数。
    • developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/… 专用部分指出需要共享字符串。它没有说明需要或在哪里可以找到 sdpMid 和 sdpMLineIndex 参数。
    • 如果文档的作者要坚持“需要交换字符串”,他们至少应该建议交换 JSON.stringify() 的结果,它确实会生成一个包含所需字段的字符串.或者需要额外的字段是开发人员不使用 JSON。该信息无处可寻,也不存在于代码示例中。
    • 一旦我们完成当前的实施运行,满手的工作(就像我们所有人一样)会尝试这样做。
    猜你喜欢
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    • 2019-05-13
    • 1970-01-01
    相关资源
    最近更新 更多