WebRTC iceConnectionState一直是'checking'状态;(使用Coturn)



我想做一个简单的视频网络聊天工具,使用webrtc和weosocket。
使用coturn作为眩晕和转向服务器。
在局域网内可以正常使用,但在公网上会被iceConnectionState检查。

下面是实现代码,基本上来自https://github.com/webrtc/samples/blob/gh-pages/src/content/peerconnection/pc1/js/main.jscaller.js:

'use strict';
const Key = 123123;
var socket = new WebSocket("wss://xxxx/webrtc");
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
startButton.addEventListener('click', start);
hangupButton.addEventListener('click', hangup);
let startTime;
const iceConfiguration = {
iceServers: [{
urls: "stun:xxxx:3478"
}, {
urls: "turn:xxxx:3478",
username: "xxxx",
credential: "xxxx"
}]
};
let localStream;
let pc;
const offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
socket.onopen = function () {
socket.send(JSON.stringify({ event: '_x_serverkey', data: Key, isCaller: true }));
console.log('send key');
};
socket.onmessage = async function (event) {
var json = JSON.parse(event.data);
if (json.event === "_ice_candidate") {
pc.addIceCandidate(new RTCIceCandidate(json.data.candidate));
} else {
if (json.event === "_answer") {
console.log('get_answer');
pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
}
}
};
async function start() {
console.log('Requesting local stream');
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
console.log('Received local stream');
localVideo.srcObject = stream;
localStream = stream;
} catch (e) {
alert(`getUserMedia() error: ${e.name}`);
}
startTime = window.performance.now();
pc = new RTCPeerConnection(iceConfiguration);
pc.addEventListener('icecandidate', onIceCandidate);
pc.addEventListener('track', gotRemoteStream);
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
try {
console.log('pc createOffer start');
const offer = await pc.createOffer(offerOptions);
await onCreateOfferSuccess(offer);
} catch (e) {
console.log(`Failed to create session description: ${e.toString()}`);
}
}
async function onCreateOfferSuccess(desc) {
console.log('setLocalDescription start');
try {
await pc.setLocalDescription(desc);
} catch (e) {
console.log(e);
}
socket.send(JSON.stringify({
event: "_offer",
data: {
sdp: pc.localDescription
}
}));
}
async function onIceCandidate(event) {
if (event.candidate !== null) {
socket.send(JSON.stringify({
event: "_ice_candidate",
data: {
candidate: event.candidate
}
}));
}
}
function gotRemoteStream(e) {
if (remoteVideo.srcObject !== e.streams[0]) {
remoteVideo.srcObject = e.streams[0];
console.log('received remote stream');
}
}

server.js:

'use strict';
const Key = 123123;
var socket = new WebSocket("wss://xxxx/webrtc");
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
startButton.addEventListener('click', start);
hangupButton.addEventListener('click', hangup);
let startTime;
const iceConfiguration = {
iceServers: [{
urls: "stun:xxxx:3478"
}, {
urls: "turn:xxxx:3478",
username: "xxxx",
credential: "xxxx"
}]
};
let localStream;
let pc;
socket.onopen = function () {
socket.send(JSON.stringify({ event: '_x_serverkey', data: Key, isCaller: false }));
console.log('send key');
};
socket.onmessage = async function (event) {
var json = JSON.parse(event.data);
if (json.event === "_ice_candidate") {
pc.addIceCandidate(new RTCIceCandidate(json.data.candidate));
} else {
console.log(json.data.sdp);
pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
if (json.event === "_offer") {
console.log('get offer');
console.log(json);
const answer = await pc.createAnswer();
await onCreateAnswerSuccess(answer);
}
}
};
async function start() {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
localVideo.srcObject = stream;
localStream = stream;
} catch (e) {
alert(`getUserMedia() error: ${e.name}`);
}
startTime = window.performance.now();
pc = new RTCPeerConnection(iceConfiguration);
pc.addEventListener('icecandidate', onIceCandidate);
pc.addEventListener('track', gotRemoteStream);
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
}
async function onIceCandidate(event) {
try {
await (pc.addIceCandidate(event.candidate));
} catch (e) {
console.log(`failed to add ICE Candidate: ${error.toString()}`);
}
}

function gotRemoteStream(e) {
if (remoteVideo.srcObject !== e.streams[0]) {
remoteVideo.srcObject = e.streams[0];
console.log('received remote stream');
}
}
async function onCreateAnswerSuccess(desc) {
await pc.setLocalDescription(desc);
console.log('setLocalDescription start');
socket.send(JSON.stringify({
event: "_answer",
data: {
sdp: pc.localDescription
}
}));
}

coturn配置:

listening-port=3478
tls-listening-port=5349
listening-ip=0.0.0.0
external-ip=**.**.**.**
min-port=8000
max-port=9000
fingerprint
lt-cred-mech
server-name=xxxx.com
user=xxx:xxxx
userdb=/var/lib/coturn/turndb
realm=xxxx.com
cert=xxx
pkey=xxx
no-cli

问题的原因是server.js的iceccandidate没有发送给call .js

修改server.js

async function onIceCandidate(event) {
if (event.candidate !== null) {
socket.send(JSON.stringify({
event: "_ice_candidate",
data: {
candidate: event.candidate
}
}));
}
}

最新更新