Trouble adding and receiving tracks in WebRTC

Viewed 184

I am building a p2p group video chat based on this example: https://github.com/eugenp/tutorials/tree/master/webrtc

I've altered the code to give each user an ID and created a dictionary in which I save created connections for each peer(key:id, value:RTCPeerConnection).

It works that when a user enters the room he gets the list of all currently connected users, then connections are created for each connected user and offers are sent. When the user gets back answers connection is established between each user. I'm able to send and receive text messages using the connections, but upon trying to .addTracks() to the individual connections nothing happens. Using the onTrack or eventlistener("track") I'm unable to retrieve the streams.

I was able to implement video and audio while it was 1on1 but upon trying to have multiple connections it doesn't work anymore. I think it has to do with the offers because they seem to lack the receive audio/video, I've tried using offerToReceiveAudio:1, offerToReceiveVideo:1 but it doesn't seem to improve the situation.

var conn = new WebSocket('wss://192.168.5.11:8443/socket');

const messageBox = document.getElementById('messageBox')
const videoGrid = document.getElementById('video-grid')
const myVideo = document.createElement('video')
myVideo.muted = true
var input = document.getElementById("messageInput");

let myID;


const configuration = {
    "iceServers": [{
        "urls": "stun:stun.l.google.com:19302"
    }]
};
connections = {}
dataChannels = {}


conn.onopen = function() {
    console.log("Connected to the signaling server");
};

conn.onmessage = function(msg) {
    console.log("Got message", msg.data);
    var content = JSON.parse(msg.data);
    var data = content.data;
    switch (content.event) {
        //upon a new user joining we will be getting an offer from them
        case "offer":
            if(content.to!=myID) break;
            var from = content.from;
            peerConnecting(content.from);
            handleOffer(data,connections[from],from);
            break;
        //the joined user gets answers and handles them
        case "answer":
            if(content.to!=myID) break;
            handleAnswer(data,connections[content.from]);
            break;
        // when a remote peer sends an ice candidate to us
        case "candidate":
            if(content.to!=myID) break;
            handleCandidate(data,connections[content.from]);
            break;
        //when a user joins he gets list of all users with the event of NEW_CONNECTION, he creates offers which are sent
        // to all the users
        case "NEW_CONNECTION":
            peerConnecting(data);
            createOffer(connections[data],data);
            console.log(data);
            break;
        //upon joining the room we get sent our own id so we can check which messages are meant for us
        case "OWN_ID":
            myID=data;
            break;
        default:
            break;
    }
};

//sends message to the socket handler
function send(message) {
    conn.send(JSON.stringify(message));
}

//creating new RTCPeerConnection for user with the ID
function peerConnecting(ID){
    connections[ID]= new RTCPeerConnection(configuration);

    navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true
    }).
    then(stream => {
        addVideoStream(myVideo, stream)
        stream.getTracks().forEach(track => connections[ID].addTrack(track,stream),console.log("track added"))
    }).catch(function(err) {
        /* handle the error */
    });
    connections[ID].onicecandidate = function(event) {
        if (event.candidate) {
            send({
                event : "candidate",
                data : event.candidate,
                from : myID,
                to : ID
            });
        }
    };

    dataChannels[ID] = connections[ID].createDataChannel("dataChannel",{
        reliable : true
    });

    dataChannels[ID].onerror = function(error) {
        console.log("Error occured on datachannel:", error);
    };

    // when we receive a message from the other peer, printing it on the console
    dataChannels[ID].onmessage = function(event) {
        console.log("message:", event.data);
        messageBox.append("them:"+event.data);
    };

    dataChannels[ID].onclose = function() {
        console.log("data channel is closed");
    };

    connections[ID].ondatachannel = function (event) {
        console.log("data channel is open");
        dataChannels[ID] = event.channel;
    };

    //addind src to remotevideo element
    const remoteStream = new MediaStream();
    const remoteVideo = document.querySelector('#remoteVideo');
    remoteVideo.srcObject = remoteStream;

    connections[ID].addEventListener('track', async (event) => {
        remoteStream.addTrack(event.track);
    });


}


function createOffer(peerConnection,ID) {
    peerConnection.createOffer({
        offerToReceiveAudio:1,
        offerToReceiveVideo:1
    }).then(offer => {
        send({
            event : "offer",
            data : offer,
            from : myID,
            to : ID
        });
        peerConnection.setLocalDescription(offer);
    }, function(error) {
        alert("Error creating an offer");
    });
}

function handleOffer(offer,peerConnection,ID) {
    peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
    // create and send an answer to an offer
    peerConnection.createAnswer({
        offerToReceiveAudio:1,
        offerToReceiveVideo:1
    }).then(answer=> {
        peerConnection.setLocalDescription(answer);
        send({
            event : "answer",
            data : answer,
            from : myID,
            to : ID
        });
    }, function(error) {
        alert("Error creating an answer");
    });

};

function handleCandidate(candidate,peerConnection) {
    peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
};

function handleAnswer(answer, peerConnection) {
    peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
    console.log("connection established successfully!!");
};

function sendMessage() {
    for (const [key, value] of Object.entries(dataChannels)) {
       value.send(input.value)
    }
    messageBox.append("me:"+input.value);
    input.value = "";
}


function addVideoStream(video, stream) {
    video.srcObject = stream
    video.addEventListener('loadedmetadata', () => {
        video.play()
    })
    videoGrid.append(video)
}```
0 Answers
Related