webRTC-没有从其他同伴那里获得流和冰候选人

时间:2018-11-13 02:27:12

标签: javascript node.js socket.io webrtc

我正在使用webRTC和socket.io开发视频通话应用程序。我查看了其他类似的项目,并尝试实施自己的项目。

第一个对等方创建要约,另一个对等方获取要约并将其保存到其远程描述中,并创建第一个对等方收到的答案。但是候选冰不交换,也不交换。 这是客户端代码:

var socket = io();
var peerConn,
  onlineUsers = [],
  username,
  caller;

function createOffer(callee) {
  peerConn = new RTCPeerConnection();
  peerConn.onicecandidate = onIce;
  peerConn.onaddstream = onAddStream;
  navigator.mediaDevices
    .getUserMedia({ audio: true, video: { height: 240, width: 320 } })
    .then(stream => (window.myVideo.srcObject = stream))
    .then(stream => peerConn.addStream(stream));
  peerConn.createOffer().then(offer => {
    peerConn.setLocalDescription(offer);
    socket.emit("call", callee, peerConn.localDescription);
  });
  caller = callee;
}

socket.on("call", (callee, caller, sdp) => {
  if (callee == username) createAnswer(sdp, caller);
});
function createAnswer(sdp, caller) {
  peerConn = new RTCPeerConnection();
  peerConn.onicecandidate = onIce;
  peerConn.onaddstream = onAddStream;
  window.caller = caller;
  navigator.mediaDevices
    .getUserMedia({ audio: true, video: { height: 240, width: 320 } })
    .then(stream => (window.myVideo.srcObject = stream))
    .then(stream => peerConn.addStream(stream));
  peerConn.setRemoteDescription(new RTCSessionDescription(sdp));
  peerConn.createAnswer().then(answer => {
    peerConn.setLocalDescription(answer);
    socket.emit("answer", caller, peerConn.localDescription);
  });
  console.log(peerConn.localDescription);
  console.log(peerConn.remoteDescription);
}

function onIce(event) {
  if (event.candidate) {
    socket.emit("ice", caller, event.candidate);
    console.log("sent ice");
  } else {
    console.log("Sent all ice");
  }
}

function onAddStream(event) {
  console.log("remote stream added");
  frndsVideo.srcObject = event.stream;
}

socket.on("answer", (callee, caller, sdp) => {
  if (caller == username) setRemoteDes(sdp);
});
function setRemoteDes(sdp) {
  peerConn.setRemoteDescription(sdp);
  console.log(peerConn.localDescription);
  console.log(peerConn.remoteDescription);
}

function addIce(caller, callee, ice) {
  peerConn.addIceCandidate(new RTCIceCandidate(ice));
  console.log("ice added");
}

socket.on("ice", addIce);

以及服务器端js代码:

socket.on("call", (callee, sdp) => {
    console.log(`${socket.username} calling ${callee}  ${sdp}`);
    onlineUsers.forEach((user, i) => {
      if (user.username == callee || user.username == socket.username) {
        onlineUsers[i].inCall = true;
      }
    });
    socket.broadcast.emit(`call`, callee, socket.username, sdp);
  });
  socket.on("answer", (caller, sdp) => {
    console.log(`${socket.username} answered ${caller}  ${sdp}`);
    socket.broadcast.emit("answer", socket.username, caller, sdp);
  });
  socket.on("ice", (caller, ice) => {
    socket.broadcast.emit("ice", socket.username, caller, ice);
    console.log("ice recived and sent");
  });

请帮助我。

1 个答案:

答案 0 :(得分:1)

在Firefox中运行它,您会看到此错误:

InvalidStateError: Cannot create offer when there are no valid transceivers.

您要在createOffer之前致电addStream,这会产生空的报价,没有候选人。

peerConn.localDescription完成之前,您还在使用setLocalDescription

这些是异步方法,需要按顺序运行,而不是并行运行。尝试链接它们:

function createOffer(callee) {
  peerConn = new RTCPeerConnection();
  peerConn.onicecandidate = onIce;
  peerConn.onaddstream = onAddStream;
  navigator.mediaDevices
    .getUserMedia({audio: true, video: {height: 240, width: 320}})
    .then(stream => {
      peerConn.addStream(myVideo.srcObject = stream);
      return peerConn.createOffer();
    })
    .then(offer => peerConn.setLocalDescription(offer))
    .then(() => socket.emit("call", callee, peerConn.localDescription))
    .catch(e => console.log(e));
  caller = callee;
}

此外,在接听电话的那一刻,请不要再延迟致电setRemoteDescription,否则您就有可能错过候选人。正如我在another answer中所述,这是时间敏感的。

function createAnswer(sdp, caller) {
  peerConn = new RTCPeerConnection();
  peerConn.onicecandidate = onIce;
  peerConn.onaddstream = onAddStream;
  window.caller = caller;
  peerConn.setRemoteDescription(sdp)
  .then(() => navigator.mediaDevices
    .getUserMedia({audio: true, video: {height: 240, width: 320}}))
  .then(stream => {
    peerConn.addStream(myVideo.srcObject = stream);
    return peerConn.createAnswer();
  })
  .then(answer => peerConn.setLocalDescription(answer))
  .then(() => socket.emit("answer", caller, peerConn.localDescription))
  .catch(e => console.log(e));
}