Building a video chat app in Django becomes increasingly challenging as user traffic grows, and this is where Agora"s real-time communication layer comes into play. A scalable setup must handle smooth audio-video delivery without delaying or dropping active sessions. Django offers a stable backend foundation, while Agora manages live streaming workloads that would be expensive and complex to build alone.
Bringing both together creates a structure that can grow with new users, new features, and higher concurrency. This introduction sets the context for why combining these two technologies is essential for building dependable real-time communication at scale.
Prerequisites
Before building your video chat app, ensure you have these ready:
- Python 3.8+ is installed on your system.
- Django installed via pip install django.
- An Agora account with your App ID and App Certificate from the Agora dashboard.
- Basic Python, Django, and web development knowledge.
- Visual Studio Code or another code editor.
- A modern browser for testing.
- Familiarity with JavaScript and asynchronous calls.
Starting Your Django Project
Create a new Django project and app for your video chat features:
django-admin startproject videochat
cd videochat
python manage.py startapp chatAdd your app to INSTALLED_APPS in videochat/settings.py:
INSTALLED_APPS = [
...,
'chat',
]
Run the server to confirm the setup:
python manage.py runserverAgora Token Generation in Django
Install Agora"s Python token builder:
pip install agora-token-builderIn videochat/settings.py, add your Agora credentials securely:
import os
AGORA_APP_ID = os.getenv('AGORA_APP_ID')
AGORA_APP_CERTIFICATE = os.getenv('AGORA_APP_CERTIFICATE')Use environment variables to avoid committing secrets to version control.
Create a view in chat/views.py to generate tokens dynamically:
from agora_token_builder import RtcTokenBuilder
from django.http import JsonResponse
from django.conf import settings
import time
def get_token(request):
channel_name = request.GET.get('channel')
if not channel_name:
return JsonResponse({'error': 'Channel name is required'}, status=400)
try:
uid = int(request.GET.get('uid', 0))
except ValueError:
return JsonResponse({'error': 'UID must be an integer'}, status=400)
role = 1 # Publisher role for video sending
expire_time_in_seconds = 3600
current_timestamp = int(time.time())
privilege_expired_ts = current_timestamp + expire_time_in_seconds
token = RtcTokenBuilder.buildTokenWithUid(
settings.AGORA_APP_ID,
settings.AGORA_APP_CERTIFICATE,
channel_name,
uid,
role,
privilege_expired_ts
)
return JsonResponse({'token': token, 'channel': channel_name, 'uid': uid})Building the Frontend for Video Calls
Create a template chat/templates/chat/room.html for your video chat UI:
<!DOCTYPE html>
<html>
<head>
<title>Agora Video Chat</title>
<script src="https://cdn.agora.io/sdk/release/AgoraRTC_N-4.19.1.js"></script>
<style>
#local-player, #remote-player {
width: 320px;
height: 240px;
background-color: black;
margin: 10px;
}
</style>
</head>
<body>
<h1>Agora Video Chat Room</h1>
<div id="local-player"></div>
<div id="remote-player"></div>
<script>
const APP_ID = '{{ agora_app_id }}'; // Pass from Django context
const CHANNEL = 'test-channel';
async function fetchToken() {
const response = await fetch(`/get-token/?channel=${CHANNEL}`);
const data = await response.json();
if (data.token) {
return data.token;
} else {
throw new Error('Token fetch failed');
}
}
async function startBasicCall() {
const client = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' });
await client.join(APP_ID, CHANNEL, await fetchToken());
const localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
const localVideoTrack = await AgoraRTC.createCameraVideoTrack();
localVideoTrack.play('local-player');
await client.publish([localAudioTrack, localVideoTrack]);
client.on('user-published', async (user, mediaType) => {
await client.subscribe(user, mediaType);
if (mediaType === 'video') {
const remoteVideoContainer = document.getElementById('remote-player');
user.videoTrack.play(remoteVideoContainer);
}
if (mediaType === 'audio') {
user.audioTrack.play();
}
});
client.on('user-unpublished', user => {
// Handle user leaving or stopping video
document.getElementById('remote-player').innerHTML = '';
});
}
startBasicCall().catch(console.error);
</script>
</body>
</html>
Notes:
- This uses the latest Agora Web SDK v4.x API.
- Token is fetched dynamically from the Django backend.
- Video and audio tracks are properly handled.
- Update your Django view rendering this template to provide the agora_app_id context.
Adding User Authentication and Scalability
Protect routes and enhance security with Django"s authentication framework. Store channels and users using Django models to track participants and active rooms.
Example model in chat/models.py:
from django.db import models
from django.contrib.auth.models import User
class Channel(models.Model):
name = models.CharField(max_length=100, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
participants = models.ManyToManyField(User, related_name='channels')Run these migrations:
python manage.py makemigrations
python manage.py migrateDeploy your app on a scalable infrastructure like AWS, Heroku, or any cloud platform. Leverage Agora's global edge network to serve users worldwide with low latency.
Testing Your App
Run Django"s development server and open multiple browsers or devices to join the video chat room simultaneously. Confirm audio-video works uninterruptedly, and tokens are generated correctly. Secure your endpoints, apply HTTPS, and enforce token expiration for production readiness.

