【问题标题】:Is onnegotiationneeded only fired from the offerer's side of a RtcPeerConnection是否需要仅从 RtcPeerConnection 的提供方一侧触发
【发布时间】:2020-04-17 13:47:01
【问题描述】:

我开发了一个聊天系统,它使用 WebRTC 让同伴互相发送视频。聊天中只有两个用户。我已经对其进行了编码,因此为每个聊天创建了两个 RtcPeerConnections;一个连接用于传出视频,一个用于传入视频。

我使用以下代码来处理需要重新协商连接(添加新曲目、网络更改等)的情况,并且我怀疑我的方法是否会导致聊天系统继续出现稳定性问题。为了简洁起见,我在下面的代码中省略了 ICE 候选人交换和一堆其他内容 - 希望它仍然足够有意义:

navigator.mediaDevices.getUserMedia(mediaConstraints)
    .then(stream => {
        // outgoingPcContainer/incomingPcContainer encapsulates the RtcPeerConnection for the outgoing video
        outgoingPcContainer.pc = new RTCPeerConnection(iceServers);   

        outgoingPcContainer.pc.onnegotiationneeded = () => {
            if (outgoingPcContainer.isNegotiating) return;
            outgoingPcContainer.isNegotiating = true;

            outgoingPcContainer.pc.createOffer({
                offerToReceiveAudio: true,
                offerToReceiveVideo: true,
            });
                .then((offer) => {
                    return outgoingPcContainer.pc.setLocalDescription(offer);
                })
                .then(() => {
                    // Send SDP to the other user via signalling channel
                    invokeSignalRMethod('sendConnectionOffer', recipientId, outgoingPcContainer.pc.localDescription);
                })
                .finally(() => {
                    outgoingPcContainer.isNegotiating = false;
                });
        };

        stream.getTracks().forEach(track => 
            outgoingPcContainer.pc.addTrack(track, stream));
    }

请注意,此事件处理程序仅受传出(提供者)RtcPeerConnection 的约束。

收件人收到此优惠并回复回复:

chatHub.on('connectionOffered', (offererId, desc) => {
    incomingPcContainer.pc = new RtcPeerConnection(iceServers);
    incomingPcContainer.pc.setRemoteDescription(desc)
        .then(() => incomingPcContainer.pc.createAnswer(answer))
        .then(answer => incomingPcContainer.pc.setLocalDescription(answer))
        .then() => {
            // send back the answer to the offerer
            invokeSignalRMethod('sendConnectionOfferAnswer', offererId, incomingPcContainer.pc.localDescription);
        });
});

最后,提供者收到接收者的答复:

chatHub.on('connectionOfferAnswered', (answererId, desc) => {
    outgoingPcContainer.pc.setRemoteDescription(new RTCSessionDescription(desc))
});

上面的代码基于关于 onnegotiationneeded here 的评论假设 RtcPeerConnection 的远程端永远不需要处理 onnegotiationneeded:

此协商应作为提议者进行,因为某些会话更改无法作为应答者进行协商。

我将此解释为连接的原始提供者只需要重新协商连接。另一种解释是,双方都可以重新谈判,但无论哪一方这样做,它都应该成为报价方。如果是后者,那么上面的代码将无法在应答者处理重新协商时正确处理。

那么,onnegotiationneeds 可以从应答者一方开火吗?在我的测试中,我没有看到这一点,我正在努力了解规范在这方面的规定。

【问题讨论】:

    标签: webrtc


    【解决方案1】:

    可以。假设您有一个纯音频连接,例如来自this sample 然后您想将视频添加到该连接,因此您将以下内容粘贴到控制台中:

    const video = await navigator.mediaDevices.getUserMedia({video: true});
    pc2.onnegotiationneeded = () => console.log('pc2 ONN');
    pc2.addTrack(video.getVideoTracks()[0], video);
    

    ONN 将触发应答器,因为它需要使用协商视频的 SDP 创建新报价。

    Mozillas Jan-Ivar 的"perfect negotiation" blog post 是一个很好的基本原理参考。不清楚 mdn 文章指的是什么,特别是因为它没有详细说明。

    【讨论】:

    • 啊,谢谢。我实际上已经阅读了那篇文章,但由于实现似乎依赖于isn't yet in Chrome 的功能,因此我大致略读了一遍。除此之外,我认为因为我使用单独的RtcPeerConnections,并且只有传出的提议者是添加或删除该连接的轨道的人,我想我避免了这种情况。尽管如此,你已经说服我这是可能的,所以我会做出必要的改变。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2022-09-23
    • 2018-05-04
    • 2012-12-23
    • 1970-01-01
    • 2017-08-22
    • 1970-01-01
    • 2017-06-25
    • 2020-11-30
    相关资源
    最近更新 更多