Onnegotiationneed только запускается со стороны отправителя RtcPeerConnection - PullRequest
1 голос
/ 17 апреля 2020

Я разрабатываю систему чата, которая использует WebRT C, чтобы позволить коллегам отправлять видео друг другу. В чате только два пользователя. Я кодировал его так, что для каждого чата создаются две RtcPeerConnections; одно соединение для исходящего видео и одно для входящего видео.

Я использую следующий код для обработки, когда необходимо пересмотреть соединение (добавлены новые треки, изменения в сети и т. д. c), и я подозреваю, что может ли мой подход вызвать проблемы со стабильностью работы системы чата. Для краткости я исключил обмен кандидатами в 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))
});

Приведенный выше код делает предположение, что удаленному концу RtcPeerConnection никогда не нужно обрабатывать onnegotiationneeded на основе комментария о onnegotiationneeded here :

Это согласование должно быть выполнено как поставщик поскольку некоторые изменения сеанса не могут быть согласованы как ответчик.

Я интерпретировал это как означающее, что исходному предложителю *1022* соединения потребуется только пересмотреть соединение. Альтернативное объяснение состоит в том, что обе стороны могут пересмотреть условия, но какая бы сторона ни сделала это, она должна стать отправителем. Если это последнее, то приведенный выше код не будет правильно обрабатывать повторное согласование, когда ожидается, что ответчик должен его обработать.

Итак, может ли согласование потребовать возмездия со стороны ответчика? В моем тестировании я не видел этого, и я изо всех сил пытаюсь получить оценку того, что спецификации говорят в этом отношении.

1 Ответ

2 голосов
/ 17 апреля 2020

Может. Допустим, у вас есть подключение только для аудио, например, этот образец Затем вы хотите добавить видео к этому соединению, чтобы вставить следующее в консоль:

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

ONN будет запускаться на ответчика, поскольку он должен создать новое предложение с SDP, которое ведет переговоры по видео.

Сообщение в блоге "1002 *" совершенные переговоры " от Mozillas Jan-Ivar является хорошим справочным материалом для обоснования. Непонятно, на что ссылается статья mdn, в частности, так как она не детализирована go.

...