web-dev-qa-db-fra.com

DOMException: échec de la définition de l'offre à distance sdp: appelé dans un état incorrect: STATE_SENTOFFER

J'essaie de créer une application Web d'appel vidéo à l'aide de webRTC. J'utilise angularjs et express.io

J'obtiens cette erreur: DOMException: Échec de la définition de l'offre à distance sdp: Appelé dans un état incorrect: STATE_SENTOFFER

Une partie de mon code est:

// in controller (socket is already defined in controller)
var videolocal = document.getElementById('videolocal');
var videoremote = document.getElementById('videoremote');
var streamlocal = null;
var pc = null;
window.URL = window.URL || window.webkitURL;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;

var configuration = {'iceServers': [
        // {'url': 'stun:stun.services.mozilla.com'}, 
        {'url': 'stun:stun.l.google.com:19302'}
    ]};

// run start(true) to initiate a call
$scope.start = function() {
    console.log('start');

    // get the local stream, show it in the local video element and send it
    navigator.getUserMedia({ "audio": true, "video": true }, function (stream) {
        videolocal.src = URL.createObjectURL(stream);
        pc = new RTCPeerConnection(configuration);
        pc.addStream(stream);

        // once remote stream arrives, show it in the remote video element
        pc.onaddstream = function (evt) {
            console.log('onaddstream');
            videoremote.src = URL.createObjectURL(evt.stream);
        };

        // send any ice candidates to the other peer
        pc.onicecandidate = function (evt) {
            console.log('onicecandidate');
            if(evt.candidate){
                socket.emit('video_call',{user:2, type: 'candidate', candidate: evt.candidate});
            }                       
        };                          

        // create an offer 
        pc.createOffer(function (offer) {
            socket.emit('video_call', {user:2,  type: "offer", offer: offer}); 
            pc.setLocalDescription(offer);
        }, function (error) { 
            alert("Error when creating an offer"); 
        });
    }, function () {alert('error in start')});
}
$scope.start();

socket.on('video_call', function (data) {
    console.log(data);
    //when somebody sends us an offer 
    function handleOffer(offer) {
        // this line is giving error
        pc.setRemoteDescription(new RTCSessionDescription(offer), function(){alert('success')}, function(e){ console.log(e); alert(e)});

        //create an answer to an offer 
        pc.createAnswer(function (answer) { 
            pc.setLocalDescription(answer); 
            socket.emit('video_call', {user:2, type: "answer", answer: answer});                            
        }, function (error) {
            console.log(error); 
            alert("Error when creating an answer"); 
        }); 
    };

    //when we got an answer from a remote user
    function handleAnswer(answer) { 
       pc.setRemoteDescription(new RTCSessionDescription(answer)); 
    };

    //when we got an ice candidate from a remote user 
    function handleCandidate(candidate) { 
       pc.addIceCandidate(new RTCIceCandidate(candidate)); 
    };

    switch(data['type']) { 
        case "offer": 
            handleOffer(data["offer"]); 
            break; 
        case "answer": 
            handleAnswer(data['answer']); 
            break; 
        //when a remote peer sends an ice candidate to us 
        case "candidate": 
            handleCandidate(data['candidate']); 
            break; 
        default:
            break; 
   }
});

Sur le serveur:

// this function is called on video_call event
video_call: function (data) {
    var id = data.user; 

    // if user is active
    // users is dict of users (user_id as key)
    if(Object.keys(users).indexOf(id.toString()) > -1){
        // for each device of the user
        users[id].forEach(function(user_socket){
            console.log(data);
            user_socket.emit('video_call', data);               
        });
    }
}

S'il vous plaît quelqu'un peut-il dire ce qui ne va pas avec ce code. Le flux local capture correctement. J'utilise un navigateur Chrome.

Données sur le serveur: enter image description here

10
Harish Kumar

Je pense que le problème est que dans votre fonction handleOffer() vous devez créer une autre PeerConnection et appeler setRemoteDescription() sur ce PC.

var remote_pc = new RTCPeerConnection(configuration)
remote_pc.setRemoteDescription(new RTCSessionDescription(offer), ...) {
  remote_pc.createAnswer()
}

C'est ce que j'ai dans mon code.

EDIT: Dans le lien officiel vous pouvez aller au chapitre 11.7 et vérifier les étapes après 15 (lorsque l'offre est envoyée et l'autre pair le reçoit).

4
Samuel Méndez