Javascript 多点连接onicecandidate事件获胜';t火

Javascript 多点连接onicecandidate事件获胜';t火,javascript,java,reactjs,websocket,webrtc,Javascript,Java,Reactjs,Websocket,Webrtc,我对webRTC多对等连接处理背后的构建逻辑有问题。 基本上,我想通过视频电话会议让房间里挤满了人。 我使用的是js提供的基本WebSocket库,前端使用React,后端使用Java(spring boot) 就我目前的理解而言,这是我设法写下的内容(根据我“认为”相关的内容进行过滤) 这是我的web套接字初始化方法(添加侦听器) 当然还有“出错时”、“关闭时”和“打开时”侦听器 这是处理传入报价的方法 const handleOfferMessage = (message) => {

我对webRTC多对等连接处理背后的构建逻辑有问题。 基本上,我想通过视频电话会议让房间里挤满了人。 我使用的是js提供的基本WebSocket库,前端使用React,后端使用Java(spring boot)

就我目前的理解而言,这是我设法写下的内容(根据我“认为”相关的内容进行过滤)

这是我的web套接字初始化方法(添加侦听器)

当然还有“出错时”、“关闭时”和“打开时”侦听器 这是处理传入报价的方法

 const handleOfferMessage = (message) => {
    console.log("Accepting Offer Message");
    console.log(message);
    let desc = new RTCSessionDescription(message.sdp);
    let newPeerConnection = new RTCPeerConnection(peerConnectionConfig);
    newPeerConnection.onicecandidate = handleICECandidateEvent;
    newPeerConnection.ontrack = handleTrackEvent;
    if (desc != null && message.sdp != null) {
      console.log("RTC Signalling state: " + newPeerConnection.signalingState);
      newPeerConnection
        .setRemoteDescription(desc)
        .then(function () {
          console.log("Set up local media stream");
          return navigator.mediaDevices.getUserMedia(mediaConstraints);
        })
        .then(function (stream) {
          console.log("-- Local video stream obtained");
          localStream = stream;
          try {
            videoSelf.current.srcObject = localStream;
          } catch (error) {
            videoSelf.current.src = window.URL.createObjectURL(stream);
          }

          console.log("-- Adding stream to the RTCPeerConnection");
          localStream
            .getTracks()
            .forEach((track) => newPeerConnection.addTrack(track, localStream));
        })
        .then(function () {
          console.log("-- Creating answer");
          return newPeerConnection.createAnswer();
        })
        .then(function (answer) {
          console.log("-- Setting local description after creating answer");
          return newPeerConnection.setLocalDescription(answer);
        })
        .then(function () {
          console.log("Sending answer packet back to other peer");
          webSocketConnection.send(
            JSON.stringify({
              from: user,
              type: "answer",
              sdp: newPeerConnection.localDescription,
              destination: message.from
            })
          );
        })
        .catch(handleErrorMessage);
    }
    peerConnections[message.from.id] = newPeerConnection;
    console.log("Peer connections updated now ", peerConnections);
  };
SN:我将对等连接定义为由用户唯一id索引的RTCPeerConnection数组

let [peerConnections, setPeerConnections] = useState([]);
这是我认为我弄错的部分,我很难理解

  const handleAnswerMessage = (message) => {
    console.log("The peer has accepted request");
    let currentPeerConnection = peerConnections[message.from.id];
    if (currentPeerConnection) {
      currentPeerConnection.setRemoteDescription(message.sdp).catch(handleErrorMessage);
      peerConnections[message.from.id] = currentPeerConnection;
    } else {
      console.error("No user was found with id ", message.from.id);
    }
    console.log("Peer connections updated now ", peerConnections);

  };
    currentPeerConnection.setRemoteDescription(message.sdp).catch(handleErrorMessage);
    peerConnections[message.from.id] = currentPeerConnection;
    console.log("Peer connections updated now ", peerConnections);

  };
答案和提议完美地工作了,我可以清楚地看到两个对等者通过发送提议进行交流,而另一个则以答复进行回应。唯一的问题是,在那之后什么都没有发生,但从我读到的关于webRTC的内容来看,它应该在设置了本地描述之后立即开始收集ice候选对象

我可以理解为什么处理应答的对等方(调用方)实际上没有启动iceecandidate,这可能是因为我没有在应答消息上设置本地描述(我不知道它是否正确)。另一方面,处理offer消息的被叫方实际上应该开始收集iceecandidates,我在那里设置本地描述

这是一些可能有帮助的附加代码

function getMedia(constraints, peerCnnct, initiator) {
    if (localStream) {
      localStream.getTracks().forEach((track) => {
        track.stop();
      });
    }
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then(stream => {
        return getLocalMediaStream(stream, peerCnnct, initiator);
      })
      .catch(handleGetUserMediaError);
  }

  function getLocalMediaStream(mediaStream, peerConnection, initiator) {
    localStream = mediaStream;
    const video = videoSelf.current;
    if (video) {
      video.srcObject = mediaStream;
      video.play();
    }
    //localVideo.srcObject = mediaStream;
    console.log("Adding stream tracks to the peer connection: ", peerConnection);

    if (!initiator) {
      localStream
        .getTracks()
        .forEach((track) => peerConnection.addTrack(track, localStream));
    }
  }

  const handlePeerConnection = (message) => {
    console.info("Creating new peer connection for user ", message.from);

    let newPeerConnection = new RTCPeerConnection(peerConnectionConfig);
    // event handlers for the ICE negotiation process
    newPeerConnection.ontrack = handleTrackEvent;
    newPeerConnection.onicecandidate = handleICECandidateEvent;
    getMedia(mediaConstraints, newPeerConnection, false);
    newPeerConnection.onnegotiationneeded = handleNegotiationNeededEvent(newPeerConnection, webSocketConnection, user, message.from);
    peerConnections[message.from.id] = newPeerConnection;
  };
在这里,你可以清楚地看到我在寻找解决方案和创建对等连接方面的不顾一切的尝试,只是为了发送报价。 我无法索引没有最终用户的对等连接,因为我需要他的id,只有在我第一次加入会议室时收到他的答复后,我才会收到他的id

(后端应该可以工作,但无论哪种方式,在ice候选处理程序方法上放置一个调试器,我都可以清楚地看到它没有被触发)

我做错了什么

编辑:现在WebSocketMessage服务器端还有一个目标用户。这样,连接到房间的新对等方接收的对等方初始化消息数量与已连接的对等方相同。然后继续为每个对等方提供一个报价,并将其设置为目的地


这个问题仍然存在,尽管这感觉很奇怪,但我通过调用getUserMedia()修复了它(这意味着在将onicecandidate事件定义添加到peerConnection之前调用addTrack)

这至少解决了我的问题

function getMedia(constraints, peerCnnct, initiator) {
    if (localStream) {
      localStream.getTracks().forEach((track) => {
        track.stop();
      });
    }
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then(stream => {
        return getLocalMediaStream(stream, peerCnnct, initiator);
      })
      .catch(handleGetUserMediaError);
  }

  function getLocalMediaStream(mediaStream, peerConnection, initiator) {
    localStream = mediaStream;
    const video = videoSelf.current;
    if (video) {
      video.srcObject = mediaStream;
      video.play();
    }
    //localVideo.srcObject = mediaStream;
    console.log("Adding stream tracks to the peer connection: ", peerConnection);

    if (!initiator) {
      localStream
        .getTracks()
        .forEach((track) => peerConnection.addTrack(track, localStream));
    }
  }

  const handlePeerConnection = (message) => {
    console.info("Creating new peer connection for user ", message.from);

    let newPeerConnection = new RTCPeerConnection(peerConnectionConfig);
    // event handlers for the ICE negotiation process
    newPeerConnection.ontrack = handleTrackEvent;
    newPeerConnection.onicecandidate = handleICECandidateEvent;
    getMedia(mediaConstraints, newPeerConnection, false);
    newPeerConnection.onnegotiationneeded = handleNegotiationNeededEvent(newPeerConnection, webSocketConnection, user, message.from);
    peerConnections[message.from.id] = newPeerConnection;
  };