Introduction
Django is a high-level Python Web framework that takes care of much of the hassle of Web development so that you can focus on writing your app without needing to reinvent the wheel. While Agora takes away the hassle of building a video chat application from scratch.
WebRTC is only one of the ways that people can implement video chat features. Companies like Agora 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:
- Quality of experience: Since WebRTC is transmitted over the Internet, which is a public domain, the quality of experience is hard to guarantee.
- Scalability: Scalability is fairly limited on group video calls due to the peer-to-peer nature of WebRTC.
After I was introduced to the Agora platform, I was impressed that setting up the same video call feature is easier with the Agora SDK than with WebRTC. I went ahead to build a video chat application with Agora and Laravel. In this article, however, I don't want Django developers to be left out so we are going to implement a video chat application with Django and Agora.
Why Agora Is the Preferred Solution
After building a video chat app with Agora, I want to highlight some of the advantages:
- There's one SDK for everything - voice, video, live streaming, screen sharing, and so on.
- I didn't have to set up a turn server with coturn on Amazon EC2 as I did in the other implementation to relay traffic between peers on different networks.
- You get 10,000 minutes every month free, and this gives you the flexibility to develop your solution prototype for free.
- You don't have the challenge of managing the underlying infrastructure supporting the video call functionality.
- Intuitive API documentation is available.
Prerequisites
- Python 3.8.5
- An average knowledge about how to create a Django project and app. The following tutorial can help you: Writing your first Django app.
- A free pusher account on pusher.com
- An understanding of pusher presence channels and the python server library.
- Agora Developer Account: (See How to get started with Agora)
Project Setup
Create and activate a python3 virtual environment for this project.
Open your terminal or command prompt and navigate to your Django project directory. We will use mysite as the project name for this tutorial.
-
Install the necessary packages from your terminal or command prompt.
pip install pusher python-dotenv
-
Create a new app called agora. Run the following from your terminal.
python manage.py startapp agora
-
In the project directory i.e mysite, run your migrations and create new super users by running the following command from your terminal.
python manage.py migrate // run the next command multiple times to create more users python manage.py createsuperuser
Download the AgoraDynamicKey Python3 code from the Agora repository: AgoraDynamicKey
Keep the downloaded folder in a location outside the project folder. Some of these files from the folder will be copied into our project when we're configuring the back end.
Configuring the Backend
We will create the views and classes with the methods needed to generate the Agora token to establish a call. We will set up Pusher at the server-side as well.
1. Add agora to the installed apps in mysite/settings.py
2. Add application routes
Create a file named urls.py in the agora directory and add the following code.
From your terminal or command prompt:
```bash
touch agora/urls.py
```
Add the following to agora/urls.py
Register the agora app routes at the project level. Add the following code to mysite/urls.py.
3. Add the downloaded AgoraDynamicKey generator files
-
Open your command prompt, and in the agora directory, create a sub-directory named agora_key.
cd agora mkdir agora_key
Copy AccessToken.py and RtcTokenBuilder.py from the src directory in the downloaded files and add them to the agora_key directory.
4. Create the views for the Agora app in agora/views.py
Add the following block of code to the agora/views.py file.
Breakdown of Methods in agora/views.py
- index: To view the video call page. Only authenticated users can view the page but non-authenticated users are redirected to the login page. We return a list of all the users apart from the currently authenticated user to be rendered on the front end.
- pusher_auth: It serves as the endpoint for authenticating the logged-in user as they join the pusher's presence channel. The ID and name of the user are returned after successful authentication with the pusher.
- generate_agora_token: To generate the Agora dynamic token. The token is used to authenticate app users when they join the agora channel to establish a call.
- call_user: This triggers a make-agora-call event on the presence-online-channel to which all logged-in users are subscribed.
The data broadcast with the make-agora-call event across the presence-online-channel contains the following:
- userToCall: This is the ID of the user who is supposed to receive a call from a caller.
- channelName: 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 client-side. It is the room the caller has already joined, waiting for the callee to also join to establish a call connection.
- from: The ID of the caller.
From the make-agora-call event, 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. Create the HTML file for the index view.
The HTML file will contain the links to the CDN for Agora SDK, Vue.js, Pusher, Bootstrap for styling, and our custom CSS and Javascript.
In your terminal navigate to the agora directory, create a templates directory and an agora subdirectory within it.
Create your index.html file in the agora subdirectory.
cd agora
mkdir -p templates/agora
touch templates/agora/index.html
Add the following to the index.html file:
NOTE:
In the Pusher instance, replace the key
with your own Pusher Key. Replace "420e941c25574fda6378" with yours.
window.pusher = new Pusher("420e941c25574fda6378", {
cluster: "APP_CLUSTER",
authEndpoint: "{% url 'agora-pusher-auth' %}",
auth: {
headers: {
"X-CSRFToken": "{{ csrf_token }}",
},
},
});
2. Create the static files
We have index.css for custom styling and index.js; our script for handling the call logic.
Add the following to index.js
Add the following to index.css
Breakdown of the Agora Call Page
On the video call page, i.e app/templates/agora/ndex.html, 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 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.
Bar gets an incoming call notification with Accept and Decline buttons and the name of the caller.
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:
3. 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.
PUSHER_APP_ID=
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_CLUSTER=
AGORA_APP_ID=
AGORA_APP_CERTIFICATE=
Testing
-
Start the Django development server from your terminal.
python manage.py runserver
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
You are presented with the Django admin login page if you are not already logged in.
After successful login, you will be taken to the Django admin dashboard. Click on the VIEW SITE link at the top right to navigate to the video call page.
In each of the browsers you opened, the other users registered on the application are displayed.
In one browser, you can call the user who is logged in and on the other browser by clicking the button that bears their name.
The other user is prompted to click the Accept button to fully establish the call.
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:
Conclusion
You have now implemented the video call feature in your Django application! 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/agora-django-video-call
Online Demo Link: https://fleet-server.herokuapp.com/agora/login/?next=/agora/dashboard/
Make sure the demo link or production version is served on HTTPS.
Test accounts:
foo@example.com: DY6m7feJtbnx3ud
bar@example.com: Me3tm5reQpWcn3Q
Other Resources
- Available events on the Agora Client
- For more information about Agora.io applications, take a look at the: Agora Quickstart Guides
- Take a look at the complete documentation for the functions discussed above and many more: Agora Web SDK API
I also invite you to join the Agora.io Developer Slack community.
Top comments (48)
Hi, Kofi mupati. I followed your all instructions and got an error. Can you please check that. Please give me a solution man.
File "C:\Users\Ehsan Software\AppData\Local\Programs\Python\Python38\lib\site-packages\pusher\client.py", line 37, in init
self._app_id = ensure_text(app_id, "app_id")
File "C:\Users\Ehsan Software\AppData\Local\Programs\Python\Python38\lib\site-packages\pusher\util.py", line 42, in ensure_text
raise TypeError("%s should be %s instead it is a %s" % (name, text, type(obj)))
TypeError: app_id should be a string instead it is a
did you add the pusher credentials to the .env file?
@mupati sorry about the late reply, I had weekend. Thanks for getting in touch. Yes I had added the pusher credentials to the .env files.
PUSHER_APP_ID= '1213947'
PUSHER_APP_KEY='2782f26c53ee13fb1ca2'
PUSHER_APP_SECRET= '8430a8454b6461e5e68e'
PUSHER_APP_CLUSTER= 'ap3'
AGORA_APP_ID= 'c00816fe3db3414584e35532dc2c43ae'
AGORA_APP_CERTIFICATE= '1c7ba4845b4945f0b9c6fe2a74835d70'
I cloned your github repo. rename the file .env.example to .env and save those credentials.
give me a solution man.
found the error. I made a mistake in the env variable names. I should be the following instead
PUSHER_APP_ID=
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_CLUSTER=
AGORA_APP_ID=
AGORA_APP_CERTIFICATE=
I've updated the post with the right ones.
which post? can you share the link? This will be great
You got any solution for the same or any link ,please share me
@sohanurshanto I made errors in the environment variable names. I've shared the correct one in this thread. I've also updated this same article to correct the mistake.
thanks
Hello brother ,I am still stuck on one problem. When I am login through admin panel site window will be there but status of offline to online not converting ,please help me out friend .I am sending you screenshot also
There's a mistake. In the index.html file, Replace 420e941c25574fda6378 with your own Pusher ID. The one over there is mine. I've updated the article to include this. The online status should work after that.
Hello , I changed the pusher key to mine but still it not changes its status from offline to online. Can you please check ones again what is the mistake and if possible please send us demo video with full tutorial its lot for us, thank you
check whether the environment variable names in your env file match with what you have in the views. I made some mistakes with that which I've corrected.
You can go through the article once more.
Thanks bro for your nice project. One thing may i ask on adding on feature if call is cancelled by one end, the other end will also be cancelled without pressing the stop button. Is something possible?
yeah it's possible. all you need is send the appropriate event through websockets from one user to the other. You listen for the event at one end and perform the action you want.
I have downloaded your repository and set up the virtual environment. After that I changed .env file with my credentials and also changed the index.html page pusher key. Unfortunately I am still getting offline. here is my pusher's data:
app_id = "1251606"
key = "4ad850a59d4a4ddaff01"
secret = "a9c40019b5f9c3003e99"
cluster = "ap2"
I have read your comments but couldn't find a solution. Please help me to figure it out.
pass the pusher cluster into the Pusher instance and let me know if it works.
Hello, I am having the issue of seeing the other users always as offline but I checked the spellings of environment variables and their values, changed the pusher key and inserted it again .
this is my .env file
PUSHER_APP_ID = 1243969
PUSHER_KEY = fd4655d98dd01fb8e82c
PUSHER_SECRET = aaf7b522efb285c73f06
PUSHER_CLUSTER = ap2
AGORA_APP_ID = 1edd45d115d04c2f83a3db514a8953b1
AGORA_APP_CERTIFICATE = 91dac37a4d28434f837c63bfd24e161a
and I swapped between inverted colons, double inverted colons and no inverted colon for values
I logged in incognito tab and normal tab. but its seems offline. I am not able to connect call. I attached the screenshot here. I used local server not https or live server. I don't know how to use it. can you help me for the same
dev-to-uploads.s3.amazonaws.com/up...
Please can you confirm whether your pusher connection is working well?
Hi, this worked great for me but I did notice when Agora SDK kicks in for streaming I get a warning in Chrome. Is the support for this SDK going to be an issue come July?
...
[Deprecation] Plan B SDP semantics, which is used when constructing an RTCPeerConnection with {sdpSemantics:"plan-b"}, is a legacy version of the Session Description Protocol that has severe compatibility issues on modern browsers. The standardized SDP format, "unified-plan", has been used by default since M72 (January, 2019). Dropping support for Plan B is targeted for M93 (Canary: July 15, 2021; Stable: August 24, 2021).
I'm glad you found it helpful. I can't tell for now but if possible use the latest stable SDK available.
I am always getting status as offline being I logged in with incognito tab as well as my normal tab as well.Can you help me for the same?
Can you confirm whether Pusher has been properly configured. Do that, refresh browser and try again.
You have hard coded a string (I am attaching a screenshot you can see in that ) Do I have to change that or will it be like that only? Also can you tell me how can I cross check if pusher is configured properly or not?
where is the screenshot
dev-to-uploads.s3.amazonaws.com/up...
Yeah. thanks for pointing it out. That is the pusher key. Replace that with yours. I'll update the post to reflect that. I'm not sure there are any security concerns with having your pusher key visible. the pusher secret must be kept secret, pun intended.
I have followed your directions but there is still a problem in the status is still offline ...
pls hellp me ..
can you confirm if your pusher keys are correct?
PUSHER_KEY='65c0628332bed3678a4f'
<br> window.pusher = new Pusher("65c0628332bed3678a4f", {</p> <p>like this ?</p>
yeah. what about the backend?
PLS bro cek my code github.com/C0SM1C5/C0SM1C5/raw/mai...
fleet-server.herokuapp.com/agora/l... hyperlink is pointing to github.com/Mupati/agora-django-vid... maybe you want to update it :)
@bashar Al-Abdulhadi may i have your code?
didn't get you, which code?
Thanks for pointing it out.
is this applicable for DRF
You can tweak it and implement the same with DRF
I got the same error ,Kofi mupati help me for the same
Hi, Kofi mupati. I followed your all instructions and got an error. Can you please check that. Please give me a solution man.
File "C:\Users\Ehsan Software\AppData\Local\Programs\Python\Python38\lib\site-packages\pusher\client.py", line 37, in init
self._app_id = ensure_text(app_id, "app_id")
File "C:\Users\Ehsan Software\AppData\Local\Programs\Python\Python38\lib\site-packages\pusher\util.py", line 42, in ensure_text
raise TypeError("%s should be %s instead it is a %s" % (name, text, type(obj)))
TypeError: app_id should be a string instead it is a
were you able to find a solution for this problem, if yes then please share the solution with me also, because i am also facing the smae problem
No, I am still working on the same issue. I don't know how to change offline status to online ,if you got any solution plz help me out.