我遇到了这个问题,我有一个在服务器上运行的webapp,有域名和工作,如果我连接到同一个网络中的另一台PC(请记住我的服务器在linode服务器上在线)(对于例如我的家)我没有任何问题,但如果我在家中连接一台笔记本电脑和我工作的其他笔记本电脑(不同的网络),连接不起作用,我尝试每次STUN / TURN信令和我跟numb.viagenie.ca一起用BOTH STUN和TURN服务器。 当我看到:webrtc出现了我的房子和我的笔记本电脑IP和端口的连接,但没有工作,看起来ICE FAILED。 这是我的RTCClient.js(我的webRTC逻辑):
var PeerManager = (function (room, cbMessages) {
var remote = window.document.getElementById('remote');
var localId,
config = {
peerConnectionConfig: {
iceServers: [
/* { 'url': 'stun:stun01.sipphone.com' },
{ 'url': 'stun:stun.ekiga.net' },
{ 'url': 'stun:stun.fwdnet.net' },
{ 'url': 'stun:stun.ideasip.com' },
{ 'url': 'stun:stun.iptel.org' },
{ 'url': 'stun:stun.rixtelecom.se' },
{ 'url': 'stun:stun.schlund.de' },
{ 'url': 'stun:stun.l.google.com:19302' },
{ 'url': 'stun:stun1.l.google.com:19302' },
{ 'url': 'stun:stun2.l.google.com:19302' },
{ 'url': 'stun:stun3.l.google.com:19302' },
{ 'url': 'stun:stun4.l.google.com:19302' },
{ 'url': 'stun:stunserver.org' },
{ 'url': 'stun:stun.softjoys.com' },
{ 'url': 'stun:stun.voiparound.com' },
{ 'url': 'stun:stun.voipbuster.com' },
{ 'url': 'stun:stun.voipstunt.com' },
{ 'url': 'stun:stun.voxgratia.org' },
{ 'url': 'stun:stun.xten.com' },
{ 'url': "stun:stun.services.mozilla.com" },*/
{ 'url': "stun:numb.viagenie.ca" },
{
'url': "turn:numb.viagenie.ca",
'credential': 'xxxxxx',
'username': 'xxxxxxxx'
},
{
'url': "turn:numb.viagenie.ca",
'credential': 'xxxxxxx',
'username': 'xxxxxxxxxxxxxxx'
},
/*{
'url': 'turn:192.158.29.39:3478?transport=udp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
},
{
'url': 'turn:192.158.29.39:3478?transport=tcp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
},*/
]
},
peerConnectionConstraints: {
optional: [
{ "DtlsSrtpKeyAgreement": true }
]
}
},
peerDatabase = {},
localStream,
//remoteVideoContainer = document.getElementById('remoteVideosContainer'),
socket = io('http://xxxxx');
//METODO CON EL QUE AUTOMATICAMENTE SE DISPARA CUANDO SE ESTABLECE LA CONEXION CON EL SERVIDOR
socket.on('connect', function () {
console.log('Se ha establecido la conexion con el servidor');
socket.emit('roomSetup', room);
});
socket.on('id', function (clientId) {
cbMessages('id', clientId);
})
socket.on('message', handleMessage);
socket.on('numberQueue', function (action) {
console.log("Recepcion en rtcClient del numberQueue");
cbMessages('numberQueue', action);
})
socket.on('readytoCall', function (action) {
console.log("Recepcion en rtcClient del readytoCall");
cbMessages('readytoCall', action);
})
socket.on('startSession', function (action) {
console.log('Recepcion en rtcClient del startSession');
cbMessages('startSession', action);
})
socket.on('syncCounters', function (action) {
console.log('Recepcion en rtcClient del syncCounters');
cbMessages('syncCounters', action);
})
socket.on('id', function (id) {
localId = id;
});
function addPeer(remoteId) {
var peer = new Peer(config.peerConnectionConfig, config.peerConnectionConstraints);
peer.pc.onicecandidate = function (event) {
console.log(event);
if (event.candidate) {
send('candidate', remoteId, {
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate
});
}
};
/* peer.pc.ontrack = function (event) {
attachMediaStream(remote, event.streams[0]);
console.log(remote, event.streams[0]);
}*/
peer.pc.onaddstream = function (event) {
attachMediaStream(remote, event.stream); /*peer.remoteVideoEl*/
// remoteVideosContainer.appendChild(peer.remoteVideoEl);
console.log(remote, event.stream);
};
peer.pc.onremovestream = function (event) {
peer.remoteVideoEl.src = '';
remoteVideosContainer.removeChild(peer.remoteVideoEl);
};
peer.pc.oniceconnectionstatechange = function (event) {
switch (
(event.srcElement // Chrome
|| event.target) // Firefox
.iceConnectionState) {
case 'disconnected':
remoteVideosContainer.removeChild(peer.remoteVideoEl);
break;
}
};
peerDatabase[remoteId] = peer;
return peer;
}
function answer(remoteId) {
var pc = peerDatabase[remoteId].pc;
pc.createAnswer(
function (sessionDescription) {
pc.setLocalDescription(sessionDescription);
send('answer', remoteId, sessionDescription);
},
error
);
}
function offer(remoteId) {
var pc = peerDatabase[remoteId].pc;
pc.createOffer(
function (sessionDescription) {
pc.setLocalDescription(sessionDescription);
send('offer', remoteId, sessionDescription);
},
error
);
}
function handleMessage(message) {
var type = message.type,
from = message.from,
pc = (peerDatabase[from] || addPeer(from)).pc;
console.log('received ' + type + ' from ' + from);
switch (type) {
case 'init':
toggleLocalStream(pc);
offer(from);
break;
case 'offer':
pc.setRemoteDescription(new RTCSessionDescription(message.payload), function () { }, error);
answer(from);
break;
case 'answer':
pc.setRemoteDescription(new RTCSessionDescription(message.payload), function () { }, error);
break;
case 'candidate':
if (pc.remoteDescription) {
pc.addIceCandidate(new RTCIceCandidate({
sdpMLineIndex: message.payload.label,
sdpMid: message.payload.id,
candidate: message.payload.candidate
}), function () { }, error);
}
break;
}
}
function send(type, to, payload) {
console.log('sending ' + type + ' to ' + to);
socket.emit('message', {
to: to,
type: type,
payload: payload
});
}
function toggleLocalStream(pc) {
if (localStream) {
(!!pc.getLocalStreams().length) ? pc.removeStream(localStream) : pc.addStream(localStream);
}
}
function error(err) {
console.log(err);
}
return {
getId: function () {
return localId;
},
setLocalStream: function (stream) {
// if local cam has been stopped, remove it from all outgoing streams.
if (!stream) {
for (id in peerDatabase) {
pc = peerDatabase[id].pc;
if (!!pc.getLocalStreams().length) {
pc.removeStream(localStream);
offer(id);
}
}
}
localStream = stream;
},
toggleLocalStream: function (remoteId) {
peer = peerDatabase[remoteId] || addPeer(remoteId);
toggleLocalStream(peer.pc);
},
peerInit: function (remoteId) {
peer = peerDatabase[remoteId] || addPeer(remoteId);
console.log('send init');
send('init', remoteId, null);
},
peerRenegociate: function (remoteId) {
offer(remoteId);
},
send: function (type, payload) {
socket.emit(type, payload);
}
};
});
var Peer = function (pcConfig, pcConstraints) {
this.pc = new RTCPeerConnection(pcConfig, pcConstraints);
this.remoteVideoEl = document.createElement('video');
this.remoteVideoEl.controls = true;
this.remoteVideoEl.autoplay = true;
}
这是我的Adapter.js
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree.
*/
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree.
*/
'use strict';
var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;
function maybeFixConfiguration(pcConfig) {
if (!pcConfig) {
return;
}
for (var i = 0; i < pcConfig.iceServers.length; i++) {
if (pcConfig.iceServers[i].hasOwnProperty('urls')) {
pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls;
delete pcConfig.iceServers[i].urls;
}
}
}
if (navigator.mozGetUserMedia) {
console.log('This appears to be Firefox');
window.webrtcDetectedBrowser = 'firefox';
window.webrtcDetectedVersion =
parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
// The RTCPeerConnection object.
RTCPeerConnection = function (pcConfig, pcConstraints) {
// .urls is not supported in FF yet.
maybeFixConfiguration(pcConfig);
return new mozRTCPeerConnection(pcConfig, pcConstraints);
};
// The RTCSessionDescription object.
RTCSessionDescription = mozRTCSessionDescription;
// The RTCIceCandidate object.
RTCIceCandidate = mozRTCIceCandidate;
// Get UserMedia (only difference is the prefix).
// Code from Adam Barth.
window.getUserMedia = navigator.mozGetUserMedia.bind(navigator);
navigator.getUserMedia = getUserMedia;
// Creates iceServer from the url for FF.
window.createIceServer = function (url, username, password) {
var iceServer = null;
var urlParts = url.split(':');
if (urlParts[0].indexOf('stun') === 0) {
// Create iceServer with stun url.
iceServer = {
'url': url
};
} else if (urlParts[0].indexOf('turn') === 0) {
if (webrtcDetectedVersion < 27) {
// Create iceServer with turn url.
// Ignore the transport parameter from TURN url for FF version <=27.
var turnUrlParts = url.split('?');
// Return null for createIceServer if transport=tcp.
if (turnUrlParts.length === 1 ||
turnUrlParts[1].indexOf('transport=udp') === 0) {
iceServer = {
'url': turnUrlParts[0],
'credential': password,
'username': username
};
}
} else {
// FF 27 and above supports transport parameters in TURN url,
// So passing in the full url to create iceServer.
iceServer = {
'url': url,
'credential': password,
'username': username
};
}
}
return iceServer;
};
window.createIceServers = function (urls, username, password) {
var iceServers = [];
// Use .url for FireFox.
for (var i = 0; i < urls.length; i++) {
var iceServer = createIceServer(urls[i],
username,
password);
if (iceServer !== null) {
iceServers.push(iceServer);
}
}
return iceServers;
};
// Attach a media stream to an element.
window.attachMediaStream = function (element, stream) {
console.log('Attaching media stream');
element.mozSrcObject = stream;
element.play();
};
window.reattachMediaStream = function (to, from) {
console.log('Reattaching media stream');
to.mozSrcObject = from.mozSrcObject;
to.play();
};
} else if (navigator.webkitGetUserMedia) {
console.log('This appears to be Chrome');
window.webrtcDetectedBrowser = 'chrome';
// Temporary fix until crbug/374263 is fixed.
// Setting Chrome version to 999, if version is unavailable.
var result = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
if (result !== null) {
window.webrtcDetectedVersion = parseInt(result[2], 10);
} else {
window.webrtcDetectedVersion = 999;
}
// Creates iceServer from the url for Chrome M33 and earlier.
window.createIceServer = function (url, username, password) {
var iceServer = null;
var urlParts = url.split(':');
if (urlParts[0].indexOf('stun') === 0) {
// Create iceServer with stun url.
iceServer = {
'url': url
};
} else if (urlParts[0].indexOf('turn') === 0) {
// Chrome M28 & above uses below TURN format.
iceServer = {
'url': url,
'credential': password,
'username': username
};
}
return iceServer;
};
// Creates iceServers from the urls for Chrome M34 and above.
window.createIceServers = function (urls, username, password) {
var iceServers = [];
if (webrtcDetectedVersion >= 34) {
// .urls is supported since Chrome M34.
iceServers = {
'urls': urls,
'credential': password,
'username': username
};
} else {
for (var i = 0; i < urls.length; i++) {
var iceServer = createIceServer(urls[i],
username,
password);
if (iceServer !== null) {
iceServers.push(iceServer);
}
}
}
return iceServers;
};
// The RTCPeerConnection object.
RTCPeerConnection = function (pcConfig, pcConstraints) {
// .urls is supported since Chrome M34.
if (webrtcDetectedVersion < 34) {
maybeFixConfiguration(pcConfig);
}
return new webkitRTCPeerConnection(pcConfig, pcConstraints);
};
// Get UserMedia (only difference is the prefix).
// Code from Adam Barth.
window.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
navigator.getUserMedia = getUserMedia;
// Attach a media stream to an element.
window.attachMediaStream = function (element, stream) {
if (typeof element.srcObject !== 'undefined') {
element.srcObject = stream;
} else if (typeof element.mozSrcObject !== 'undefined') {
element.mozSrcObject = stream;
} else if (typeof element.src !== 'undefined') {
element.src = URL.createObjectURL(stream);
} else {
console.log('Error attaching stream to element.');
}
};
window.reattachMediaStream = function (to, from) {
to.src = from.src;
};
} else {
console.log('Browser does not appear to be WebRTC-capable');
}
// Returns the result of getUserMedia as a Promise.
function requestUserMedia(constraints) {
return new Promise(function (resolve, reject) {
var onSuccess = function (stream) {
resolve(stream);
};
var onError = function (error) {
reject(error);
};
try {
getUserMedia(constraints, onSuccess, onError);
} catch (e) {
reject(e);
}
});
}
if (typeof module !== 'undefined') {
module.exports = {
RTCPeerConnection: RTCPeerConnection,
getUserMedia: getUserMedia,
attachMediaStream: attachMediaStream,
reattachMediaStream: reattachMediaStream,
webrtcDetectedBrowser: webrtcDetectedBrowser,
webrtcDetectedVersion: webrtcDetectedVersion
//requestUserMedia: not exposed on purpose.
//trace: not exposed on purpose.
};
}
SDP
SDP local
v=0
o=mozilla...THIS_IS_SDPARTA-52.0.2 4443962319420549785 0 IN IP4 0.0.0.0
s=-
t=0 0
a=sendrecv
a=fingerprint:sha-256 A0:E0:C7:7E:3A:3B:4E:88:14:A9:D4:1F:A6:08:0B:C6:97:05:BC:33:4B:A5:CE:F8:CC:20:79:B1:BC:96:AF:17
a=group:BUNDLE sdparta_0 sdparta_1
a=ice-options:trickle
a=msid-semantic:WMS *
m=audio 62832 UDP/TLS/RTP/SAVPF 109 101
c=IN IP4 190.117.88.12
a=candidate:0 1 UDP 2122252543 ::38c8:a270:c7ff:d856 62830 typ host
a=candidate:6 1 UDP 2122187007 ::b43e:ec0d:7743:c6 62831 typ host
a=candidate:12 1 UDP 2122121471 192.168.0.38 62832 typ host
a=candidate:13 1 UDP 1685921791 190.117.88.12 62832 typ srflx raddr 192.168.0.38 rport 62832
a=sendrecv
a=end-of-candidates
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
a=fmtp:101 0-15
a=ice-pwd:51e616b53508d2921fdde4894fe81529
a=ice-ufrag:9bfab4a4
a=mid:sdparta_0
a=msid:{2d638fea-7857-49cb-80a8-985d96460b21} {b82b166d-9a6e-4fc5-a10e-bb597ce567f6}
a=rtcp-mux
a=rtpmap:109 opus/48000/2
a=rtpmap:101 telephone-event/8000
a=setup:active
a=ssrc:2090540075 cname:{794f53ca-9dd9-43f0-8d17-babc96ab5d2d}
m=video 62832 UDP/TLS/RTP/SAVPF 120
c=IN IP4 190.117.88.12
a=sendrecv
a=fmtp:120 max-fs=12288;max-fr=60
a=ice-pwd:51e616b53508d2921fdde4894fe81529
a=ice-ufrag:9bfab4a4
a=mid:sdparta_1
a=msid:{2d638fea-7857-49cb-80a8-985d96460b21} {16b00fa2-9fbd-48ed-acd7-f14d80f4fa5d}
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:120 goog-remb
a=rtcp-mux
a=rtpmap:120 VP8/90000
a=setup:active
a=ssrc:2849290137 cname:{794f53ca-9dd9-43f0-8d17-babc96ab5d2d}
SDP remoto
v=0
o=mozilla...THIS_IS_SDPARTA-52.0.2 4028535757436800601 0 IN IP4 0.0.0.0
s=-
t=0 0
a=sendrecv
a=fingerprint:sha-256 E6:53:BD:DC:C0:74:F0:DE:2B:53:60:BF:41:45:F3:6D:61:64:82:FC:C4:61:0E:52:11:1F:A3:17:EF:58:4C:81
a=group:BUNDLE sdparta_0 sdparta_1
a=ice-options:trickle
a=msid-semantic:WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101
c=IN IP4 0.0.0.0
a=candidate:0 1 UDP 2122252543 192.168.1.101 62841 typ host
a=candidate:0 2 UDP 2122252542 192.168.1.101 62842 typ host
a=candidate:1 1 UDP 1686052863 181.66.165.192 5654 typ srflx raddr 192.168.1.101 rport 62841
a=candidate:1 2 UDP 1686052862 181.66.165.192 5655 typ srflx raddr 192.168.1.101 rport 62842
a=sendrecv
a=extmap:1/sendonly urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
a=fmtp:101 0-15
a=ice-pwd:84d2a654605c91ba448fc90003f8c79e
a=ice-ufrag:0628a660
a=mid:sdparta_0
a=msid:{e08aacff-06fd-4f6d-ba42-408b4948501d} {209331a1-d401-4dea-8667-cf81750a5a63}
a=rtcp-mux
a=rtpmap:109 opus/48000/2
a=rtpmap:9 G722/8000/1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=setup:actpass
a=ssrc:1248822540 cname:{f918048b-0188-438e-b0bb-a223d8d4ae07}
m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97
c=IN IP4 0.0.0.0
a=candidate:0 1 UDP 2122252543 192.168.1.101 62843 typ host
a=candidate:0 2 UDP 2122252542 192.168.1.101 62844 typ host
a=candidate:1 1 UDP 1686052863 181.66.165.192 5656 typ srflx raddr 192.168.1.101 rport 62843
a=candidate:1 2 UDP 1686052862 181.66.165.192 5657 typ srflx raddr 192.168.1.101 rport 62844
a=sendrecv
a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
a=fmtp:120 max-fs=12288;max-fr=60
a=fmtp:121 max-fs=12288;max-fr=60
a=ice-pwd:84d2a654605c91ba448fc90003f8c79e
a=ice-ufrag:0628a660
a=mid:sdparta_1
a=msid:{e08aacff-06fd-4f6d-ba42-408b4948501d} {7a9fa748-c382-4134-a3d4-b7e48afa95fa}
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:120 goog-remb
a=rtcp-fb:121 nack
a=rtcp-fb:121 nack pli
a=rtcp-fb:121 ccm fir
a=rtcp-fb:121 goog-remb
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:126 goog-remb
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=rtcp-fb:97 goog-remb
a=rtcp-mux
a=rtpmap:120 VP8/90000
a=rtpmap:121 VP9/90000
a=rtpmap:126 H264/90000
a=rtpmap:97 H264/90000
a=setup:actpass
a=ssrc:109206018 cname:{f918048b-0188-438e-b0bb-a223d8d4ae07}
Estadísticas RDP
inbound_rtp_audio_0
Local: 19:08:53 GMT-0500 inboundrtp SSRC: 0
inbound_rtp_video_1
Local: 19:08:53 GMT-0500 inboundrtp SSRC: 0
outbound_rtp_video_1
Local: 19:08:53 GMT-0500 outboundrtp SSRC: 2849290137
outbound_rtp_audio_0
Local: 19:08:53 GMT-0500 outboundrtp SSRC: 2090540075
请帮帮我
答案 0 :(得分:1)
您的浏览器没有收集任何候选人&#34; typ relay&#34;,仅#34; typ host&#34;和&#34; typ srflx&#34;。这表明您使用的凭据是错误的。请参阅"Example 1 - My WebRTC app works locally but not on a different network!"
部分服务器列表看起来像你正在尝试使用&#34;免费&#34;一个......不,没有免费的服务器。