WebRTC double video-offer message

2019-07-23 11:51发布

问题:

I'm trying to build a video-chat with a WebRTC. The problem which I have, is that the video-offer is going in both sides like:

PC1 -> send video-offer
PC2 <- handle video-offer message
PC2 -> send video-answer
PC1 <- handle video-answer (when there is debugger breakpoint, the connection is working)
PC2 -> send video-offer
...

I'm sending video-offer message only in negotiationEventHandler:

function handleNegotiationNeededEvent() {
    logMessage('HandleNegotiationNeededEvent fired!');
    myPeerConnection.createOffer() //tworzymy SDP offer dla drugiego uzytkownika
        .then(function (offer) {
        return myPeerConnection.setLocalDescription(offer);
    })
        .then(function () {
            sendToWebSocket(msgTypeVideoOffer, senderId, receiverId, JSON.stringify(myPeerConnection.localDescription));
        })
        .catch(reportError);
}

and handling video-offer / video-answer in two functions

function handleVideoOfferMsg(msg){
    logMessage("handle video-offer message call");
    var localStream = null;

    createPeerConnection();

    var desc = new RTCSessionDescription(JSON.parse(msg.messageContent));
    debugger;
    myPeerConnection.setRemoteDescription(desc)
        .then(function () {
            return navigator.mediaDevices.getUserMedia(mediaConstraints);
        })
        .then(function (stream) {
            localStream = stream;
            document.getElementById("local_video").srcObject = localStream;
            myPeerConnection.addStream(localStream);
        })
        .then(function () { //Utworz odpowiedz
            return myPeerConnection.createAnswer();
        })
        .then(function (answer) { //Ustaw ja sobie jako lokalna
            return myPeerConnection.setLocalDescription(answer);
        })
        .then(function () { //I wyslij SDP do peera
            sendToWebSocket(msgTypeVideoAnswer, senderId, receiverId, JSON.stringify(myPeerConnection.localDescription));
        })
        .catch(handleGetUserMediaError);
}

function handleVideoAnswerMessage(message) {
    logMessage("handle video answer message" + message);
    var desc = message.messageContent;
    myPeerConnection.setRemoteDescription(JSON.parse(desc));
}

The problem is, that handling video-offer is setting a new objects, what probably is a reason of losing a connection.

回答1:

This is a bug in the Chrome browser. MDN is right, and this works fine in Firefox.

For a basic sendrecv audio+video offer, the answerer should be allowed to add one video and one audio stream and call setLocalDescription without this firing a negotiationneeded event.

Chrome fails to clear negotiationneeded on the answerer side after the expected audio and video have been added, and in fact will keep firing negotiationneeded back and forth forever.



回答2:

The answer is, that negotiationneeded event is fired every time, when RTCPeerConnection.addStream() function is called with success. So my solution is to check if only inviter has such event handler set:

if(isInviter){
        myPeerConnection.onnegotiationneeded = handleNegotiationNeededEvent;
    }

My question code is based on mozilla WebRTC Signalling sample, which is just wrong implemented, so be careful using it: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling