How to add Video Call and Voice Call Functionality in a Full Stack Whatsapp Clone

Written by kishansheth | Published 2023/07/26
Tech Story Tags: nextjs | web-development | reactjs | nodejs | zegocloud-sdk | video-chat-app | web-design | tailwindcss

TLDRThis blog post demonstrates how to integrate Zegocloud's services for Video Call and Voice Call functionality into a Full Stack WhatsApp Clone using React and Zegocloud's SDKs. The WhatsApp Clone offers features like login with Google using Firebase, real-time messaging with Socket.io, voice notes with live audio waveforms, support for emojis, and more. The integration process involves creating a Zegocloud account, configuring a Zegocloud project for Video and Voice Calls, and installing the Zegocloud React SDK. The post provides step-by-step instructions to join a room, create local audio and video streams, start a video call, and render video streams. The blog post aims to help developers build video call apps using Zegocloud and React, and it encourages readers to follow along with a YouTube tutorial for creating the complete WhatsApp Clone.via the TL;DR App

In this article I will show you how we integrated Zegocloud’s services for Video Call and Voice Call functionality with my Full Stack Whatsapp Clone Video on Youtube.

Features of Whatsapp Clone

  • Login with Google using Firebase: Seamlessly sign in with your Google account via Firebase integration.
  • Switch between multiple databases using Prisma: Customize your database preferences to suit your needs effortlessly.
  • Send and Receive Messages using Sockets: Real-time messaging capabilities using Socket.io for instant communication.
  • Voice Call and Video Call Feature: Enjoy crystal clear voice and video calls within the app. This functionality is built using Zegocloud Voice Call and Video Call services.
  • Voice Notes with Live Audio Waveforms: Send and receive voice notes accompanied by live audio waveforms for an enhanced messaging experience.
  • Support for Emoji: Express yourself with a wide range of emojis to add fun and emotions to your conversations.
  • Send Images: Share images with your friends and loved ones effortlessly.
  • Online/Offline Functionality: Easily identify the online and offline status of your contacts.
  • Search Messages: Quickly find specific messages using the search functionality.
  • Capture Photo From Camera: Take instant photos using your device's camera and send them instantly.
  • Message Read Status: Know when your messages have been read by your recipients.
  • Message Time: Stay updated with the time stamps of messages for better organization.

Tech Stack of Whatsapp Clone

App Screenshots

Introducing Zegocloud

ZEGOCLOUD is a cloud-native solution designed for facilitating video calls. By granting developers access to a comprehensive suite of UIKIt’s and SDKs, ZEGOCLOUD empowers them to effortlessly construct their own video and voice calling applications.

Creating Zegocloud Account

Head over to Zegocloud and create an account. Zegocloud provides free 10,000 minutes of free trial to get you started.

Create a new Zegocloud Project

Now in your Zegocloud console click on create your first project as shown in the image below.

Select a project use case

Zegocloud provides various pre configured use cases for your apps; we are going to select the Video and Voice Call Option and click Next.

Project Name and Scnearios

Now in the next screen you need to give a unique project name. We are going to give the name as whastasppclone.

Next, we will select the project Scenario.

Zegocloud provides two scenarios: The UIKIT’s and the SDKS’s.

Here we are going to select the Start with the Customs SDK’s option.

With this Zegolcoud will start configuring your app. This process will take few minutes.

Now all the things are configured for Zegocloud.

Install the Zegocloud package for the Whatsapp Clone

You can install the ZEGOCLOUD React SDK using the following command:

npm i zego-express-engine-webrtc

This will install the ZEGOCLOUD React SDK into your project.

Import the ZEGOCLOUD SDK into your project and initialize it

In your project's container.js file, import the ZEGOCLOUD SDK and initialize the zegocloud app by the function as follows:

import React from "react";
import { ZegoExpressEngine } from "zego-express-engine-webrtc";

function App() {
  useEffect(() => {
    const zg = new ZegoExpressEngine(
      process.env.NEXT_PUBLIC_ZEGO_APP_ID,
      process.env.NEXT_PUBLIC_ZEGO_SERVER_ID
    );
  }, []);
  return (
    <div>
      <div id="local-video"></div>
      <div id="remote-video"></div>
    </div>
  );
}

export default App;

In the above step, we have utilized the useEffect hook to initialize the ZegoClouds library by passing the app ID and server secret as parameters.

Now you need the APP_ID and the SERVER_ID from your zegocloud project configuration screen.

You need to paste those in the Next Config file in your Next.js App

Join a Room

import React from "react";
import { ZegoExpressEngine } from "zego-express-engine-webrtc";

function App() {
  useEffect(() => {
    const initializeApp = async () => {
      const zg = new ZegoExpressEngine(
        process.env.NEXT_PUBLIC_ZEGO_APP_ID,
        process.env.NEXT_PUBLIC_ZEGO_SERVER_ID
      );
      await zg.loginRoom(
        "zego-room",
        token,
        { userID: "123", userName: "kishan" },
        { userUpdate: true }
      );
  }, []);
  return (
    <div>
      <div id="local-video"></div>
      <div id="remote-video"></div>
    </div>
  );
}

Now in this step, we have joined the passing of the token, userId, and userName, and the userUpdate status.

Create a local audio and video stream.

import React from "react";
import { ZegoExpressEngine } from "zego-express-engine-webrtc";

function App() {
  useEffect(() => {
    const initializeApp = async () => {
      const zg = new ZegoExpressEngine(
        process.env.NEXT_PUBLIC_ZEGO_APP_ID,
        process.env.NEXT_PUBLIC_ZEGO_SERVER_ID
      );
      await zg.loginRoom(
        "zego-room",
        token,
        { userID: "123", userName: "kishan" },
        { userUpdate: true }
      );

      const localStream = await zg.createStream({
        camera: {
          audio: true,
          video: true,
        },
      });
      // Get the audio tag.
      const localAudio = document.getElementById("local-video");

      const videoElement = document.createElement("video");
      videoElement.id = "local-video";
      videoElement.className = "h-28 w-32";
      videoElement.autoplay = true;
      videoElement.muted = false;

      videoElement.playsInline = true;

      localAudio.appendChild(videoElement);

      const td = document.getElementById("audio-local");
      td.srcObject = localStream;
    };
  }, []);
  return (
    <div>
      <div id="local-video"></div>
      <div id="remote-video"></div>
    </div>
  );
}

We have created the video elements here where we will be actually displaying the video streams of our local webcam.

Start a video call.

import React from "react";
import { ZegoExpressEngine } from "zego-express-engine-webrtc";

function App() {
  useEffect(() => {
    const initializeApp = async () => {
      const zg = new ZegoExpressEngine(
        process.env.NEXT_PUBLIC_ZEGO_APP_ID,
        process.env.NEXT_PUBLIC_ZEGO_SERVER_ID
      );
      await zg.loginRoom(
        "zego-room",
        token,
        { userID: "123", userName: "kishan" },
        { userUpdate: true }
      );

      const localStream = await zg.createStream({
        camera: {
          audio: true,
          video: true,
        },
      });
      // Get the audio tag.
      const localAudio = document.getElementById("local-video");

      const videoElement = document.createElement("video");
      videoElement.id = "local-video";
      videoElement.className = "h-28 w-32";
      videoElement.autoplay = true;
      videoElement.muted = false;

      videoElement.playsInline = true;

      localAudio.appendChild(videoElement);

      const td = document.getElementById("audio-local");
      td.srcObject = localStream;
    };

    const streamID = "123" + Date.now();

    zg.startPublishingStream(streamID, localStream);
  }, []);
  return (
    <div>
      <div id="local-video"></div>
      <div id="remote-video"></div>
    </div>
  );
}

Here we have started publishing our local stream to the specified room.

Render the video streams.

import React from "react";
import { ZegoExpressEngine } from "zego-express-engine-webrtc";

function App() {
  useEffect(() => {
    const initializeApp = async () => {
      const zg = new ZegoExpressEngine(
        process.env.NEXT_PUBLIC_ZEGO_APP_ID,
        process.env.NEXT_PUBLIC_ZEGO_SERVER_ID
      );

      zg.on(
        "roomStreamUpdate",
        async (roomID, updateType, streamList, extendedData) => {
          if (updateType == "ADD") {
            const rmVideo = document.getElementById("remote-video");
            const vd = document.createElement("video");
            vd.id = streamList[0].streamID;
            vd.autoplay = true;
            vd.playsInline = true;
            vd.muted = false;
            if (rmVideo) {
              rmVideo.appendChild(vd);
            }
            zg.startPlayingStream(streamList[0].streamID, {
              audio: true,
              video: true,
            }).then((stream) => {
              vd.srcObject = stream;
            });

            // New stream added, start playing the stream.
          } else if (updateType == "DELETE" && zg && streamList[0].streamID) {
            zg.stopPublishingStream(streamList[0].streamID);
            zg.logoutRoom("123");
          }
        }
      );

      await zg.loginRoom(
        "zego-room",
        token,
        { userID: "123", userName: "kishan" },
        { userUpdate: true }
      );

      const localStream = await zg.createStream({
        camera: {
          audio: true,
          video: true,
        },
      });
      // Get the audio tag.
      const localAudio = document.getElementById("local-video");

      const videoElement = document.createElement("video");
      videoElement.id = "local-video";
      videoElement.className = "h-28 w-32";
      videoElement.autoplay = true;
      videoElement.muted = false;

      videoElement.playsInline = true;

      localAudio.appendChild(videoElement);

      const td = document.getElementById("audio-local");
      td.srcObject = localStream;
    };

    const streamID = "123" + Date.now();

    zg.startPublishingStream(streamID, localStream);
  }, []);
  return (
    <div>
      <div id="local-video"></div>
      <div id="remote-video"></div>
    </div>
  );
}

Now as soon as the other user joins the room, we want to display the upcoming video stream and render it to the DOM.

Conclusion

With this we have successfully integrated the Voice Call and Video Call in our Whatsapp Clone uisng Zegocloud’s Voice and Video Call SDK’s.

We hope that this blog post has helped you to get started with building video call apps using Zegocloud and React.

For more information, please refer to the Zegocloud documentation.

You can follow along my Youtube Tutorial to create the entire Whatspp Clone using Zegocloud’s SDK’s.

https://www.youtube.com/watch?v=keYFkLycaDg&embedable=true


Written by kishansheth | I am a kind of guy who likes programming at its core; excellent communication as well as leadership skills.
Published by HackerNoon on 2023/07/26