Search code examples
htmlwebrtcweb-audio-apigetusermedia

1 page WebRTC - not getting any audio at the remote peer


I'm trying to build a one-page webRTC app in order to learn this topic. I have 2 audio tags :

<audio id="local"></audio>
<audio id="remote"></audio>

One represents the local peer and the other represents the remote peer. I've successfully "sent" the local video to the remote peer - the descriptions were set as the local and the remote descriptions of the 2 peers and the stream was successfully "arrived" to the remote peer - I can inspect the 2 audio elements and see that they both have a blob url of the stream. But, only when I play the local video I can hear the audio - when I'm turning it off and playing the remote audio, I don't hear anything.

Why is it happening? Here is the JS code:

var local = document.querySelector("#local"); //The local audio tag
var remote = document.querySelector("#remote"); //The remote audio tag
var pc1; //The local peer
var pc2; //The remote peer

//Autoplay
//local.play();
remote.play();

navigator.webkitGetUserMedia({audio:true},function(stream){ //Get the audio
    local.src = window.URL.createObjectURL(stream);
    pc1 = new webkitRTCPeerConnection(null); //Initialize the local peer
    pc2 = new webkitRTCPeerConnection(null); //Initialize the remote peer
    pc1.addStream(stream); //Add the local stream to the connection => pass it to the remote peer

    pc1.createOffer(gotDescription1); //Create an offer and when you get the description call gotDescription1
    pc2.createAnswer(gotDescription2); //Create an answer acoording to the description you get from the local peer
    pc1.onicecandidate = gotLocalIceCandidate;
    pc2.onicecandidate = gotRemoteIceCandidate;
    pc2.onaddstream = gotRemoteStream; //When you get stream, call gotRemoteStream

},function(e){ //If there is an error
    console.error("ERROR: "+e);
});

function gotDescription1(desc){
    console.log("Offer from pc1 \n" + desc.sdp);
    pc1.setLocalDescription(desc); //set the description as the local description of the local peer
    //(Send the description to the remote peer)
    pc2.setRemoteDescription(desc); //set the description as the remote description of the remote peer
}

function gotDescription2(desc){
    console.log("Set the description in pc2");
    pc2.setLocalDescription(desc); //Set the description as the local description of the remote peer
    //(Send the description to the local peer)
    pc1.setRemoteDescription(desc); //set the description as the remote description of the local peer
}

function gotRemoteStream(e){
    remote.src = window.URL.createObjectURL(e.stream); //Play the stream you get
}

function gotLocalIceCandidate(event) {
    if (event.candidate) {
        pc2.addIceCandidate(new RTCIceCandidate(event.candidate));
    }
}

function gotRemoteIceCandidate(event) {
    if (event.candidate) {
        pc1.addIceCandidate(new RTCIceCandidate(event.candidate));
    }
}

Solution

  • You order of execution in your javascript is slightly off

    You have not set the onaddstream event handler until already getting the remote stream(getting the remote stream can happen as early as setting the remote description).

    It is also better for you to handle creating the answer inside the gotDescription1 callback as the callbacks are asynchronous and could be called out of order. I also set both audio html5 elements to autoplay instead of having to set them to play(you may want to do this as well)

    Get user media changes:

     navigator.webkitGetUserMedia({ audio: true }, function (stream) { //Get the audio
            local.src = window.URL.createObjectURL(stream);
            pc1 = new webkitRTCPeerConnection(null); //Initialize the local peer
            pc2 = new webkitRTCPeerConnection(null); //Initialize the remote peer
            pc1.addStream(stream); //Add the local stream to the connection => pass it to the remote peer
            pc1.onicecandidate = gotLocalIceCandidate;
            pc2.onicecandidate = gotRemoteIceCandidate;
            pc2.onaddstream = gotRemoteStream; //When you get stream, call gotRemoteStream
            pc1.createOffer(gotDescription1); //Create an offer and when you get the description call gotDescription1
        }, function (e) { //If there is an error
            console.error("ERROR: " + e);
        });
    

    And the gotDescription1 callback:

    function gotDescription1(desc) {
        console.log("Offer from pc1 \n" + desc.sdp);
        pc1.setLocalDescription(desc); //set the description as the local description of the local peer
        //(Send the description to the remote peer)
        pc2.setRemoteDescription(desc); //set the description as the remote description of the remote peer
        pc2.createAnswer(gotDescription2); //Create an answer acoording to the description you get from the local peer
    }