Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
September 14, 2020 10:13 pm GMT

Build a video chat app in minutes with React and daily-js

With video chat apps on the rise for, well, obvious reasons, its increasingly important to be able to add video call capabilities to apps and websites quickly. The more customizable those video calls can be, the better for building unique user experiences.

This post walks you through how to build a custom video chat app with React and the Daily API.

Two people smiling in a video call in the React demo app

What well build

In our app, when a participant clicks to start a call, theyll create a meeting room, pass the rooms URL to a new Daily call object, and join the call. The call object keeps track of important information about the meeting, like other participants and the things they do on the call (e.g. mute their mic or leave), and it leaves your app's UI entirely up to you. When the last participant leaves the room, the call object is destroyed.

What youll need to build it

  • Daily account: Sign up for an account if you dont have one already.
  • Cloned daily-demos Github repository: The fastest way to follow along with this tutorial and get a demo app up and running is by cloning this repo.
  • Familiarity with React: In this post we skip over a lot of the code that isnt related to Daily, so it could be worth brushing up on React and/or hooks [0].

Once you have those things, were ready to get started!

Build and run the app

After youve cloned the repository:

cd daily-demosnvm icd react-demonpm inpm run dev

Now, open your browser and head to localhost:<port>, using the port printed in the terminal after running the above. You should have an app running locally that mirrors the live demo: you can click to start a call, and share the link with another participant or yourself in a new tab.

Anakin Skywalker in Phantom Menace exclaims its working

Its great that its working...but how is it working?

How the app works

Daily concepts

Before diving into the code, lets cover some Daily fundamentals.

The call object

A Daily call object is like a direct line to the Daily API. It gives us the finest-grained control over a video call, letting us access its lowest level foundations, like participant video and audio tracks. Invoking DailyIframe.createCallObject() creates a call object. Once created, we pass a meeting room URL to the call object to join a call.

In addition to all of that, the call object keeps track of our calls state, both meeting state and participant state.

State #1: meeting state

Meeting state tracks where a current (often called "local") participant is in the life of a call. A participant can start to join a call, be in a call, have left a call, or be experiencing an error.

We can check a calls meeting state via the call object with callObject.meetingState(). If a participant is joining a meeting, the "joining-meeting" event will be returned, for example.

Meeting state changes trigger events like "joining-meeting." We can add event listeners for those state changes with callObject.on().

State #2: participant state

Participant state monitors all participants on the call (including the current user) and the video, audio, or other media theyre sharing with everybody else.

callObject.participants() returns a set of participant objects, keyed by an ID (or "local", for the current user). Each participant object includes fields like audioTrack and videoTrack.

The events "participant-joined", "participant-left", and "participant-updated" broadcast changes to participant state. The first two are only sent when participants other than the current local participant join or leave, while the latter fires on changes like camera and microphone toggling for any participant, including local.

Now that weve covered the Daily call object and its states, were ready to look at our app.

Whats happening in the code

App.js: Creating, joining, and leaving a call

Before we get into the details of each stage of a meeting, lets look at how we wire up our top-level event listeners. In App.js, we listen for changes to callObject.meetingState(), so we can update the UI for the local participant depending on where theyre at in their user journey: in a call, out of a call, or experiencing errors:

When a local participant leaves a meeting, we call callObject.destroy(). We do this to clean up our call object's global footprint, to open the door for our app to create another call object in the future with different create-time options.

Creating a call

When a participant clicks to start a call, they invoke the createCall() function to create a short-lived, demo-only room.

In real production code you'll want to create rooms by calling the Daily REST API from your backend server, to avoid storing API keys in your client-side JavaScript [1].

Joining a call

Once we have a room, well join it by invoking the .join() method on the call object [2].

Leaving a call

When a participant clicks the Leave button, well initiate that process by invoking the leave() method on the call object [3, 4].

Call.js and callState.js: Using state to determine the call display

We now know how different operations in a call take place, so the next step is to know how those operations affect our display. This involves keeping tabs on participant state in order to display the call's participants and their video and audio streams.

While App.js listened to callObject.meetingState(), in Call.js well listen for callObject.participantState() and update our component state accordingly [5].

Our demo app displays each participant (including the current user) as their own "tile", and also displays any screen share as its own tile independent of the participant doing the sharing.

To accomplish this, we map callObject.participantState() to the calls component state, specifically into a set of "call items" in callState.js:

Each call item corresponds to a call participant, storing the participants video track, audio track, and a boolean that notes whether or not a participant is in the process of joining a call [6].

To populate the call items, we call our getCallItems() function, which loops over participant state:

We import callState in Call.js, where we invoke the getTiles() function to pass participant video and audio tracks to their respective tile components.

Now lets take a closer look at those tiles.

Pink and yellow tiles shift colors

Tile.js: displaying each participants video stream

Each of our tile components contains either a <video> and/or an <audio> element. Each tag references its respective DOM element [7]. Note the autoPlay muted playsInline attribute. These are the set of attributes that will let your audio and video play automatically on Chrome, Safari, and Firefox.

Next up: give participants control over whether or not they display their videos and share their audio or screens.

Tray.js: Enable participant controls

Once again we'll use participant state to determine whether we're actively sharing audio, video, and our screen.

Well look specifically at callObject.participants().local, since were concerned about adjusting the user interface for the current, or local, user. The only event we need to listen to is "participant-updated" [8].

With our event listener handling state updates, we can wire up our buttons to handle the relevant callObject methods to control user input: .setLocalVideo, .setLocalAudio, and .startScreenShare or .stopScreenShare.

What to add next

Congratulations! If youve read this far, you now have an overview of your custom video chat app. To dig even deeper into the code, have a look at how the demo handles edge cases over on the Daily blog. Or, to see everything else the Daily APIs have to offer, grab a cup of tea and head over to docs.daily.co for some fun evening reading.

Thanks for reading! As always, we'd love to know what you think and how we can better help you to build that next great video chat app, so please don't hesitate to reach out.

Dinaosaur in a cup that has a tea rex tea bag

Footnotes

[0] If youd like to get familiar with React and come back later, check out the many great resources on DEV (like Ali Spittels intro), or the React docs for more on hooks.
[1] Our teammate wrote an excellent post on how to set up an instant Daily server on Glitch.
[2] Note that, because we invoke destroy() on our call object after each call ends, we need to create a new call object in order to join a room. This is not strictly necessary you could hold onto a single call object for the lifetime of your app if you so desired, but, as we mentioned earlier, we prefer this approach to leave the door open for a future differently-configured call object.
[3] You mightve noticed that both the join() and leave() call object operations are asynchronous, as is destroy(). To avoid undefined behavior and app errors, like leaving and destroying a call object simultaneously, it's important to prevent triggering one call object operation while another is pending. A straightforward way to do this is to use meeting state to update relevant buttons' idle states so that the user can't start an operation until it's safe, like we do in our demo app.
[4] Because destroy() is asynchronous, the DailyIframe.createCallObject() must only be invoked once destroy()'s Promise has been resolved.
[5] In the demo app, we use a reducer to update the component state.
[6] We only set isLoading to true if weve never received audio or video tracks for a participant.
[7] We did that so we could programmatically set their srcObject properties whenever our media tracks change (see lines 18-31 in Tile.js).
[8] You might remember that "participant-joined" and "participant-left" are only ever about other (not local) participants.


Original Link: https://dev.to/trydaily/build-a-video-chat-app-in-minutes-with-react-and-daily-js-481c

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To