Webrtc视频聊天在不同网络中不工作
我正在尝试使用来自的代码实现与webrtc的视频聊天。它可以在同一个网络上正常工作,但不能在不同的网络上工作。我已经在我的服务器上安装了coturn。我不确定它是否工作正常 有人用过谷歌代码实验室的代码并让它工作了吗 这是修改后的main.js文件Webrtc视频聊天在不同网络中不工作,webrtc,turn,coturn,Webrtc,Turn,Coturn,我正在尝试使用来自的代码实现与webrtc的视频聊天。它可以在同一个网络上正常工作,但不能在不同的网络上工作。我已经在我的服务器上安装了coturn。我不确定它是否工作正常 有人用过谷歌代码实验室的代码并让它工作了吗 这是修改后的main.js文件 'use strict'; var isChannelReady = false; var isInitiator = false; var isStarted = false; var localStream; var pc; var remot
'use strict';
var isChannelReady = false;
var isInitiator = false;
var isStarted = false;
var localStream;
var pc;
var remoteStream;
var turnReady;
var pcConfig = {
"iceServers":[
{'urls': 'stun:stun.l.google.com:19302'},
{"urls":["turn:78.129.167.90"],"username":"wyzturner1","credential":"wyzturnp2ss"}]
};
// Set up audio and video regardless of what devices are present.
var sdpConstraints = {
offerToReceiveAudio: true,
offerToReceiveVideo: true
};
/////////////////////////////////////////////
var room = 'foo';
// Could prompt for room name:
// room = prompt('Enter room name:');
var socket = io.connect('https://www.samplesite.com:8080');
if (room !== '') {
socket.emit('create or join', room);
console.log('Attempted to create or join room', room);
}
socket.on('created', function(room) {
console.log('Created room ' + room);
isInitiator = true;
});
socket.on('full', function(room) {
console.log('Room ' + room + ' is full');
});
socket.on('join', function (room){
console.log('Another peer made a request to join room ' + room);
console.log('This peer is the initiator of room ' + room + '!');
isChannelReady = true;
});
socket.on('joined', function(room) {
console.log('joined: ' + room);
isChannelReady = true;
});
socket.on('log', function(array) {
console.log.apply(console, array);
});
////////////////////////////////////////////////
function sendMessage(message) {
console.log('Client sending message: ', message);
socket.emit('message', message);
}
// This client receives a message
socket.on('message', function(message) {
console.log('Client received message:', message);
if (message === 'got user media') {
maybeStart();
} else if (message.type === 'offer') {
if (!isInitiator && !isStarted) {
maybeStart();
}
pc.setRemoteDescription(new RTCSessionDescription(message));
doAnswer();
} else if (message.type === 'answer' && isStarted) {
pc.setRemoteDescription(new RTCSessionDescription(message));
} else if (message.type === 'candidate' && isStarted) {
var candidate = new RTCIceCandidate({
sdpMLineIndex: message.label,
candidate: message.candidate
});
pc.addIceCandidate(candidate);
} else if (message === 'bye' && isStarted) {
handleRemoteHangup();
}
});
////////////////////////////////////////////////////
var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');
navigator.mediaDevices.getUserMedia({
audio: false,
video: true
})
.then(gotStream)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
function gotStream(stream) {
console.log('Adding local stream.');
localVideo.src = window.URL.createObjectURL(stream);
localStream = stream;
sendMessage('got user media');
if (isInitiator) {
maybeStart();
}
}
var constraints = {
video: true
};
console.log('Getting user media with constraints', constraints);
//if (location.hostname !== 'localhost') {
// requestTurn(
// 'https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913'
// );
//}
function maybeStart() {
console.log('>>>>>>> maybeStart() ', isStarted, localStream, isChannelReady);
if (!isStarted && typeof localStream !== 'undefined' && isChannelReady) {
console.log('>>>>>> creating peer connection');
createPeerConnection();
isStarted = true;
console.log('isInitiator', isInitiator);
if (isInitiator) {
doCall();
}
}
}
window.onbeforeunload = function() {
sendMessage('bye');
};
/////////////////////////////////////////////////////////
function createPeerConnection() {
try {
pc = new RTCPeerConnection(pcConfig);
pc.addStream(localStream);
pc.onicecandidate = handleIceCandidate;
pc.onaddstream = handleRemoteStreamAdded;
pc.oniceconnectionstatechange = function(){
console.log('ICE state: ',pc.iceConnectionState);
}
pc.onremovestream = handleRemoteStreamRemoved;
console.log('Created RTCPeerConnnection');
} catch (e) {
console.log('Failed to create PeerConnection, exception: ' + e.message);
alert('Cannot create RTCPeerConnection object.');
return;
}
}
function handleIceCandidate(event) {
console.log('icecandidate event: ', event);
if (event.candidate) {
sendMessage({
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate
});
} else {
console.log('End of candidates.');
}
}
function handleRemoteStreamAdded(event) {
console.log('Remote stream added.');
remoteVideo.src = window.URL.createObjectURL(event.stream);
remoteStream = event.stream;
}
function handleCreateOfferError(event) {
console.log('createOffer() error: ', event);
}
function doCall() {
console.log('Sending offer to peer');
pc.createOffer(setLocalAndSendMessage, handleCreateOfferError);
}
function doAnswer() {
console.log('Sending answer to peer.');
pc.createAnswer().then(
setLocalAndSendMessage,
onCreateSessionDescriptionError
);
}
function setLocalAndSendMessage(sessionDescription) {
// Set Opus as the preferred codec in SDP if Opus is present.
// sessionDescription.sdp = preferOpus(sessionDescription.sdp);
pc.setLocalDescription(sessionDescription);
console.log('setLocalAndSendMessage sending message', sessionDescription);
sendMessage(sessionDescription);
}
function onCreateSessionDescriptionError(error) {
trace('Failed to create session description: ' + error.toString());
}
function requestTurn(turnURL) {
var turnExists = false;
for (var i in pcConfig.iceServers) {
if (pcConfig.iceServers[i].urls.substr(0, 5) === 'turn:') {
turnExists = true;
turnReady = true;
break;
}
}
// if (!turnExists) {
// console.log('Getting TURN server from ', turnURL);
// // No TURN server. Get one from computeengineondemand.appspot.com:
// var xhr = new XMLHttpRequest();
// xhr.onreadystatechange = function() {
// if (xhr.readyState === 4 && xhr.status === 200) {
// var turnServer = JSON.parse(xhr.responseText);
// console.log('Got TURN server: ', turnServer);
// pcConfig.iceServers.push({
// 'url': 'turn:' + turnServer.username + '@' + turnServer.turn,
// 'credential': turnServer.password
// });
// turnReady = true;
// }
// };
// xhr.open('GET', turnURL, true);
// xhr.send();
// }
}
function handleRemoteStreamAdded(event) {
console.log('Remote stream added.');
remoteVideo.src = window.URL.createObjectURL(event.stream);
remoteStream = event.stream;
}
function handleRemoteStreamRemoved(event) {
console.log('Remote stream removed. Event: ', event);
}
function hangup() {
console.log('Hanging up.');
stop();
sendMessage('bye');
}
function handleRemoteHangup() {
console.log('Session terminated.');
stop();
isInitiator = false;
}
function stop() {
isStarted = false;
// isAudioMuted = false;
// isVideoMuted = false;
pc.close();
pc = null;
}
///////////////////////////////////////////
// Set Opus as the default audio codec if it's present.
function preferOpus(sdp) {
var sdpLines = sdp.split('\r\n');
var mLineIndex;
// Search for m line.
for (var i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('m=audio') !== -1) {
mLineIndex = i;
break;
}
}
if (mLineIndex === null) {
return sdp;
}
// If Opus is available, set it as the default in m line.
for (i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('opus/48000') !== -1) {
var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
if (opusPayload) {
sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex],
opusPayload);
}
break;
}
}
// Remove CN in m line and sdp.
sdpLines = removeCN(sdpLines, mLineIndex);
sdp = sdpLines.join('\r\n');
return sdp;
}
function extractSdp(sdpLine, pattern) {
var result = sdpLine.match(pattern);
return result && result.length === 2 ? result[1] : null;
}
// Set the selected codec to the first in m line.
function setDefaultCodec(mLine, payload) {
var elements = mLine.split(' ');
var newLine = [];
var index = 0;
for (var i = 0; i < elements.length; i++) {
if (index === 3) { // Format of media starts from the fourth.
newLine[index++] = payload; // Put target payload to the first.
}
if (elements[i] !== payload) {
newLine[index++] = elements[i];
}
}
return newLine.join(' ');
}
// Strip CN from sdp before CN constraints is ready.
function removeCN(sdpLines, mLineIndex) {
var mLineElements = sdpLines[mLineIndex].split(' ');
// Scan from end for the convenience of removing an item.
for (var i = sdpLines.length - 1; i >= 0; i--) {
var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
if (payload) {
var cnPos = mLineElements.indexOf(payload);
if (cnPos !== -1) {
// Remove CN payload from m line.
mLineElements.splice(cnPos, 1);
}
// Remove CN line in sdp
sdpLines.splice(i, 1);
}
}
sdpLines[mLineIndex] = mLineElements.join(' ');
return sdpLines;
}
“严格使用”;
var isChannelReady=false;
var isInitiator=false;
var isStarted=假;
var-localStream;
var-pc;
远程流;
var-turnReady;
变量pcConfig={
“ICEServer”:[
{'URL':'stun:stun.l.google.com:19302'},
{“URL”:[“turn:78.129.167.90”],“用户名”:“wyzturner1”,“凭证”:“wyzturnp2ss”}]
};
//设置音频和视频,而不管有什么设备。
变量SDP约束={
offerToReceiveAudio:正确,
offerToReceiveVideo:正确
};
/////////////////////////////////////////////
变量室='foo';
//无法提示输入房间名称:
//房间=提示('输入房间名称:');
var socket=io.connect('https://www.samplesite.com:8080');
如果(房间!=''){
socket.emit('create或join',房间);
console.log('试图创建或加入文件室',文件室');
}
插座打开('已创建'),功能(房间){
console.log('创建的房间'+房间);
isInitiator=true;
});
插座打开(“满”,功能(房间){
console.log('房间'+房间+'已满');
});
插座开('join',功能(房间){
log('另一个对等方请求加入房间'+房间);
console.log('此对等方是文件室“+文件室+!”的发起方);
isChannelReady=true;
});
插座上的('连接',功能(房间){
控制台日志('已加入:'+房间);
isChannelReady=true;
});
socket.on('log',函数(数组){
console.log.apply(控制台,数组);
});
////////////////////////////////////////////////
函数sendMessage(消息){
log('客户端发送消息:',消息);
发出('message',message);
}
//此客户端接收一条消息
socket.on('message',函数(message){
log('客户端收到的消息:',消息);
如果(消息=='已获得用户媒体'){
maybeStart();
}else if(message.type==='offer'){
如果(!isInitiator&!isStarted){
maybeStart();
}
pc.setRemoteDescription(新的RTCSessionDescription(消息));
doAnswer();
}else if(message.type==='answer'&&isstart){
pc.setRemoteDescription(新的RTCSessionDescription(消息));
}else if(message.type==='candidate'&&isStarted){
var候选者=新的候选者({
sdpMLineIndex:message.label,
候选人:message.candidate
});
pc.addIceCandidate(候选人);
}else if(消息==='bye'&&istarted){
handleRemoteHangup();
}
});
////////////////////////////////////////////////////
var localVideo=document.querySelector('#localVideo');
var remoteVideo=document.querySelector(“#remoteVideo”);
navigator.mediaDevices.getUserMedia({
音频:错,
视频:真的
})
.然后(gotStream)
.catch(函数(e){
警报('getUserMedia()错误:'+e.name);
});
函数gotStream(stream){
log('添加本地流');
localVideo.src=window.URL.createObjectURL(流);
localStream=stream;
sendMessage('got user media');
if(isInitiator){
maybeStart();
}
}
变量约束={
视频:真的
};
log('获取带有约束的用户媒体',约束);
//if(location.hostname!=“localhost”){
//请求回合(
// 'https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913'
// );
//}
函数maybeStart(){
log(“>>>>maybeStart()”,isStart,localStream,isChannelReady);
如果(!isStart&&typeof localStream!=='undefined'&&isChannelReady){
log(“>>>创建对等连接”);
createPeerConnection();
IsStart=true;
console.log('isinitator',isinitator);
if(isInitiator){
doCall();
}
}
}
window.onbeforeunload=函数(){
发送消息(“再见”);
};
/////////////////////////////////////////////////////////
函数createPeerConnection(){
试一试{
pc=新的RTPEERCONNECTION(pcConfig);
pc.addStream(localStream);
pc.onicecandidate=handleIceCandidate;
pc.onaddstream=handleRemoteStreamAdded;
pc.oniceconnectionstatechange=函数(){
console.log('ICE state:',pc.iceConnectionState);
}
pc.onremovestream=已移除把手移除测试流;
log('Created rtpeerconconnection');
}捕获(e){
console.log('创建对等连接失败,异常:'+e.message);
警报('无法创建RTPeerConnection对象');
返回;
}
}
函数handleIceCandidate(事件){
log('icecandidate事件:',事件);
if(事件候选){
发送消息({
键入:“候选人”,
标签:event.candidate.sdpMLineIndex,
id:event.candidate.sdpMid,
候选人:event.candidate.candidate
});
}否则{
console.log(“候选对象结束”);
}
}
添加函数handleremotestream(事件){
log('添加了远程流');
remoteVideo.src=window.URL.createObjectURL(event.stream);
remoteStream=event.stream;
}
函数handleCreateOfferError(事件){
日志('createOffer()错误:',事件);
}
函数doCall(){
console.log(“向对等方发送报价”);
pc.createOffer(setLocalAndSendMessage,handleCreateOfferError);
}
函数doAnswer(){
log('向对等方发送应答');
pc.createAnswer()。然后(
setLocalAndSendMessage,
onCreateSessionDescriptionError
);
}
函数setLocalAndSendMessage(sessionDescription){
//如果存在Opus,则将Opus设置为SDP中的首选编解码器。
//sessionDescription.sdp=preferOpus(sessionDescription.sdp);
pc.setLocalDescription(sessionDescription);
log('setLocalAndSendMessage发送消息',sessionDescription);
sendMessage(sessionDescription);
}
函数onCreateSessionDescriptionError(错误){
跟踪('未能创建会话描述:'+错误.toString());
}
函数requestTurn(turnURL){
var=false;
for(var)