WebRTC videocall移动热点错误

WebRTC videocall移动热点错误,webrtc,stun,Webrtc,Stun,我正在尝试使用WebRTC和SocketIO为消息传递构建一个简单的p2p视频通话。当两个客户端都连接到不同的WIFI网络时,视频聊天可以正常工作,但当其中一个客户端使用移动热点时,无法建立连接。以下是一些可能有助于发现问题的关键代码块: 开始通话/createOffer function callNeighbor(){ if(buddy=={}){console.log('CALL_NEIGHBOR Neighbor NULL')} else{ const servers =

我正在尝试使用WebRTC和SocketIO为消息传递构建一个简单的p2p视频通话。当两个客户端都连接到不同的WIFI网络时,视频聊天可以正常工作,但当其中一个客户端使用移动热点时,无法建立连接。以下是一些可能有助于发现问题的关键代码块: 开始通话/createOffer

function callNeighbor(){
  if(buddy=={}){console.log('CALL_NEIGHBOR Neighbor NULL')}
  else{

    const servers = {iceServers: [{urls: 'stun:stun1.l.google.com:19305'}]};
    pc=new RTCPeerConnection(servers);
    pc.onicecandidate = e => onIceCandidate(pc, e);
    pc.ontrack=gotRemoteStream;
    pc.onnegotiationneeded=function(){
      pc.createOffer().then(success=>{
        console.log(success)
        pc.setLocalDescription(success).then(success=>{
          socket.emit('rtcRequest',{from:name,to:buddy.name,body:pc.localDescription});

        },error=>{
          console.log(failure);
        });

      },
        failure=>{
          console.log(failure);
        })
    }
    navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
  }
}
function handleCall(stream) {
  console.log(stream);
  localOut.srcObject = stream;

  localStream = stream;
  const audioTracks = localStream.getAudioTracks();
  if (audioTracks.length > 0) {
    // console.log(`Using Audio device: ${audioTracks[0].label}`);
  }
  localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
  // console.log('Adding Local Stream to peer connection');
  pc.createAnswer().then(answer=>{
    pc.setLocalDescription(answer).then(success=>{
        socket.emit('rtcResponse',{from:name,to:buddy.name,body:pc.localDescription});

    },error=>{console.log(error)})

  },error=>{console.log(error)})
}

onICECandidate

function onIceCandidate(pc, event) {
  const candidate=event.candidate
  if(candidate==null){return}
  console.log('**SENDING ICE** '+candidate)
  console.log(candidate)
  socket.emit("rtcICE",{from:name,to:buddy.name, body:candidate});
  console.log(`PC ICE candidate:\n${candidate ? candidate.candidate : '(null)'}`);
}

socket.on('rtcICE',function(data){//rtcICE is via socketIO see onICECandidate above
  pc.addIceCandidate((data.body)).then(success=>console.log(success),error=>console.log(error));
})
接听来电/createAnswer

function callNeighbor(){
  if(buddy=={}){console.log('CALL_NEIGHBOR Neighbor NULL')}
  else{

    const servers = {iceServers: [{urls: 'stun:stun1.l.google.com:19305'}]};
    pc=new RTCPeerConnection(servers);
    pc.onicecandidate = e => onIceCandidate(pc, e);
    pc.ontrack=gotRemoteStream;
    pc.onnegotiationneeded=function(){
      pc.createOffer().then(success=>{
        console.log(success)
        pc.setLocalDescription(success).then(success=>{
          socket.emit('rtcRequest',{from:name,to:buddy.name,body:pc.localDescription});

        },error=>{
          console.log(failure);
        });

      },
        failure=>{
          console.log(failure);
        })
    }
    navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
  }
}
function handleCall(stream) {
  console.log(stream);
  localOut.srcObject = stream;

  localStream = stream;
  const audioTracks = localStream.getAudioTracks();
  if (audioTracks.length > 0) {
    // console.log(`Using Audio device: ${audioTracks[0].label}`);
  }
  localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
  // console.log('Adding Local Stream to peer connection');
  pc.createAnswer().then(answer=>{
    pc.setLocalDescription(answer).then(success=>{
        socket.emit('rtcResponse',{from:name,to:buddy.name,body:pc.localDescription});

    },error=>{console.log(error)})

  },error=>{console.log(error)})
}

添加Ice候选者

function onIceCandidate(pc, event) {
  const candidate=event.candidate
  if(candidate==null){return}
  console.log('**SENDING ICE** '+candidate)
  console.log(candidate)
  socket.emit("rtcICE",{from:name,to:buddy.name, body:candidate});
  console.log(`PC ICE candidate:\n${candidate ? candidate.candidate : '(null)'}`);
}

socket.on('rtcICE',function(data){//rtcICE is via socketIO see onICECandidate above
  pc.addIceCandidate((data.body)).then(success=>console.log(success),error=>console.log(error));
})
日志

来电者

接受者

编辑以下是设置远程描述的代码

socket.on('rtcRequest',function(data){
  const offer=data.body;
  const servers = {iceServers: [{urls: 'stun:stun1.l.google.com:19305'}]};;
  pc=new RTCPeerConnection(servers);
  pc.onicecandidate = e => onIceCandidate(pc, e);
  pc.ontrack=gotRemoteStream;
  pc.onnegotiationneeded=function(){
    console.log('NEGOTIATION NEEDED!!!')}
  pc.setRemoteDescription(data.body).then(success=>{
    navigator.mediaDevices.getUserMedia(constraints).then(handleCall).catch(handleError);
    },
    error=>{console.log(error)
    }
  );

})

我也有同样的问题。如果您控制自己的TURN服务器,请检查所有需要的端口UDP和TCP端口。在我的例子中,我忘了在我只打开UDP的TCP端口中打开3748。

我也有同样的问题。如果您控制自己的TURN服务器,请检查所有需要的端口UDP和TCP端口。在我的例子中,我忘了在只打开UDP的TCP端口中打开3748。

什么时候在接收器端执行setRemoteDescription()?@kenjitanaka刚刚在底部添加了它更新,该代码在两个不同的wifi网络上工作,但在移动热点上断开。在OnGotiationNeeded事件中不执行setRemoteDescription()。我不是,很抱歉,格式不正确,onnegotiationneeded只是控制台记录“需要协商”;我只是想看看它什么时候着火,所以这就是为什么我添加了在接收器端执行setRemoteDescription()的logWhen?@kenjitanaka刚刚在底部添加了它更新,代码在两个不同的wifi网络上工作,但在移动热点上断开。在OnGetiationRequired事件中不执行setRemoteDescription()。我不是,很抱歉,格式不正确,onnegotiationneeded只是控制台记录“需要协商”;我只是想看看它什么时候着火,所以我加了那个日志