Build a Scalable Video Chat App with Agora in Laravel
Tags: agora, videochat, laravel, websockets
Published: 2021-01-17 00:45:35



#Introduction
Laravel is a powerful PHP framework that aims to make the web development process easier without sacrificing application functionality. This is especially true when you try to build a video chat app with Laravel.

Previously, I built a video chat app with WebRTC and Laravel and wrote about it here: <a href="https://dev.to/mupati/adding-video-chat-to-your-laravel-app-5ak7" target="_blank">Adding Video Chat To Your Laravel App</a>. WebRTC is only one of the ways that people can implement video chat features. Companies like <a href="https://www.agora.io/en/" target="_blank">Agora</a> also provide a fully packaged video chat SDK to provide a high-quality Real-Time Engagement video chat experience. As someone who has WebRTC development experience, I can tell you there are some limitations with WebRTC, such as:
<ol>
<li><strong>Quality of experience:</strong> Since WebRTC is transmitted over the Internet, which is a public domain, the quality of experience is hard to guarantee.</li>
<li><strong>Scalability:</strong> Scalability is fairly limited on group video calls due to the peer-to-peer nature of WebRTC.</li>
</ol>

After I was introduced to Agora, I was impressed that setting up the same video call feature is easier with Agora than with WebRTC. Let me walk you through building a video chat app with Agora in Laravel.

# Why Agora Is the Preferred Solution
After building a video chat app with Agora, I want to highlight some of the advantages:
<ol>

<li>There's one SDK for everything - voice, video, live streaming, screen sharing, and so on.</li>
</li>

<li>I didn't have to set up a turn server with <a href="https://github.com/coturn/coturn" target="_blank">coturn</a> on Amazon EC2 as I did in the other implementation to relay traffic between peers on different networks.</li>

<li>You get <a href="https://www.agora.io/en/pricing/" target="_blank">10,000 minutes every month </a>free, and this gives you the flexibility to develop your solution prototype for free.</li>

<li>You don't have the challenge of managing the underlying infrastructure supporting the video call functionality.</li>

<li>Intuitive API documentation is available.</li>

</ol>

# Prerequisites
<ul>

<li>A Laravel project with VueJs authentication with some created users. 
You can download the following base project to get started: <a href="https://github.com/Mupati/laravel-8-vue-auth-starter" target="_blank">Laravel 8 Vue Auth Starter</a></li>

<li>An understanding of <a href="https://laravel.com/docs/8.x/broadcasting" target="_blank">Laravel's broadcasting and event system</a> and WebSockets in general.</li>

<li>A free pusher account on <a href="https://pusher.com/" target="_blank">pusher.com</a></li>

<li>An Agora Account: <a href="https://www.agora.io/en/blog/how-to-get-started-with-agora?utm_source=medium&utm_medium=blog&utm_campaign=Build_A_Scalable_Video_Chat_App_With_Agora_In_Laravel" target="_blank">How to get started with Agora</a></li>

</ul>


# Project Setup
<ol>
<li>Open your terminal or console and navigate to your Laravel project directory.</li>
<li>Install the necessary packages. <br/><br/>

```bash
composer require pusher/pusher-php-server "~4.0"
npm install --save laravel-echo pusher-js
```
</li>
<li>Download the AgoraDynamicKey PHP code from the Agora repository: <a href="https://github.com/AgoraIO/Tools/tree/master/DynamicKey/AgoraDynamicKey/php" target="_blank">AgoraDynamicKey</a>
Keep the downloaded folder in a location outside the project folder. Some files from the folder will be copied into our project when we're configuring the back end.</li>
</ol>


# Configuring the Backend
We will set up the various controllers and classes with methods needed to generate the Agora token to establish a call. Laravel's broadcasting system will also be activated.
We begin with the endpoints that will be accessed from the front end.

### 1. Add Application Routes.
Add the following code to routes/web.php.
{% gist https://gist.github.com/Mupati/c6856332a0a2a8207ed2a8d2cfecb426 %}


### 2. Activate Laravel's Broadcasting System.
Uncomment BroadcastServiceProvider in config/app.php in your project folder.
```diff
+ App\Providers\BroadcastServiceProvider::class
- //App\Providers\BroadcastServiceProvider::class 
```

### 3. Create a presence channel in routes/channels.php
We get to know online users by looking at who has subscribed to this channel on the front end. We return their ID and name.
{% gist https://gist.github.com/Mupati/e2ee893b467cb8fab6be73eb9c5340c2 %}

### 4. Create an event for making a call named MakeAgoraCall
This event will be used to make a call by broadcasting some data over the agora-online-channel. Run the following command in your terminal/console:
```bash
php artisan make:event MakeAgoraCall
```
Add the following code to MakeAgoraCall.php
{% gist https://gist.github.com/Mupati/d3ae9fbc829f55791fbbf7eef29e7df8 %}

### 5. Add the downloaded AgoraDynamicKey generator files

<ul>
  <li>Open your command line, and in your project's app directory create a directory named Class along with a subdirectory named AgoraDynamicKey. <br/><br/>
```bash
cd app
mkdir -p Class/AgoraDynamicKey
```
</li>

<li>Open the AgoraDynamicKey folder that was downloaded as part of the project setup. Next, copy the AccessToken.php and RtcTokenBuilder.php from the src directory into the AgoraDynamicKey directory that was created in the previous step.</li>

<li>Open AccessToken.php and RtcTokenBuilder.php, and add the project's namespace to make them accessible in a controller.</li>
</ul>

#### RtcTokenBuilder.php becomes:
{% gist https://gist.github.com/Mupati/0da81de7706654daed1f96afdbd64255 %}

#### AccessToken.php becomes:
{% gist https://gist.github.com/Mupati/f46c0e46552ded8f4deb7480368325e0 %}

### 6. Create the AgoraVideoController.php
Next, create the AgoraVideoController using the command line.

```bash
php artisan make:controller AgoraVideoController
```
Add the following code to AgoraVideoController.php:
{% gist https://gist.github.com/Mupati/45244c79a8a86673dafa7f91cb577a59 %}

#### Breakdown of Methods in the AgoraVideoController
<ul>
<li><strong>index:</strong> To view the video call page.</li>
<li><strong>token:</strong> To generate the Agora dynamic token. The token generation code is taken from sample/RtcTokenBuilderSample.php, which can be found in the files downloaded during the project setup.</li>
<li><strong>callUser:</strong> To call a particular user by broadcasting a MakeAgoraCall event across a Laravel presence channel that I've named agora-online-channel. All logged-in users subscribe and listen to events on this channel.</li>
</ul>
The data received from the MakeAgoraEvent by the users subscribed to the agora-online-channel contains the following:
<ul>
<li><strong>userToCall:</strong> This is the ID of the user who is supposed to receive a call from a caller.</li>
<li><strong>channelName:</strong> This is the call channel that the caller has already joined on the front end. This is a channel created with the Agora SDK on the front end. It is the room the caller has already joined, waiting for the callee to also join to establish a call connection.</li>
<li><strong>from:</strong> The ID of the caller.</li>
</ul>

From the MakeAgoraEvent, a user can determine whether they are being called if the userToCall value matches their ID. We show an incoming call notification with a button to accept the call.
They know who the caller is by the value of from.


# Configuring the Front End
We are going to create the user interface for making and receiving the video call with the ability to toggle the on and off states of the camera and the microphone.

### 1. Add a link to the Agora SDK
Add the following <script src="https://cdn.agora.io/sdk/release/AgoraRTCSDK-3.3.1.js"></script> to the head tag of resources/views/layouts/app.blade.php.<br/><br/>
It then becomes:
{% gist https://gist.github.com/Mupati/f8d0b540c5fd5f3516939e71bca3a478 %}

### 2. Instantiate Laravel Echo and Pusher Instantiate Laravel Echo and Pusher in resources/js/bootstrap.js by uncommenting the following block of code:
{% gist https://gist.github.com/Mupati/513cfced1c0a8c313f8fef26fdc5afea %}

### 3. Create an Agora chat component
On your terminal or command line, create a component called AgoraChat.vue with the following command:
```bash
touch resources/js/components/AgoraChat.vue
```
Add the following code:
{% gist https://gist.github.com/Mupati/dd063d90f697902899746ffbfbff1f80 %}

#### Breakdown of the AgoraChat Component
On the AgoraChat page, we display buttons that bear the name of each registered user and whether they are online or offline at the moment.


To place a call, we click the button of a user with online status. An online user indicates one who is readily available to receive a call. For our demo, we see a list of users. The user named Bar is indicated as being online. The caller named Foo can call Bar by clicking the button.

![Users to Call](https://cdn-images-1.medium.com/max/800/1*CVFUgDtUg_e4ra-emGsZTw.png)
Bar gets an incoming call notification with Accept and Decline buttons and the name of the caller.

![Call Notification](https://cdn-images-1.medium.com/max/800/1*_lMG4lzRZrvuJGFlfdsdIw.png)

From the call notification image above, we see that the caller's name is Foo. Bar can then accept the call for a connection to be established.


The following diagram explains the call logic in terms of the code:

![The Call Logic](https://cdn-images-1.medium.com/max/2560/1*EaEUAS5kf7Ku676T7n6h2w.jpeg)

### 4. Register the AgoraChat.vue component
Add the following code to resources/js/app.js:
{% gist https://gist.github.com/Mupati/5faf924330043c608bb9ae892fd98557 %}

### 5. Create an Agora chat view
On your terminal or command line, create a view called agora-chat.blade.php with the following command:
```bash
touch resources/views/agora-chat.blade.php
```
Add the following code to the agora-chat.blade.php:

{% gist https://gist.github.com/Mupati/232ad6d601b2ab50c3681d62586c80a5 %}

### 6. Update env variables with Pusher and Agora keys
The .env file is located at the root of your project folder. Add the credentials you got from Agora and Pusher.
{% gist https://gist.github.com/Mupati/d8eeb69eafe5a1bdd207c89647702b85 %}

# Testing
<ol>
<li>
Start the Laravel development server from your terminal.<br/>br/>
```bash
php artisan serve
```
</li>
<li>Open another terminal and run the front end.
<br/><br/>
```bash
npm run dev
```
</li>
<li>
Open two different browsers or two instances of the same browser, with one instance in incognito mode, and go to http://127.0.0.1:8000/agora-chat.
</li>
<li>You are presented with a login page if you are not already logged in.</li>
<li>After successful login, you are automatically redirected to the video chat page, where you see the buttons with names of the users with an indication of their online status.
</li>
<li>In each of the browsers you opened, the other users registered on the application are displayed as described in 5.</li>
<li>In one browser, you can call the user who is logged in on the other browser by clicking the button that bears their name.</li>
<li>The other user is prompted to click the Accept button to fully establish the call.</li>
</ol>

#### Video Demonstration of the Video Call
To confirm that your demo is functioning properly, see my demo video as an example of how the finished project should look and function:
{% youtube GCAuXcy7Rrk %}

# Conclusion
You have now implemented the video chat feature in Laravel! It's not that hard, right?


To include video calling functionality in your web app, you don't have to build it from scratch.


Agora provides a lot of great features out of the box. It also helps businesses save development hours when implementing video chat into existing projects. The only thing a developer has to do is build a compelling front end - Agora handles the video chat back end.

Link to project repository: https://github.com/Mupati/laravel-video-chat<br/> 
Demo link: https://laravel-video-call.herokuapp.com/agora-chat<br/>
Make sure the demo link or production version is served on HTTPS.

Test accounts:<br/>
foo@example.com: DY6m7feJtbnx3ud<br/>
bar@example.com: Me3tm5reQpWcn3Q<br/>

# Other Resources
<ul>
<li><a href="https://docs.agora.io/en/Video/API%20Reference/web/interfaces/agorartc.client.html#agorartc.client.html%23on" target="_blank">Available events on the Agora Client</a></li>
<li><a href="https://docs.agora.io/en/Video/run_demo_video_call_web?platform=Web" target="_blank">Agora Quickstart Guides</a></li>
<li><a href="https://docs.agora.io/en/Video/API%20Reference/web/index.html" target="_blank">Agora Web SDK API</a></li>
</ul>

I also invite you to <a href="https://app.slack.com/client/T265K8ZT9/C263V5MFV/thread/CPQP4GMJ9-1585749906.115600" target="_blank">join the Agora.io Developer Slack community</a>.