React Video Calling Tutorial
This tutorial teaches you how to build Zoom/Whatsapp style video calling experience for your app.
- Calls run on Stream's global edge network for optimal latency & reliability.
- Permissions give you fine grained control over who can do what.
- Video quality and codecs are automatically optimized.
- Powered by Stream's Video Calling API.
Step 0 - Prepare your environment
Confused about "Step 0 - Prepare your environment"?
Let us know how we can improve our documentation:
For this tutorial, you'll need a few tools to be installed on your device. You can skip this step in case you already have them installed.
Step 1 - Set up an app and install React Video SDK
Confused about "Step 1 - Set up an app and install React Video SDK"?
Let us know how we can improve our documentation:
In this step, we will create a new React application using the Vite CLI, and install Stream's React Video SDK. We recommend using Vite because it is fast and easy to use.
Step 2 - Create & Join a call
Confused about "Step 2 - Create & Join a call"?
Let us know how we can improve our documentation:
Open up src/App.tsx
and replace it with this code:
To actually run this sample we need a valid user token. The user token is typically generated by your server side API. When a user logs in to your app you return the user token that gives them access to the call. To make this tutorial easier to follow we'll generate a user token for you:
Please update REPLACE_WITH_USER_ID, REPLACE_WITH_TOKEN and REPLACE_WITH_CALL_ID with the actual values shown below:
Here are credentials to try out the app with:
Property | Value |
---|---|
API Key | Waiting for an API key ... |
Token | Token is generated ... |
User ID | Loading ... |
Call ID | Creating random call ID ... |
Now when you run the sample app it will connect successfully. The text will say "Call ... has 1 participant" (yourself).
Let's review what we did in the above code
User setup
First we create a user object. You typically sync these users via a server side integration from your own backend. Alternatively, you can also use guest or anonymous users.
Client setup
Next we initialize the client by passing the API Key, user and user token.
Create and join call
After the user and client are created, we create a call like this:
As soon as you use call.join()
the connection for video & audio is setup.
In production grade apps, you'd typically store the call
instance in a state variable and take care of correctly disposing it.
Read more in our Joining and Creating Calls guide.
Rendering the UI
Lastly, the UI is rendered by observing the call state through the call state hooks (participants and call state):
You'll find all relevant state for the call in call.state
also exposed through a set of SDK provided hooks.
The documentation on Call and Participant state explains this in further detail.
Step 3 - Joining from the web
Confused about "Step 3 - Joining from the web"?
Let us know how we can improve our documentation:
To make this a little more interactive, let's join the call from your browser.
In your browser, you'll see the text update to 2 participants. Let's keep the browser tab open as you go through the tutorial.
Step 4 - Rendering Video
Confused about "Step 4 - Rendering Video"?
Let us know how we can improve our documentation:
In this next step we're going to render your local & remote participants video.
Let's update our UILayout
component to load the predefined SDK stylesheet, apply the default theme and render the video.
We will now create a MyParticipantList
component that will render the remote participants video.
Now when you run the app, you'll see your local video in a floating video element and the video from your other browser tab. The end result should look somewhat like this:
Let's review the changes we made
ParticipantView is one of our primary low-level components.
It only displays the video comes with some default UI elements, such as participant's name. The video is lazily loaded, and only requested from the video infrastructure if you're actually displaying it. So if you have a video call with 200 participants, and you show only 10 of them, you'll only receive video for 10 participants. This is how software like Zoom and Google Meet make large calls work.
MyFloatingLocalParticipant
renders a display of your own video.
MyParticipantList
renders a list of remote participants.
Step 5 - A Full Video Calling UI
Confused about "Step 5 - A Full Video Calling UI"?
Let us know how we can improve our documentation:
The above example showed how to use the call state and React to build a basic video UI. For a production version app, you'd want a few more UI elements:
- Indicators of when someone is speaking
- Quality of their network connection
- Layout support for more than two participants
- Labels for the participant names
- Call controls
Stream React Video SDK ships with several React components to make this easy. You can customize the components with theming, arguments and swapping parts of them. This is convenient if you want to quickly build a production ready calling experience for you app. (and if you need more flexibility, many customers use the above low level approach to build a UI from scratch).
To render a full calling UI, we'll leverage the SpeakerLayout component for arranging the video elements, and the CallControls component for rendering the call controls. Also, we are going to introduce a minimalistic CSS file to make the UI look a bit nicer.
The final UI should look like this:
When you now run your app, you'll see a more polished video UI. It supports reactions, screensharing, active speaker detection, network quality indicators etc. The most commonly used UI components are:
- ParticipantView: For rendering video and automatically requesting video tracks when needed. Most of the Video components are built on top of this.
- DefaultParticipantViewUI: The participant's video + some UI elements for network quality, reactions, speaking etc.
ParticipantView
uses this UI by default. - PaginatedGridLayout: A grid of participants. Support pagination out of the box.
- SpeakerLayout: A layout that shows the active speaker in a large video, and the rest of the participants a scrollable bar.
- CallControls: A set of buttons for controlling your call, such as changing audio and video mute state, switching mic or a camera.
The full list of UI components is available in the docs.
Because of simplicity, in this tutorial, we are skipping some of the best practices for building a production ready app. Take a look at our sample app linked at the end of this tutorial for a more complete example.
Step 6 - Customizing the UI
Confused about "Step 6 - Customizing the UI"?
Let us know how we can improve our documentation:
You can customize the UI by:
- Building your own UI components (the most flexibility, build anything).
- Mixing and matching with Stream's UI Components (speeds up how quickly you can build custom video UIs).
- Theming (basic customization of colors, fonts etc).
You can find many examples on how to build your own custom UI components in our UI Cookbook docs.
Step 7 - Enable Noise Cancellation
Confused about "Step 7 - Enable Noise Cancellation"?
Let us know how we can improve our documentation:
Background noise during a call session is never pleasant for the call participants.
Our SDK provides a plugin that helps to greatly reduce the unwanted noise caught by your microphone. Read more on how to enable it here.
Recap
Confused about "Recap"?
Let us know how we can improve our documentation:
Please do let us know if you ran into any issues while building an video calling app with React Video SDK. Our team is also happy to review your UI designs and offer recommendations on how to achieve it with Stream.
To recap what we've learned:
- To set up a call:
const call = client.call('default', '123');
. - The call type (
'default'
in the above case) controls which features are enabled and how permissions are setup. - When you join a call, realtime communication is setup for audio & video calling:
call.join()
. - Call state
call.state
and helper state access hooks exposed throughuseCallStateHooks()
make it easy to build your own UI ParticipantView
is the low level component that renders video, plays audio and by default, it utilizesDefaultParticipantViewUI
that adds UI elements as participant name, network quality, etc...
We've used Stream's Video Calling API, which means calls run on a global edge network of video servers. By being closer to your users the latency and reliability of calls are better. The React SDK enables you to build in-app video calling, audio rooms and livestreaming in days.
The source code for the final app can be found in our GitHub repository.
We hope you've enjoyed this tutorial and please do feel free to reach out if you have any suggestions or questions.
Final Thoughts
In this video app tutorial we built a fully functioning React messaging app with our React SDK component library. We also showed how easy it is to customize the behavior and the style of the React video app components with minimal code changes.
Both the video SDK for React and the API have plenty more features available to support more advanced use-cases.
Give us Feedback!
Did you find this tutorial helpful in getting you up and running with React for adding video to your project? Either good or bad, we’re looking for your honest feedback so we can improve.