Sumit Athani
Sumit Athani

Reputation: 1

I'm trying to create a video calling app, using simple-peer and rooms. Not able to get stream from 1st user, but stream is received by 1st user

The problem is the user already in the room can access the other user's vid, but not vice versa. I guess this is signalling issue, and im not able to track it down. Please do help me here. Thanks in advance.

Signalling server:
const express = require("express");
const { createServer } = require("node:http");
const crypto = require("crypto");
const app = express();
const server = createServer(app);

const io = require("socket.io")(server, {
  cors: {
    origin: "*",
  },
});

let rooms = {};

io.on("connection", (socket) => {
  socket.emit("getId", { id: socket.id });

  socket.on("getMeetLink", (data) => {
    const roomId = crypto.randomUUID();
    rooms[roomId] = [];
    console.log(rooms);
    io.to(data.id).emit("meetLink", { roomId });
  });

  socket.on("joinRoom", (data) => {
    socket.join(data.roomId);
    io.to(data.id).emit("onJoinRoom", {
      message: "success",
    });

    socket.to(data.roomId).emit("someone-joining-room", {
      signalData: data.signalData,
      id: data.id,
    });
  });

  socket.on("accept-peer", (data) => {
    io.to(data.id).emit("acceptConnection", { signalData: data.signalData });
  });

  socket.on("sendMessage", (data) => {
    socket.to(data.roomId).emit("incomingMessage", { message: data.message });
  });

  socket.on("disconnect", () => {
    console.log("user disconnected");
  });
});

server.listen(8000, () => {
  console.log("Server running on port", 8000);
});

Client side code:

import React, { useRef, useEffect, useState } from "react";
import {
  Box,
  Button,
  Card,
  CardContent,
  IconButton,
  Input,
  TextField,
} from "@mui/material";
import { MicOff, Mic, Videocam, VideocamOff } from "@mui/icons-material";
import io from "socket.io-client";
import Peer from "simple-peer";
// import {} from "@mui/";

const socket = io.connect("http://localhost:8000");
const HomePage = () => {
  const [videoEnabled, setVideoEnabled] = useState(false);
  const [audioEnabled, setAudioEnabled] = useState(false);
  const [id, setId] = useState(null);
  const [roomId, setRoomId] = useState("");
  const [inRoom, setInRoom] = useState(false);
  const [message, setMessage] = useState("");
  const [myStream, setMyStream] = useState();
  const videoRef = useRef(null);
  const mediaStreams = useRef([]); // Store media streams for cleanup
  const secondVideo = useRef(null);
  const userVideo = useRef();
  const connectionRef = useRef();
  const incomingVids = [];
  useEffect(() => {
    socket.on("getId", (data) => {
      setId(data.id);
      console.log(data.id);
    });

    socket.on("incomingMessage", (data) => {
      console.log(data);
    });

    socket.on("someone-joining-room", (data) => {
      console.log("someOneJoing the room", data);
      const peer = new Peer({
        initiator: false,
        trickle: false,
        stream: myStream,
      });
      peer.on("signal", (signalData) => {
        console.log("sending the signal data back.");
        socket.emit("accept-peer", { signalData: signalData, id: data.id });
      });
      peer.on("stream", (stream) => {
        console.log("someone stream", stream);
        userVideo.current.srcObject = stream;
        incomingVids.push({ stream, id: data.id });
        console.log(incomingVids);
      });

      peer.signal(data.signalData);

      connectionRef.current = peer;
    });
  }, []);

  const getMeetLink = () => {
    console.log("getting meet link");
    socket.emit("getMeetLink", { id });
    socket.on("meetLink", (data) => {
      console.log(data);
      setRoomId(data.roomId);
    });
  };

  const handleInputChange = (event) => {
    setRoomId(event.target.value);
  };

  const handleSetMessageChange = (event) => {
    setMessage(event.target.value);
  };

  const hanndleJoinRoom = () => {
    console.log({ roomId, id });
    const peer = new Peer({
      initiator: true,
      trickle: true,
      stream: myStream,
    });
    peer.on("signal", (data) => {
      console.log("joining room", { roomId, id, signalData: data });
      socket.emit("joinRoom", { roomId, id, signalData: data });
      socket.on("onJoinRoom", (data) => {
        // console.log(data);
        if (data.message == "success") {
          setInRoom(true);
        }
      });
    });

    socket.on("acceptConnection", (vals) => {
      console.log("connection got accepted");
      console.log("Data ", vals);
      peer.signal(vals.signalData);
      peer.on("stream", (stream) => {
        console.log("i joined stream ", stream);
        userVideo.current.srcObject = stream;
      });
    });

    connectionRef.current = peer;
  };

  useEffect(() => {
    // Cleanup function to stop media streams when the component unmounts
    return () => {
      mediaStreams.current.forEach((stream) => {
        stream.getTracks().forEach((track) => track.stop());
      });
    };
  }, [mediaStreams]);

  const handleSendMessage = () => {
    socket.emit("sendMessage", { roomId, message });
  };

  const handleVideoToggle = async () => {
    if (!videoEnabled) {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          video: true,
        });

        setVideoEnabled(true);
        setMyStream(stream);
        mediaStreams.current.push(stream);
        videoRef.current.srcObject = stream;
        videoRef.current.play();
      } catch (error) {
        console.error("Error accessing video:", error);
        setVideoEnabled(false);
      }
    } else {
      const videoStream = mediaStreams.current.find(
        (stream) => stream.getVideoTracks().length > 0
      );
      if (videoStream) {
        videoStream.getTracks().forEach((track) => track.stop());
        videoRef.current.pause();
        videoRef.current.srcObject = null;
        mediaStreams.current = mediaStreams.current.filter(
          (stream) => stream !== videoStream
        );
        setVideoEnabled(false);
      }
    }
  };

  const handleAudioToggle = async () => {
    if (!audioEnabled) {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
        });
        setAudioEnabled(true);
        mediaStreams.current.push(stream);
      } catch (error) {
        console.error("Error accessing audio:", error);
        setAudioEnabled(false);
      }
    } else {
      const audioStream = mediaStreams.current.find(
        (stream) => stream.getAudioTracks().length > 0
      );
      if (audioStream) {
        audioStream.getTracks().forEach((track) => track.stop());
        mediaStreams.current = mediaStreams.current.filter(
          (stream) => stream !== audioStream
        );
        setAudioEnabled(false);
      }
    }
  };

  //   useEffect(() => {
  //     handleAudioToggle();
  //     handleAudioToggle();
  //   }, []);

  return (
    <div
      style={{
        display: "flex",
        // flexDirection: "column",
        alignItems: "center",
        justifyContent: "center",
        height: "100vh",
      }}
    >
      <Card
        style={{
          display: "flex",
          height: "70vh",
          width: "90%",
          // justifySelf: "center",
        }}
        elevation={10}
      >
        <div style={{ flexGrow: 2, margin: "20px" }}>
          <div
            style={{
              display: "flex",
              flexDirection: "column",
              width: "100%",
              height: "100%",
            }}
          >
            <div style={{ display: "flex" }}>
              <video
                style={{
                  // zIndex: 0,
                  width: "calc(50% + 2px)",
                  transform: "scaleX(-1)",
                  height: "80%",
                }}
                playsInline
                muted
                ref={videoRef}
                autoPlay
              ></video>
              <video
                style={{
                  // zIndex: 0,
                  width: "calc(50% + 2px)",
                  transform: "scaleX(-1)",
                  height: "80%",
                }}
                playsInline
                muted
                ref={userVideo}
                autoPlay
              ></video>
            </div>
            <div
              style={{
                height: "20%",
                // backgroundColor: "green",
                display: "flex",
                justifyContent: "center",
                alignItems: "center",
                justifyContent: "space-evenly",
              }}
            >
              <div>
                <IconButton onClick={handleVideoToggle}>
                  {videoEnabled ? <Videocam /> : <VideocamOff />}
                </IconButton>
              </div>
              <div>
                <IconButton onClick={handleAudioToggle}>
                  {audioEnabled ? <Mic /> : <MicOff />}
                </IconButton>
              </div>
            </div>
          </div>
        </div>
        <div style={{ margin: "20px" }}>
          <Card
            style={{ height: "100%", width: "100%", padding: "5px" }}
            elevation={5}
          >
            <CardContent
              style={{
                display: "flex",
                flexDirection: "column",
                justifyContent: "space-evenly",
                alignItems: "center",
                margin: 0,
                padding: 0,
                height: "100%",
              }}
            >
              {!inRoom && (
                <>
                  <div style={{ display: "flex", flexDirection: "column" }}>
                    <TextField
                      id="filled-basic"
                      label="Email"
                      margin="0"
                      variant="filled"
                    />
                    <TextField
                      id="filled-basic"
                      label="Room code"
                      margin="0"
                      variant="filled"
                      value={roomId}
                      onChange={handleInputChange}
                    />
                  </div>
                  <Button
                    variant="contained"
                    style={{ width: "90%" }}
                    onClick={hanndleJoinRoom}
                  >
                    Join
                  </Button>
                  <Button
                    variant="contained"
                    style={{ width: "90%" }}
                    onClick={getMeetLink}
                  >
                    Create Room
                  </Button>
                </>
              )}

              {inRoom && (
                <>
                  <div>{roomId}</div>
                  <Input
                    value={message}
                    onChange={handleSetMessageChange}
                  ></Input>
                  <Button
                    variant="contained"
                    style={{ width: "90%" }}
                    onClick={handleSendMessage}
                  >
                    Send Message
                  </Button>
                </>
              )}
            </CardContent>
          </Card>
        </div>
      </Card>
    </div>
  );
};

export default HomePage;

I tried to debug the signalling data exchange by logging the signal data.

console.log("connection got accepted");
      console.log("Data ", vals);

this does log, but the next peer.on("stream") has no logs.

Upvotes: 0

Views: 98

Answers (0)

Related Questions