Gaming With Villain
Gaming With Villain

Reputation: 1

WebRTC ICE Candidates Not Settling on Receiver Side (React, Socket.io)

I am implementing a video call feature using two separate RTCPeerConnection instances for sending and receiving video. Currently, I have only implemented the sender's RTC connection, meaning only the receiver can see the sender's video.

Issue: ICE candidates are received on the receiver's side but don't seem to be applied properly. Tracks seem to be received, but no video is displayed.

reciever logs

reciever logs 2

sender logs

webrtc recievr

webrtc sender

function VideoFrameReciever() {
  const { match,  socket } = useAuthStore();
  const remoteVideoRef = useRef();

  const startCall = async () => {
    let candidates= null;
    const sendersPC = new RTCPeerConnection({
      iceServers: [
        { urls: "stun:stun.l.google.com:19302" }, // Example STUN server (Google)
        { urls: "stun:global.stun.twilio.com:3478" }, // Example STUN server (Twilio)
        // Add more STUN servers if needed
      ],
    });
    socket.on("receive-offer", async ({ sdp, from }) => {
      console.log("offer received");

      await sendersPC.setRemoteDescription(sdp);
      const answer = await sendersPC.createAnswer();
      await sendersPC.setLocalDescription(answer);

      socket.emit("send-answer", {
        sdp: sendersPC.localDescription,
        to: match,
      });
      console.log("answer sent");
      sendersPC.onicecandidate = (e) => {
        if (e.candidate) {
          socket.emit("send-ice-candidate", {
            candidate: e.candidate,
            to: match,
          });
          console.log("ice candidate sent", e.candidate);
        }
      };
    });
    socket.on("receive-ice-candidate", async ({ candidate }) => {
    console.log("ice candidates recieved--->",candidate)
    console.log("senderPc---->",sendersPC);
      await sendersPC.addIceCandidate(candidate);
    });

    sendersPC.ontrack = (event) => {
      console.log("track received");
      console.log(event);
      if (remoteVideoRef.current) {
        remoteVideoRef.current.srcObject = event.streams[0]; // Use the streams from the event
        console.log("remoteVideoRef is available", event.streams[0]);
      } else {
        console.error("remoteVideoRef is not available yet.");
      }
    };
  };

  startCall();

  return (
    <div className="mt-30 bg-white">
      <div className="video-container flex justify-between items-center gap-10 p-5 rounded-xl">
        <div className=" bg-emerald-500 border-2 border-emerald-500 h-[300px] w-[510px]">
          {/* {myStream && (
            <>
              <h1>My Stream</h1>
              <ReactPlayer
                playing
                muted
                height="300px"
                width="500px"
                url={myStream}
              />
            </>
          )} */}
        </div>
        <div className=" bg-emerald-500 border-2 border-emerald-500 h-[300px] w-[510px]">
          <h1>Remote Stream</h1>
          <video ref={remoteVideoRef}></video>
        </div>
      </div>
    </div>
  );
} 

function VideoFrameSender() {
  const { match, socket, connectSocket } = useAuthStore();
  useEffect(() => {
    connectSocket();
  }, []);
  const startCall = async () => {
    const sendersPC = new RTCPeerConnection({
      iceServers: [
        { urls: "stun:stun.l.google.com:19302" }, // Example STUN server (Google)
        { urls: "stun:global.stun.twilio.com:3478" }, // Example STUN server (Twilio)
        // Add more STUN servers if needed
      ],
    });

    sendersPC.onnegotiationneeded = async () => {
      console.log("negotiation needed");
      const offer = await sendersPC.createOffer();
      await sendersPC.setLocalDescription(offer);
      socket.emit("send-offer", { sdp: sendersPC.localDescription, to: match });
      console.log("offer sent");
    };

    socket.on("receive-answer", async ({ sdp }) => {
      console.log("answer received");
      await sendersPC.setRemoteDescription(sdp);
    });

    sendersPC.onicecandidate = (e) => {
      if (e.candidate) {
        socket.emit("send-ice-candidate", {
          candidate: e.candidate,
          to: match,
        });
        console.log("ice candidate sent", e.candidate);
      }
    };
    socket.on("receive-ice-candidate", async ({ candidate }) => {
      console.log("ice candidate received--->", candidate);
      await sendersPC.addIceCandidate(candidate);
    });

    const stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: false,
    });

    // Correct way to add track with stream:
    stream.getTracks().forEach((track) => sendersPC.addTrack(track, stream)); // Add each track with the stream
    console.log("Sender tracks:", stream.getTracks()); // <--- Crucial log
  };
  startCall();
  return (
    <div className="mt-30 bg-white">
      <div className="video-container flex justify-between items-center gap-10 p-5 rounded-xl">
        <div className=" bg-emerald-500 border-2 border-emerald-500 h-[300px] w-[510px]">
          {/* {myStream && (
            <>
              <h1>My Stream</h1>
              <ReactPlayer
                playing
                muted
                height="300px"
                width="500px"
                url={myStream}
              />
            </>
          )} */}
        </div>
        <div className=" bg-emerald-500 border-2 border-emerald-500 h-[300px] w-[510px]">
          {/* {remoteStream && (
            <>
              <h1>Remote Stream</h1>
              <ReactPlayer
                playing
                muted
                height="300px"
                width="500px"
                url={remoteStream}
              />
            </>
          )} */}
        </div>
      </div>
    </div>
  );
}

Upvotes: 0

Views: 42

Answers (0)

Related Questions