socket.iowebrtcvideocall

Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Failed to set local offer sdp: Called in wrong state: have-remote-offer


While calling to another user getting this error "Uncaught (in promise) DOMException: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Failed to set local offer sdp: Called in wrong state: have-remote-offer".

Receiver is able to see both local and remote stream but caller not able to see remote stream.

                  switch(type){
                    case 'client-candidate':
                        if(pc.localDescription){
                            await pc.addIceCandidate(new RTCIceCandidate(data));
                        }
                    break;

                    case 'is-client-ready':
                        if(!pc){
                            await getConn();
                        }
                        if(!localStream){
                            await getCam();
                        }

                        if(pc.iceConnectionState === 'connected'){
                            send('clent-already-oncall', null, presentUserId, null);
                        }else{
                            displayCall(incomingData);

                            $(document).on('click', '#declineBtn', function(){
                                send('client-rejected', sendTo, currentUserName, presentUserId, null);
                                $('#incomingCallModel').modal('toggle');
                            });

                            $(document).on('click', '#answerBtn', function(){
                                
                                send('client-is-ready', sendTo, currentUserName, presentUserId, null);
                                $('#incomingCallModel').modal('toggle');
                                createOffer(sendTo, presentUserId);
                            });
                        }
                    break;

                    case 'client-answer':
                        if(pc.localDescription){
                            await pc.setRemoteDescription(data);
                        }
                    break;

                    case 'client-offer':
                        createAnswer(sendTo, presentUserId, data);
                    break;

                    case 'client-is-ready':
                        createOffer(sendTo, presentUserId);
                    break;

                    case 'client-rejected':
                        alert('Client has rejected your call');
                    break;

                    case 'clent-already-oncall':
                        setTimeout(() => {
                            alert('client is on other call');
                            window.location.reload(true);
                        }, 2000);
                    break;
                }

let pc;

        function getConn(){
            if(!pc){
                pc = new RTCPeerConnection();
            }
        }

        async function getCam(){
            try{
                if(!pc){
                    await getConn();
                }
                mediaStream = await window.navigator.mediaDevices.getUserMedia(mediaConst);
                localVideo.srcObject = mediaStream;
                localStream = mediaStream;
                localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
            }catch(error){
                // alert('Camera not found')
                console.log(error);
            }
        }

        function displayCall(incomingData){
            $('.incoming-call-user-name').text(incomingData.callingUserName);

            let calligUserProfile = $("#allUserList").find("[data-id='" + incomingData.callingUserId + "']").data("profile");
            $('.calling-user-pic').attr('src', calligUserProfile);
            $('#incomingCallModel').modal('show');
        }

        function send(type, sendTo, callingUserName, callingUserId, data){
            socket.emit('sendChatRequest', JSON.stringify({
                type: type,
                receiverId: sendTo,
                callingUserName: callingUserName,
                callingUserId: callingUserId,
                data: data,
            }));
        }

        async function createOffer(sendTo, calledById){
            if(!pc){
                await getConn(); 
            }
            if(!localStream){
                await getCam();
            }
            await pc.createOffer(options);
            await sendIceCandidate(sendTo,calledById);
            await pc.setLocalDescription(pc.localDescription);
            send('client-offer', sendTo, currentUserName, calledById, pc.localDescription);
        }

        async function sendIceCandidate(sendTo, calledById){
            pc.onicecandidate = event => {
                if(event.candidate !== null){
                    send('client-candidate', sendTo, currentUserName, calledById, event.candidate);
                }
            }
            
            pc.ontrack = event => { 
                console.log(event)
                $('#video').removeClass('hide');
                $('#video').addClass('show');
                $('#videoCall').addClass('hide');

                if (remoteVideo.srcObject) return;

                remoteVideo.srcObject = event.streams[0];
            }
        }

        async function createAnswer(sendTo, presentUserId, data){
            if(!pc){
                await getConn(); 
            }
            if(!localStream){
                await getCam();
            }
            
            await sendIceCandidate(sendTo, presentUserId);
            await pc.setRemoteDescription(data);
            await pc.createAnswer();
            await pc.setLocalDescription(pc.localDescription);
            send('client-answer', sendTo, currentUserName, presentUserId, pc.localDescription);
        }

Solution

  • Possible reasons.

    Possible reasons of onTrack not firing