“Cannot create answer in state stable” in chrome [duplicate]












2
















This question already has an answer here:




  • How to set remote description for a WebRTC caller in Chrome without errors?

    1 answer




I'm implementing WebRTC peer-to-peer call, it is working well in all browser except if chrome is the call initializer (who invoke invite function).



if chrome is the call initializer, the ICE connection state change to connected and the video appear in the other peer,then an error "DOMException: "Cannot create answer in state stable"' happen and the video stop transfer to the other peer.



if the receiver is also chrome, the error says "Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer."



these are the handleVideoOfferMsg function and handleGetUserMediaError function (which trigger the error) code:



function handleVideoOfferMsg(msg) {
// debugger;
// $("#ring")[0].play();

var localStream = null;

targetUsername = msg.from;

// Call createPeerConnection() to create the RTCPeerConnection.

log("Starting to accept invitation from " + targetUsername);
createPeerConnection();

// We need to set the remote description to the received SDP offer
// so that our local WebRTC layer knows how to talk to the caller.

var desc = new RTCSessionDescription(msg.sdp);

myPeerConnection.setRemoteDescription(desc).then(function () {

log("Setting up the local media stream...");
return navigator.mediaDevices.getUserMedia(responserConstraints);
})
.then(function(stream) {

$("#video-container").removeClass("hidden");
log("-- Local video stream obtained");
localStream = stream;
if(responserConstraints.hasOwnProperty('video'))
{
$("#localVideo").removeClass('hidden')[0].srcObject = localStream;
}

log("-- Adding outgoing tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.then(function() {
log("------> Creating answer");
// Now that we've successfully set the remote description, we need to
// start our stream up locally then create an SDP answer. This SDP
// data describes the local end of our call, including the codec
// information, options agreed upon, and so forth.
return myPeerConnection.createAnswer();
})
.then(function(answer) {
log("------> Setting local description after creating answer");
// We now have our answer, so establish that as the local description.
// This actually configures our end of the call to match the settings
// specified in the SDP.
return myPeerConnection.setLocalDescription(answer);
})
.then(function() {
var msg = {
name: myUsername,
target: targetUsername,
type: "video-answer",
sdp: myPeerConnection.localDescription
};

// We've configured our end of the call now. Time to send our
// answer back to the caller so they know that we want to talk
// and how to talk to us.

log("Sending answer packet back to other peer");
sendToServer(msg);
})
.catch(
handleGetUserMediaError);

}

function handleGetUserMediaError(e) {
log(e);
switch(e.name) {
case "NotFoundError":
alert("Unable to open your call because no camera and/or microphone" +
"were found.");
break;
case "SecurityError":
case "PermissionDeniedError":
// Do nothing; this is the same as the user canceling the call.
break;
default:
//the error occur here
alert("Error opening your camera and/or microphone: " + e.message);
console.log("----------");
console.log(e);
break;
}

// Make sure we shut down our end of the RTCPeerConnection so we're
// ready to try again.

closeVideoCall();
}


the invite function:



function invite() {
log("Starting to prepare an invitation");
if (myPeerConnection) {
alert("You can't start a call because you already have one open!");
} else {

var clickedUsername = $("input[name=teacherId]").val();
console.log('user id is '+ clickedUsername);

// Don't allow users to call themselves, because weird.

if (clickedUsername === myUsername) {
alert("I'm afraid I can't let you talk to yourself. That would be weird.");
return;
}

// Record the username being called for future reference

targetUsername = clickedUsername;
log("Inviting user " + targetUsername);

// Call createPeerConnection() to create the RTCPeerConnection.

log("Setting up connection to invite user: " + targetUsername);
createPeerConnection();

// Now configure and create the local stream, attach it to the
// "preview" box (id "video"), and add it to the
// RTCPeerConnection.

log("Requesting webcam access...");

isInviter = true;

navigator.mediaDevices.getUserMedia(mediaConstraints)
.then(function(localStream) {

$("#video-container").removeClass("hidden");

console.log(localStream);
log("-- Local video stream obtained");

if(responserConstraints.hasOwnProperty('video'))
{
var localVideo = $('#localVideo');
localVideo.removeClass('hidden')[0].srcObject = localStream;
localVideo[0].mute;
}
else
{
var videoEl = document.getElementById("video");
videoEl.muted = true;
videoEl.srcObject = localStream;
}


log("-- Adding incoming tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.catch(handleGetUserMediaError);
}
}


the console response is the following:



    [3:28:31 PM] *** ICE gathering state changed to: gathering
opensocket.js:66 [3:28:31 PM] Outgoing ICE candidate: candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10
opensocket.js:66 [3:28:31 PM] Sending 'new-ice-candidate' message: {"type":"new-ice-candidate","candidate":{"candidate":"candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10","sdpMid":"audio","sdpMLineIndex":0,"usernameFragment":"76SW"},"hash":"m0wk8Kaz8JFejuJGte7kAmNtYDiWPZNBGl7fKA5b"}
opensocket.js:66 [3:28:31 PM] -- Local video stream obtained
opensocket.js:66 [3:28:31 PM] -- Adding outgoing tracks to the RTCPeerConnection
opensocket.js:66 [3:28:31 PM] ------> Creating answer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:66 [3:28:31 PM] InvalidStateError: Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer.


I can't find a way to solve it !, the error only occur in chrome !



Any help, please ?



Edit: This is my handleNegotiationNeededEvent function:



function handleNegotiationNeededEvent() {
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}









share|improve this question















marked as duplicate by jib javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Jan 3 at 14:41


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • 1





    Where's your createOffer? Also, are you relying on negotiationneeded by any chance?

    – jib
    Jan 3 at 1:37











  • @jib sorry, I edit the question and added the handleNegotiationNeededEvent which fired onnegotiationneeded

    – shamaseen
    Jan 3 at 6:41
















2
















This question already has an answer here:




  • How to set remote description for a WebRTC caller in Chrome without errors?

    1 answer




I'm implementing WebRTC peer-to-peer call, it is working well in all browser except if chrome is the call initializer (who invoke invite function).



if chrome is the call initializer, the ICE connection state change to connected and the video appear in the other peer,then an error "DOMException: "Cannot create answer in state stable"' happen and the video stop transfer to the other peer.



if the receiver is also chrome, the error says "Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer."



these are the handleVideoOfferMsg function and handleGetUserMediaError function (which trigger the error) code:



function handleVideoOfferMsg(msg) {
// debugger;
// $("#ring")[0].play();

var localStream = null;

targetUsername = msg.from;

// Call createPeerConnection() to create the RTCPeerConnection.

log("Starting to accept invitation from " + targetUsername);
createPeerConnection();

// We need to set the remote description to the received SDP offer
// so that our local WebRTC layer knows how to talk to the caller.

var desc = new RTCSessionDescription(msg.sdp);

myPeerConnection.setRemoteDescription(desc).then(function () {

log("Setting up the local media stream...");
return navigator.mediaDevices.getUserMedia(responserConstraints);
})
.then(function(stream) {

$("#video-container").removeClass("hidden");
log("-- Local video stream obtained");
localStream = stream;
if(responserConstraints.hasOwnProperty('video'))
{
$("#localVideo").removeClass('hidden')[0].srcObject = localStream;
}

log("-- Adding outgoing tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.then(function() {
log("------> Creating answer");
// Now that we've successfully set the remote description, we need to
// start our stream up locally then create an SDP answer. This SDP
// data describes the local end of our call, including the codec
// information, options agreed upon, and so forth.
return myPeerConnection.createAnswer();
})
.then(function(answer) {
log("------> Setting local description after creating answer");
// We now have our answer, so establish that as the local description.
// This actually configures our end of the call to match the settings
// specified in the SDP.
return myPeerConnection.setLocalDescription(answer);
})
.then(function() {
var msg = {
name: myUsername,
target: targetUsername,
type: "video-answer",
sdp: myPeerConnection.localDescription
};

// We've configured our end of the call now. Time to send our
// answer back to the caller so they know that we want to talk
// and how to talk to us.

log("Sending answer packet back to other peer");
sendToServer(msg);
})
.catch(
handleGetUserMediaError);

}

function handleGetUserMediaError(e) {
log(e);
switch(e.name) {
case "NotFoundError":
alert("Unable to open your call because no camera and/or microphone" +
"were found.");
break;
case "SecurityError":
case "PermissionDeniedError":
// Do nothing; this is the same as the user canceling the call.
break;
default:
//the error occur here
alert("Error opening your camera and/or microphone: " + e.message);
console.log("----------");
console.log(e);
break;
}

// Make sure we shut down our end of the RTCPeerConnection so we're
// ready to try again.

closeVideoCall();
}


the invite function:



function invite() {
log("Starting to prepare an invitation");
if (myPeerConnection) {
alert("You can't start a call because you already have one open!");
} else {

var clickedUsername = $("input[name=teacherId]").val();
console.log('user id is '+ clickedUsername);

// Don't allow users to call themselves, because weird.

if (clickedUsername === myUsername) {
alert("I'm afraid I can't let you talk to yourself. That would be weird.");
return;
}

// Record the username being called for future reference

targetUsername = clickedUsername;
log("Inviting user " + targetUsername);

// Call createPeerConnection() to create the RTCPeerConnection.

log("Setting up connection to invite user: " + targetUsername);
createPeerConnection();

// Now configure and create the local stream, attach it to the
// "preview" box (id "video"), and add it to the
// RTCPeerConnection.

log("Requesting webcam access...");

isInviter = true;

navigator.mediaDevices.getUserMedia(mediaConstraints)
.then(function(localStream) {

$("#video-container").removeClass("hidden");

console.log(localStream);
log("-- Local video stream obtained");

if(responserConstraints.hasOwnProperty('video'))
{
var localVideo = $('#localVideo');
localVideo.removeClass('hidden')[0].srcObject = localStream;
localVideo[0].mute;
}
else
{
var videoEl = document.getElementById("video");
videoEl.muted = true;
videoEl.srcObject = localStream;
}


log("-- Adding incoming tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.catch(handleGetUserMediaError);
}
}


the console response is the following:



    [3:28:31 PM] *** ICE gathering state changed to: gathering
opensocket.js:66 [3:28:31 PM] Outgoing ICE candidate: candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10
opensocket.js:66 [3:28:31 PM] Sending 'new-ice-candidate' message: {"type":"new-ice-candidate","candidate":{"candidate":"candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10","sdpMid":"audio","sdpMLineIndex":0,"usernameFragment":"76SW"},"hash":"m0wk8Kaz8JFejuJGte7kAmNtYDiWPZNBGl7fKA5b"}
opensocket.js:66 [3:28:31 PM] -- Local video stream obtained
opensocket.js:66 [3:28:31 PM] -- Adding outgoing tracks to the RTCPeerConnection
opensocket.js:66 [3:28:31 PM] ------> Creating answer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:66 [3:28:31 PM] InvalidStateError: Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer.


I can't find a way to solve it !, the error only occur in chrome !



Any help, please ?



Edit: This is my handleNegotiationNeededEvent function:



function handleNegotiationNeededEvent() {
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}









share|improve this question















marked as duplicate by jib javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Jan 3 at 14:41


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • 1





    Where's your createOffer? Also, are you relying on negotiationneeded by any chance?

    – jib
    Jan 3 at 1:37











  • @jib sorry, I edit the question and added the handleNegotiationNeededEvent which fired onnegotiationneeded

    – shamaseen
    Jan 3 at 6:41














2












2








2


1







This question already has an answer here:




  • How to set remote description for a WebRTC caller in Chrome without errors?

    1 answer




I'm implementing WebRTC peer-to-peer call, it is working well in all browser except if chrome is the call initializer (who invoke invite function).



if chrome is the call initializer, the ICE connection state change to connected and the video appear in the other peer,then an error "DOMException: "Cannot create answer in state stable"' happen and the video stop transfer to the other peer.



if the receiver is also chrome, the error says "Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer."



these are the handleVideoOfferMsg function and handleGetUserMediaError function (which trigger the error) code:



function handleVideoOfferMsg(msg) {
// debugger;
// $("#ring")[0].play();

var localStream = null;

targetUsername = msg.from;

// Call createPeerConnection() to create the RTCPeerConnection.

log("Starting to accept invitation from " + targetUsername);
createPeerConnection();

// We need to set the remote description to the received SDP offer
// so that our local WebRTC layer knows how to talk to the caller.

var desc = new RTCSessionDescription(msg.sdp);

myPeerConnection.setRemoteDescription(desc).then(function () {

log("Setting up the local media stream...");
return navigator.mediaDevices.getUserMedia(responserConstraints);
})
.then(function(stream) {

$("#video-container").removeClass("hidden");
log("-- Local video stream obtained");
localStream = stream;
if(responserConstraints.hasOwnProperty('video'))
{
$("#localVideo").removeClass('hidden')[0].srcObject = localStream;
}

log("-- Adding outgoing tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.then(function() {
log("------> Creating answer");
// Now that we've successfully set the remote description, we need to
// start our stream up locally then create an SDP answer. This SDP
// data describes the local end of our call, including the codec
// information, options agreed upon, and so forth.
return myPeerConnection.createAnswer();
})
.then(function(answer) {
log("------> Setting local description after creating answer");
// We now have our answer, so establish that as the local description.
// This actually configures our end of the call to match the settings
// specified in the SDP.
return myPeerConnection.setLocalDescription(answer);
})
.then(function() {
var msg = {
name: myUsername,
target: targetUsername,
type: "video-answer",
sdp: myPeerConnection.localDescription
};

// We've configured our end of the call now. Time to send our
// answer back to the caller so they know that we want to talk
// and how to talk to us.

log("Sending answer packet back to other peer");
sendToServer(msg);
})
.catch(
handleGetUserMediaError);

}

function handleGetUserMediaError(e) {
log(e);
switch(e.name) {
case "NotFoundError":
alert("Unable to open your call because no camera and/or microphone" +
"were found.");
break;
case "SecurityError":
case "PermissionDeniedError":
// Do nothing; this is the same as the user canceling the call.
break;
default:
//the error occur here
alert("Error opening your camera and/or microphone: " + e.message);
console.log("----------");
console.log(e);
break;
}

// Make sure we shut down our end of the RTCPeerConnection so we're
// ready to try again.

closeVideoCall();
}


the invite function:



function invite() {
log("Starting to prepare an invitation");
if (myPeerConnection) {
alert("You can't start a call because you already have one open!");
} else {

var clickedUsername = $("input[name=teacherId]").val();
console.log('user id is '+ clickedUsername);

// Don't allow users to call themselves, because weird.

if (clickedUsername === myUsername) {
alert("I'm afraid I can't let you talk to yourself. That would be weird.");
return;
}

// Record the username being called for future reference

targetUsername = clickedUsername;
log("Inviting user " + targetUsername);

// Call createPeerConnection() to create the RTCPeerConnection.

log("Setting up connection to invite user: " + targetUsername);
createPeerConnection();

// Now configure and create the local stream, attach it to the
// "preview" box (id "video"), and add it to the
// RTCPeerConnection.

log("Requesting webcam access...");

isInviter = true;

navigator.mediaDevices.getUserMedia(mediaConstraints)
.then(function(localStream) {

$("#video-container").removeClass("hidden");

console.log(localStream);
log("-- Local video stream obtained");

if(responserConstraints.hasOwnProperty('video'))
{
var localVideo = $('#localVideo');
localVideo.removeClass('hidden')[0].srcObject = localStream;
localVideo[0].mute;
}
else
{
var videoEl = document.getElementById("video");
videoEl.muted = true;
videoEl.srcObject = localStream;
}


log("-- Adding incoming tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.catch(handleGetUserMediaError);
}
}


the console response is the following:



    [3:28:31 PM] *** ICE gathering state changed to: gathering
opensocket.js:66 [3:28:31 PM] Outgoing ICE candidate: candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10
opensocket.js:66 [3:28:31 PM] Sending 'new-ice-candidate' message: {"type":"new-ice-candidate","candidate":{"candidate":"candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10","sdpMid":"audio","sdpMLineIndex":0,"usernameFragment":"76SW"},"hash":"m0wk8Kaz8JFejuJGte7kAmNtYDiWPZNBGl7fKA5b"}
opensocket.js:66 [3:28:31 PM] -- Local video stream obtained
opensocket.js:66 [3:28:31 PM] -- Adding outgoing tracks to the RTCPeerConnection
opensocket.js:66 [3:28:31 PM] ------> Creating answer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:66 [3:28:31 PM] InvalidStateError: Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer.


I can't find a way to solve it !, the error only occur in chrome !



Any help, please ?



Edit: This is my handleNegotiationNeededEvent function:



function handleNegotiationNeededEvent() {
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}









share|improve this question

















This question already has an answer here:




  • How to set remote description for a WebRTC caller in Chrome without errors?

    1 answer




I'm implementing WebRTC peer-to-peer call, it is working well in all browser except if chrome is the call initializer (who invoke invite function).



if chrome is the call initializer, the ICE connection state change to connected and the video appear in the other peer,then an error "DOMException: "Cannot create answer in state stable"' happen and the video stop transfer to the other peer.



if the receiver is also chrome, the error says "Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer."



these are the handleVideoOfferMsg function and handleGetUserMediaError function (which trigger the error) code:



function handleVideoOfferMsg(msg) {
// debugger;
// $("#ring")[0].play();

var localStream = null;

targetUsername = msg.from;

// Call createPeerConnection() to create the RTCPeerConnection.

log("Starting to accept invitation from " + targetUsername);
createPeerConnection();

// We need to set the remote description to the received SDP offer
// so that our local WebRTC layer knows how to talk to the caller.

var desc = new RTCSessionDescription(msg.sdp);

myPeerConnection.setRemoteDescription(desc).then(function () {

log("Setting up the local media stream...");
return navigator.mediaDevices.getUserMedia(responserConstraints);
})
.then(function(stream) {

$("#video-container").removeClass("hidden");
log("-- Local video stream obtained");
localStream = stream;
if(responserConstraints.hasOwnProperty('video'))
{
$("#localVideo").removeClass('hidden')[0].srcObject = localStream;
}

log("-- Adding outgoing tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.then(function() {
log("------> Creating answer");
// Now that we've successfully set the remote description, we need to
// start our stream up locally then create an SDP answer. This SDP
// data describes the local end of our call, including the codec
// information, options agreed upon, and so forth.
return myPeerConnection.createAnswer();
})
.then(function(answer) {
log("------> Setting local description after creating answer");
// We now have our answer, so establish that as the local description.
// This actually configures our end of the call to match the settings
// specified in the SDP.
return myPeerConnection.setLocalDescription(answer);
})
.then(function() {
var msg = {
name: myUsername,
target: targetUsername,
type: "video-answer",
sdp: myPeerConnection.localDescription
};

// We've configured our end of the call now. Time to send our
// answer back to the caller so they know that we want to talk
// and how to talk to us.

log("Sending answer packet back to other peer");
sendToServer(msg);
})
.catch(
handleGetUserMediaError);

}

function handleGetUserMediaError(e) {
log(e);
switch(e.name) {
case "NotFoundError":
alert("Unable to open your call because no camera and/or microphone" +
"were found.");
break;
case "SecurityError":
case "PermissionDeniedError":
// Do nothing; this is the same as the user canceling the call.
break;
default:
//the error occur here
alert("Error opening your camera and/or microphone: " + e.message);
console.log("----------");
console.log(e);
break;
}

// Make sure we shut down our end of the RTCPeerConnection so we're
// ready to try again.

closeVideoCall();
}


the invite function:



function invite() {
log("Starting to prepare an invitation");
if (myPeerConnection) {
alert("You can't start a call because you already have one open!");
} else {

var clickedUsername = $("input[name=teacherId]").val();
console.log('user id is '+ clickedUsername);

// Don't allow users to call themselves, because weird.

if (clickedUsername === myUsername) {
alert("I'm afraid I can't let you talk to yourself. That would be weird.");
return;
}

// Record the username being called for future reference

targetUsername = clickedUsername;
log("Inviting user " + targetUsername);

// Call createPeerConnection() to create the RTCPeerConnection.

log("Setting up connection to invite user: " + targetUsername);
createPeerConnection();

// Now configure and create the local stream, attach it to the
// "preview" box (id "video"), and add it to the
// RTCPeerConnection.

log("Requesting webcam access...");

isInviter = true;

navigator.mediaDevices.getUserMedia(mediaConstraints)
.then(function(localStream) {

$("#video-container").removeClass("hidden");

console.log(localStream);
log("-- Local video stream obtained");

if(responserConstraints.hasOwnProperty('video'))
{
var localVideo = $('#localVideo');
localVideo.removeClass('hidden')[0].srcObject = localStream;
localVideo[0].mute;
}
else
{
var videoEl = document.getElementById("video");
videoEl.muted = true;
videoEl.srcObject = localStream;
}


log("-- Adding incoming tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.catch(handleGetUserMediaError);
}
}


the console response is the following:



    [3:28:31 PM] *** ICE gathering state changed to: gathering
opensocket.js:66 [3:28:31 PM] Outgoing ICE candidate: candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10
opensocket.js:66 [3:28:31 PM] Sending 'new-ice-candidate' message: {"type":"new-ice-candidate","candidate":{"candidate":"candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10","sdpMid":"audio","sdpMLineIndex":0,"usernameFragment":"76SW"},"hash":"m0wk8Kaz8JFejuJGte7kAmNtYDiWPZNBGl7fKA5b"}
opensocket.js:66 [3:28:31 PM] -- Local video stream obtained
opensocket.js:66 [3:28:31 PM] -- Adding outgoing tracks to the RTCPeerConnection
opensocket.js:66 [3:28:31 PM] ------> Creating answer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:66 [3:28:31 PM] InvalidStateError: Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer.


I can't find a way to solve it !, the error only occur in chrome !



Any help, please ?



Edit: This is my handleNegotiationNeededEvent function:



function handleNegotiationNeededEvent() {
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}




This question already has an answer here:




  • How to set remote description for a WebRTC caller in Chrome without errors?

    1 answer








javascript stream video-streaming webrtc






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 6:40







shamaseen

















asked Jan 2 at 13:33









shamaseenshamaseen

311315




311315




marked as duplicate by jib javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Jan 3 at 14:41


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









marked as duplicate by jib javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Jan 3 at 14:41


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.










  • 1





    Where's your createOffer? Also, are you relying on negotiationneeded by any chance?

    – jib
    Jan 3 at 1:37











  • @jib sorry, I edit the question and added the handleNegotiationNeededEvent which fired onnegotiationneeded

    – shamaseen
    Jan 3 at 6:41














  • 1





    Where's your createOffer? Also, are you relying on negotiationneeded by any chance?

    – jib
    Jan 3 at 1:37











  • @jib sorry, I edit the question and added the handleNegotiationNeededEvent which fired onnegotiationneeded

    – shamaseen
    Jan 3 at 6:41








1




1





Where's your createOffer? Also, are you relying on negotiationneeded by any chance?

– jib
Jan 3 at 1:37





Where's your createOffer? Also, are you relying on negotiationneeded by any chance?

– jib
Jan 3 at 1:37













@jib sorry, I edit the question and added the handleNegotiationNeededEvent which fired onnegotiationneeded

– shamaseen
Jan 3 at 6:41





@jib sorry, I edit the question and added the handleNegotiationNeededEvent which fired onnegotiationneeded

– shamaseen
Jan 3 at 6:41












1 Answer
1






active

oldest

votes


















0














Ok I found a solution and it was really strange !



It look like chrome is firing onnegotiationneeded twice !
I don't know why chrome is doing such weird behavior !



so createOffer is fired twice because of that, as the log show:



opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer


so my solution was to change the handleNegotiationNeededEvent as the following:



var Negotiation = 0;
function handleNegotiationNeededEvent() {
if(Negotiation === 0 )
{
Negotiation++;
}
else
{
return;
}
// if (myPeerConnection.signalingState === "stable") return;
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}


it look like strange to me, but at least it is working now.






share|improve this answer
























  • negotiationneeded is somewhat buggy in Chrome: bugs.chromium.org/p/chromium/issues/detail?id=740501

    – Philipp Hancke
    Jan 3 at 8:14


















1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Ok I found a solution and it was really strange !



It look like chrome is firing onnegotiationneeded twice !
I don't know why chrome is doing such weird behavior !



so createOffer is fired twice because of that, as the log show:



opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer


so my solution was to change the handleNegotiationNeededEvent as the following:



var Negotiation = 0;
function handleNegotiationNeededEvent() {
if(Negotiation === 0 )
{
Negotiation++;
}
else
{
return;
}
// if (myPeerConnection.signalingState === "stable") return;
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}


it look like strange to me, but at least it is working now.






share|improve this answer
























  • negotiationneeded is somewhat buggy in Chrome: bugs.chromium.org/p/chromium/issues/detail?id=740501

    – Philipp Hancke
    Jan 3 at 8:14
















0














Ok I found a solution and it was really strange !



It look like chrome is firing onnegotiationneeded twice !
I don't know why chrome is doing such weird behavior !



so createOffer is fired twice because of that, as the log show:



opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer


so my solution was to change the handleNegotiationNeededEvent as the following:



var Negotiation = 0;
function handleNegotiationNeededEvent() {
if(Negotiation === 0 )
{
Negotiation++;
}
else
{
return;
}
// if (myPeerConnection.signalingState === "stable") return;
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}


it look like strange to me, but at least it is working now.






share|improve this answer
























  • negotiationneeded is somewhat buggy in Chrome: bugs.chromium.org/p/chromium/issues/detail?id=740501

    – Philipp Hancke
    Jan 3 at 8:14














0












0








0







Ok I found a solution and it was really strange !



It look like chrome is firing onnegotiationneeded twice !
I don't know why chrome is doing such weird behavior !



so createOffer is fired twice because of that, as the log show:



opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer


so my solution was to change the handleNegotiationNeededEvent as the following:



var Negotiation = 0;
function handleNegotiationNeededEvent() {
if(Negotiation === 0 )
{
Negotiation++;
}
else
{
return;
}
// if (myPeerConnection.signalingState === "stable") return;
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}


it look like strange to me, but at least it is working now.






share|improve this answer













Ok I found a solution and it was really strange !



It look like chrome is firing onnegotiationneeded twice !
I don't know why chrome is doing such weird behavior !



so createOffer is fired twice because of that, as the log show:



opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer


so my solution was to change the handleNegotiationNeededEvent as the following:



var Negotiation = 0;
function handleNegotiationNeededEvent() {
if(Negotiation === 0 )
{
Negotiation++;
}
else
{
return;
}
// if (myPeerConnection.signalingState === "stable") return;
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");

log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}


it look like strange to me, but at least it is working now.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 3 at 6:47









shamaseenshamaseen

311315




311315













  • negotiationneeded is somewhat buggy in Chrome: bugs.chromium.org/p/chromium/issues/detail?id=740501

    – Philipp Hancke
    Jan 3 at 8:14



















  • negotiationneeded is somewhat buggy in Chrome: bugs.chromium.org/p/chromium/issues/detail?id=740501

    – Philipp Hancke
    Jan 3 at 8:14

















negotiationneeded is somewhat buggy in Chrome: bugs.chromium.org/p/chromium/issues/detail?id=740501

– Philipp Hancke
Jan 3 at 8:14





negotiationneeded is somewhat buggy in Chrome: bugs.chromium.org/p/chromium/issues/detail?id=740501

– Philipp Hancke
Jan 3 at 8:14





Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

A Topological Invariant for $pi_3(U(n))$