DEV Community

Cover image for Video call app using webrtc
Tejendra Singh Rajawat
Tejendra Singh Rajawat

Posted on

Video call app using webrtc

Hi there, today we are creating video call app using webRtc, firebase and react.js.
You can also test code available here -> Github

1. Create Room ->

First, create realtime database in firebase and create a roomId using urlparams, which is a random created key in firebase database.

// reference of RD
let RD = firebase.database().ref();
// url params
const URLPARAMS = new URLSearchParams(window.location.search);
// get id from url
const roomId = URLPARAMS.get("id");

if (roomId) {
  // set room id as child
  RD = RD.child(roomId);
} else {
  // create id and set to roomid
  RD = RD.push();
  window.history.replaceState(null, "meet", "?id=" + RD.key);
}
Enter fullscreen mode Exit fullscreen mode

2. create participant object -

now we will create an object participant in our roomId which contains audio,video and screen share information. It will look like this -
participant data
To get this output ,we will do as follow , you can get userName as string or get it dynamically too.

const participantDb = RD.child("participant");
  useEffect(() => {
    //check for value if true
    connectedRef.on("value", (snap) => {
      if (snap.val()) {
        // create values to push
        const defaultPref = {
          audio: true,
          video: false,
          screen: false,
        };
        // push data to participant
        const pushedDataOfParticipant = participantDb.push({
          userName: 'tejendra',
          preference: defaultPref,
        });
        // remove user when he quit or close browser
        pushedDataOfParticipant.onDisconnect().remove();
      }
    });
  }, []);
Enter fullscreen mode Exit fullscreen mode

3. Peer Connection -

Now most important part of webrtc is create peer to peer connection so we can communication in realtime, for that we need to follow below image.

Image description

For signaling we are using firebase.
First user will create a offer for others to join and when someone joins then one answer will be created and they will communicate using signaling.

i. create offer -

export const createOffer = async (peerConnection, receiverId, createdID) => {
  const currentParticipantRef = participantRef.child(receiverId);
  peerConnection.onicecandidate = (event) => {
    event.candidate &&
      currentParticipantRef
        .child("offerCandidates")
        .push({ ...event.candidate.toJSON(), userId: createdID });
  };

  const offerDescription = await peerConnection.createOffer();
  await peerConnection.setLocalDescription(offerDescription);

  const offer = {
    sdp: offerDescription.sdp,
    type: offerDescription.type,
    userId: createdID,
  };

  await currentParticipantRef.child("offers").push().set({ offer });
};

export const initializeListensers = async (userId) => {
  const currentUserRef = participantRef.child(userId);

  currentUserRef.child("offers").on("child_added", async (snapshot) => {
    const data = snapshot.val();
    if (data?.offer) {
      const pc =
        store.getState().participants[data.offer.userId].peerConnection;
      await pc.setRemoteDescription(new RTCSessionDescription(data.offer));
      await createAnswer(data.offer.userId, userId);
    }
  });

  currentUserRef.child("offerCandidates").on("child_added", (snapshot) => {
    const data = snapshot.val();
    if (data.userId) {
      const pc = store.getState().participants[data.userId].peerConnection;
      pc.addIceCandidate(new RTCIceCandidate(data));
    }
  });

  currentUserRef.child("answers").on("child_added", (snapshot) => {
    const data = snapshot.val();
    if (data?.answer) {
      const pc =
        store.getState().participants[data.answer.userId].peerConnection;
      const answerDescription = new RTCSessionDescription(data.answer);
      pc.setRemoteDescription(answerDescription);
    }
  });

  currentUserRef.child("answerCandidates").on("child_added", (snapshot) => {
    const data = snapshot.val();
    if (data.userId) {
      const pc = store.getState().participants[data.userId].peerConnection;
      pc.addIceCandidate(new RTCIceCandidate(data));
    }
  });
};
Enter fullscreen mode Exit fullscreen mode

ii. create answer -

const createAnswer = async (otherUserId, userId) => {
  const pc = store.getState().participants[otherUserId].peerConnection;
  const participantRef1 = participantRef.child(otherUserId);
  pc.onicecandidate = (event) => {
    event.candidate &&
      participantRef1
        .child("answerCandidates")
        .push({ ...event.candidate.toJSON(), userId: userId });
  };

  const answerDescription = await pc.createAnswer();
  await pc.setLocalDescription(answerDescription);

  const answer = {
    type: answerDescription.type,
    sdp: answerDescription.sdp,
    userId: userId,
  };

  await participantRef1.child("answers").push().set({ answer });
};
Enter fullscreen mode Exit fullscreen mode

That's it, now you can create a simple UI component and start realtime chat with audio, video and screen share.

Image description

Top comments (0)