Video call app using webrtc
Tags: react, javascript, webrtc, videocall
Published: 2022-09-06 12:21:59

Hi there, today we are creating video call app using webRtc, firebase and react.js.
You can also test code available here -> [Github](https://github.com/Tejendrasrajawat/webRtc)

## 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);
}
```

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tu6qwfequblc57mt6z4g.png)
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();
      }
    });
  }, []);
```
## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llkri6nfo5hweh8eeph1.png)

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));
    }
  });
};
```

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 });
};
``` 

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

 
![Image description](https://user-images.githubusercontent.com/38542608/182521898-c72f5d7e-4460-4e01-a050-2db0eca6fa32.png)