问题
I have created video chat app using webRTC and Django channel.My app working 90% of time properly when using it in the same network but fail when using it on a different network.I am not able to see a video of remote person when using it on a different network.
I used chrome://webrtc-internals/ to trace my webRTC response and I got iceconnectionstate : failed when called using different network
Below screenshot is taken when I got success in the same network
And after success also it gave addIceCandidateFailed error on the same network but video calling works properly and this error comes only in chrome but not in firefox. Below is the screenshot
Below is my STUN/TUNE server configuration which is free.I got this from one of the StackOverflow links.
var peerConnectionConfig = {
iceServers: [{
urls: ["turn:173.194.72.127:19305?transport=udp",
"turn:[2404:6800:4008:C01::7F]:19305?transport=udp",
"turn:173.194.72.127:443?transport=tcp",
"turn:[2404:6800:4008:C01::7F]:443?transport=tcp"
],
username: "CKjCuLwFEgahxNRjuTAYzc/s6OMT",
credential: "u1SQDR/SQsPQIxXNWQT7czc/G4c="
},
{
urls: ["stun:stun.l.google.com:19302"]
}
]
};
Below is my webRTC javascript code
$(function() {
var initiator,pc;
var isSender = false;
var peerConnectionConfig = {
iceServers: [{
urls: ["turn:173.194.XX.127:19305?transport=udp",
"turn:[2404:XXXX:XXXX:C01::7F]:19305?transport=udp",
"turn:173.194.XX.127:443?transport=tcp",
"turn:[2404:XXXX:XXXX:C01::7F]:443?transport=tcp"
],
username: "XXXXXXXXXX",
credential: "YYYYYYYYYYY"
},
{
urls: ["stun:stun.l.google.com:19302"]
}
]
};
$.ajax({
type: "GET",
url: '/isRoomExist/?roomName=121' ,
beforeSend: function() {},
success: function(data) {
data = JSON.parse(data);
initiatorCtrl(data[0].flgInitiator);
}
});
var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
var chatsock = new ReconnectingWebSocket(ws_scheme + '://' + window.location.host + "/chat" + window.location.pathname);
function initiatorCtrl(event) {
if (event == "fullhouse") {
alert("full house");
}
if (event == "initiator") {
initiator = false;
init();
}
if (event == "not initiator") {
initiator = true;
init();
}
}
function init() {
var constraints = {
audio: true,
video: true
};
getUserMedia(constraints, connect, fail);
}
function connect(stream) {
pc = new RTCPeerConnection(peerConnectionConfig);
if (stream) {
pc.addStream(stream);
$('#local').attachStream(stream);
}
pc.onaddstream = function(event) {
$('#remote').attachStream(event.stream);
logStreaming(true);
};
pc.onicecandidate = function(event) {
if (event.candidate) {
chatsock.send(JSON.stringify(event.candidate));
isSender = true;
}
};
if (initiator) {
createOffer();
} else {
log('waiting for offer...');
}
logStreaming(false);
chatsock.onmessage = function(event) {
var signal1 = JSON.parse(event.data);
var signal = JSON.parse(signal1);
if (isSender) {
isSender = false
} else {
if (signal.sdp) {
if (initiator) {
receiveAnswer(signal);
} else {
receiveOffer(signal);
}
} else if (signal.candidate) {
pc.addIceCandidate(new RTCIceCandidate(signal));
}
}
};
}
function createOffer() {
pc.createOffer(function(offer) {
pc.setLocalDescription(offer, function() {
chatsock.send(JSON.stringify(offer));
isSender = true;
}, fail);
}, fail);
}
function receiveOffer(offer) {
pc.setRemoteDescription(new RTCSessionDescription(offer), function() {
pc.createAnswer(function(answer) {
pc.setLocalDescription(answer, function() {
chatsock.send(JSON.stringify(answer));
isSender = true;
}, fail);
}, fail);
}, fail);
}
function receiveAnswer(answer) {
pc.setRemoteDescription(new RTCSessionDescription(answer));
}
function log() {
console.log(Array.prototype.join.call(arguments, ' '))
console.log.apply(console, arguments);
}
function logStreaming(streaming) {
$('#streaming').text(streaming ? '[streaming]' : '[..]');
}
function fail() {
console.error.apply(console, arguments);
}
jQuery.fn.attachStream = function(stream) {
this.each(function() {
this.src = URL.createObjectURL(stream);
this.play();
});
};
});
回答1:
As per your webrtc-internals, you are adding the remote candidates before setting the remote description.
Put the candidate's in a queue, until you receive the remote description.
After setting the remote description,
you can send local candidates to remote user from queue or from onicecandidate
and add the remote candidates to your pc.
Update:
The order of messages is in general not the same as the POST order
from the other client because the POSTs are async and the server may handle
candidates faster(just relay & smaller size) than offer/answer(need to handle routing/cdr/forking).
Queuing Remote Candidates: We need to process remote offer before adding the candidates.
Queuing Local Candidates: If call/offer is forked to multiple destinations(user logged in mobile's & browser's Or group calling), then only first answer will be accepted by initiator. So all receiving endpoints need to queue local candidates, until their answer got acknowledged.
Reference Example
来源:https://stackoverflow.com/questions/44198962/webrtc-video-audio-calling-failed-90-of-time-on-different-network-but-got-succe