A unified, self-hosted educational platform combining virtual classrooms,
AI-powered attendance, real-time engagement analytics, and non-destructive video editing —
all secured over HTTPS with end-to-end encryption.
Click to expand / collapse
- What is EduMi 2?
- Why EduMi 2?
- Key Features
- Technology Stack
- System Architecture
- Project Structure
- Prerequisites
- Installation
- Environment Variables
- Running the App
- Accessing the App
- Trusting the SSL Certificate
- Production Deployment (Docker)
- Default Credentials & Ports
- 🖥️ Server Deployment Guide ← Deploy to a real server
- Contributing
EduMi 2 replaces the fragmented patchwork of tools schools rely on today — video conferencing software, manual attendance registers, surveillance dashboards, and standalone video editors — with a single, self-hosted platform.
Everything runs over HTTPS. Biometrics are encrypted at rest. Real-time features are powered by WebSockets and WebRTC. No third-party cloud dependencies required.
| ❌ Problem | ✅ EduMi 2 Solution |
|---|---|
| Manual roll call wastes 5–10 min per class | AI face-recognition attendance — fully automated |
| Zero visibility into student attention | Real-time engagement scoring with emotion detection |
| 5+ fragmented tools to manage | One platform for meetings, cameras, recordings & editing |
| Raw biometric data stored in plaintext | Fernet AES-256 encryption for all face embeddings |
| Expensive dedicated camera hardware | Use any Android / iPhone as a live classroom camera |
| Meetings served over plain HTTP | Full HTTPS via self-signed cert + Daphne ASGI |
🔐 HTTPS Everywhere
- Daphne ASGI server runs with a self-signed SSL/TLS certificate
- All session and CSRF cookies are
HTTPS-only(SESSION_COOKIE_SECURE,CSRF_COOKIE_SECURE) - One-click PowerShell script installs the cert as a trusted root CA on Windows — no browser warnings
🤖 AI-Powered Attendance
- Students register their face once via the browser — no app required
- Face encodings (128-d embeddings from
dlib) are Fernet-encrypted before being written to the database - During class, the camera service continuously matches live frames against stored embeddings
- Attendance is only recorded after sustained verified presence (configurable duration in seconds)
📊 Real-Time Engagement Analytics
- Every few seconds, per-student emotional state and attention data is captured from camera feeds
StudentEngagementSnapshotrecords are aggregated into anEngagementReportautomatically after class- Teachers access a post-class dashboard showing attention scores, emotion breakdowns, and trend graphs
🎥 Dual Camera System
- RTSP Cameras — register hardware IP cameras by URL; stream live MJPEG in-browser
- Mobile Cameras — use any phone running IP Webcam (Android) or DroidCam as a live feed
- Both feeds pipe into the same AI pipeline — head counting, engagement scoring, face recognition
🖥️ Virtual Classrooms (LiveKit WebRTC)
- Persistent virtual classrooms with student membership and teacher-controlled approval
- Low-latency video/audio via LiveKit SFU (Selective Forwarding Unit)
- In-meeting controls: mute all, kick participant, raise hand queue, live chat
- Attendance auto-logged from join/leave WebRTC events
✂️ Non-Destructive Video Editor
- Edit recordings without touching the original file — source is always preserved
- Intelligent Sequencer: Real-time gap-skipping playback engine that instantly jumps over deleted clips during preview
- State Persistence: Browser-level
localStorageauto-saving ensures your edits survive page reloads - Precision Trimming: Live video scrubbing preview while dragging clip edges on the timeline
- Keyboard-Driven Workflow: Industry-standard shortcuts (
Spaceto play,Sto split,Delto remove,Ctrl+C/V/X, Arrow key seeking) - Actions (trim, mute, rotate, add text overlay, add audio) stored as an ordered sequence in the database
- Final export applies all actions as a single FFmpeg pipeline pass — no generation loss
⚡ Real-Time Everything
- WebSocket notifications for meetings, messages, and attendance events
- Celery background task queue for face processing, report generation, and recording management
- Redis channel layer for multi-consumer pub/sub across all services
| Layer | Technologies |
|---|---|
| Web Framework | Django 4.2, Python 3.11+ |
| ASGI Server | Daphne 4.0 + Twisted (SSL endpoint) |
| Real-Time | Django Channels 4.0, WebSockets |
| Video Conferencing | LiveKit WebRTC SFU |
| Computer Vision | OpenCV, face_recognition, dlib |
| Video Processing | FFmpeg (subprocess pipeline) |
| Background Tasks | Celery 5.3 + Redis |
| Encryption | cryptography (Fernet AES-256) |
| Database | SQLite (dev) / PostgreSQL (prod) |
| Static Files | WhiteNoise |
| Web Server (prod) | Nginx (reverse proxy + SSL termination) |
| Deployment | Docker, Docker Compose |
┌──────────────────────────────────────────────────────────────┐
│ Browser / Client │
│ HTTPS · WebSocket (wss://) · WebRTC │
└────────────────────────────┬─────────────────────────────────┘
│
┌─────────────▼─────────────┐
│ Nginx : 443 (prod) │ ← SSL termination + static files
│ Daphne : 8002 (dev) │ ← HTTPS + WSS direct
└─────────────┬─────────────┘
│
┌────────────────▼────────────────┐
│ Django Main App │
│ school_project/ │
│ ┌──────────┐ ┌─────────────┐ │
│ │ accounts │ │ meetings │ │ ← Auth, profiles, messaging
│ │ │ │ (LiveKit) │ │ ← Virtual classrooms
│ ├──────────┤ ├─────────────┤ │
│ │attendance│ │ cameras │ │ ← Face AI + engagement
│ │ │ │ (RTSP) │ │ ← Hardware camera mgmt
│ ├──────────┤ ├─────────────┤ │
│ │ videos │ │video_editing│ │ ← Upload & storage
│ │ │ │ │ │ ← Non-destructive editor
│ ├──────────┤ ├─────────────┤ │
│ │ mobile │ │ common │ │ ← Phone cameras
│ │ cameras │ │ │ │ ← Shared utilities
│ └──────────┘ └─────────────┘ │
└────────────┬──────────┬───────────┘
│ │
┌──────────▼──┐ ┌───▼──────┐
│ SQLite / │ │ Redis │
│ PostgreSQL │ │ :6379 │
└─────────────┘ └────┬─────┘
│
┌──────────────┴─────────────┐
│ │
┌───────────▼──────────┐ ┌─────────────▼──────┐
│ Celery Worker │ │ Camera Service │
│ (face processing, │ │ :8003 (Waitress) │
│ report gen, │ │ ─ MJPEG proxy │
│ recording mgmt) │ │ ─ Head counting │
└──────────────────────┘ │ ─ Face detection │
└──────────┬──────────┘
│
┌────────────▼────────────┐
│ LiveKit SFU : 7880 │
│ WebRTC peer routing │
└─────────────────────────┘
Edumi2/
│
├── school_project/ # Django project root
│ ├── settings.py # Master configuration
│ ├── urls.py # Root URL routing
│ ├── asgi.py # ASGI entry (Daphne + Channels)
│ ├── wsgi.py # WSGI entry (production alt.)
│ ├── celery.py # Celery application init
│ └── middleware.py # DatabaseErrorMiddleware
│
├── accounts/ # Auth, profiles, messaging, notifications
├── attendance/ # Face recognition attendance + engagement analytics
├── cameras/ # RTSP hardware camera management
├── mobile_cameras/ # Phone camera integration
├── meetings/ # LiveKit virtual classrooms
├── videos/ # Video upload and storage
├── video_editing/ # Non-destructive video editor
├── common/ # Shared models, utils, template tags
│
├── camera_service/ # AI microservice (port 8003, Waitress)
│
├── templates/ # HTML templates (per-app subfolders)
├── static/ # Source static files (CSS, JS, images)
├── staticfiles/ # Collected static files (auto-generated)
│
├── certs/ # SSL certificate + private key
│ ├── edumi.crt
│ └── edumi.key
│
├── config/ # Service configuration files
│ ├── livekit.yaml # LiveKit server config
│ └── .env.example # Environment variable template
│
├── nginx/ # Nginx config (production)
│ └── nginx.conf
│
├── scripts/ # Setup and deployment scripts
│ ├── generate_ssl_cert.py # Regenerate SSL certificates
│ ├── trust_ssl_cert.ps1 # Install cert as trusted root CA (Windows)
│ ├── trust_ssl_cert.bat # Double-click launcher for above
│ ├── allow_firewall.ps1 # Open Windows Firewall ports
│ ├── allow_firewall.bat # Launcher for above
│ └── deploy.sh # Linux Docker deployment
│
├── livekit-bin/ # LiveKit server binary (Windows) — see Prerequisites
├── database/ # SQLite DB + media files (gitignored)
├── logs/ # Application logs (gitignored)
│
├── manage.py # Django management CLI
├── requirements.txt # Python dependencies (52 packages)
├── Dockerfile # Main app container
├── docker-compose.yml # Full-stack orchestration
├── run_ssl_server.py # HTTPS server launcher (Daphne + SSL)
├── run_https.bat # Quick HTTPS-only start (Windows)
├── start_app.bat # Full system start (Windows, double-click)
├── start_app.ps1 # Full system start script (PowerShell)
├── start.sh # Full system start (Linux / Docker)
├── .env # Environment variables (gitignored)
└── .gitignore
Install all of the following before cloning the repository.
https://python.org/downloads/
python --version # Should output Python 3.11.x or higher| Platform | Command |
|---|---|
| Windows |
Download from microsoftarchive/redis, or use WSL2: sudo apt install redis-server |
| Ubuntu / Debian |
sudo apt install redis-server |
| macOS |
brew install redis |
redis-cli ping # Expected response: PONGWindows — Download from ffmpeg.org, extract the archive, and add the bin/ directory to your system PATH.
Linux:
sudo apt install ffmpegffmpeg -version # Verify installationWindows — dlib-bin in requirements.txt installs a pre-built wheel. No build tools needed.
Linux:
sudo apt install cmake build-essential libopenblas-dev liblapack-dev libx11-devThe livekit-bin/ folder is excluded from version control. Download the binary manually:
- Create a folder named
livekit-binin the project root - Download the latest release for your OS from LiveKit GitHub Releases
- Extract and place the
livekit-serverexecutable (e.g.,livekit-server.exeon Windows) insideEdumi2\livekit-bin/
git clone -b new_edumi https://github.com/GAuravgiy87/Edumi2.git
cd Edumi2# Windows (PowerShell)
python -m venv venv
venv\Scripts\activate# Linux / macOS
python3 -m venv venv
source venv/bin/activatepip install -r requirements.txtInstalls all 52 packages including OpenCV, face_recognition, dlib, Daphne, Celery, LiveKit SDK, and more.
cp config/.env.example .envOpen .env and populate all required values. Full reference in the Environment Variables section below.
python manage.py migratepython manage.py createsuperuserpython scripts/generate_ssl_cert.pyCreates certs/edumi.crt and certs/edumi.key — valid for 10 years, covering localhost, 127.0.0.1, and edumi.ac.in.
:: Windows — double-click this file and approve the UAC prompt
scripts\trust_ssl_cert.batAfter completing this step, Chrome and Edge will display the connection as 🔒 Secure with no warnings.
start_app.ps1 handles this automatically. To add it manually:
# Append to: C:\Windows\System32\drivers\etc\hosts
127.0.0.1 edumi.ac.in www.edumi.ac.in
Copy config/.env.example to .env and configure every value below.
# ── Django Core ─────────────────────────────────────────────────────────────
SECRET_KEY=your-very-long-random-secret-key-here
DEBUG=True # Set to False in production
ALLOWED_HOSTS=* # Restrict in production, e.g. edumi.ac.in
# ── HTTPS Security ──────────────────────────────────────────────────────────
SESSION_COOKIE_SECURE=True # Cookies transmitted over HTTPS only
CSRF_COOKIE_SECURE=True # CSRF token transmitted over HTTPS only
SECURE_SSL_REDIRECT=False # Set True if you have a plain-HTTP port to redirect
CSRF_TRUSTED_ORIGINS=https://localhost:8002,https://127.0.0.1:8002,https://edumi.ac.in:8002
# ── LiveKit WebRTC ───────────────────────────────────────────────────────────
LIVEKIT_URL=ws://localhost:8002/livekit-proxy
LIVEKIT_INTERNAL_URL=ws://localhost:7880
LIVEKIT_INTERNAL_HTTP_URL=http://localhost:7880
LIVEKIT_API_KEY=your-livekit-api-key
LIVEKIT_API_SECRET=your-livekit-api-secret-32-chars-min
# ── Redis (Celery + Channels) ────────────────────────────────────────────────
REDIS_URL=redis://localhost:6379/0
# ── Face Recognition & Encryption ───────────────────────────────────────────
# Generate: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
FACE_ENCRYPTION_KEY=your-fernet-encryption-key-here
FACE_MATCH_THRESHOLD=0.50 # 0 = identical · 1 = completely different · lower = stricter
FACE_PRESENCE_DURATION=30 # Seconds of continuous verified presence to mark attendance
# ── Camera Service ───────────────────────────────────────────────────────────
CAMERA_SERVICE_URL=http://localhost:8003
# ── Logging ──────────────────────────────────────────────────────────────────
LOG_LEVEL=INFOGenerate a SECRET_KEY:
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"Generate a FACE_ENCRYPTION_KEY:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"Starts Redis, generates the SSL cert if missing, runs migrations, collects static files, starts Celery, the Camera Service, the LiveKit SFU, and the Daphne HTTPS server — all in one command.
# Windows — double-click or run from PowerShell:
.\start_app.bat
# Or directly via PowerShell:
powershell -ExecutionPolicy Bypass -File start_app.ps1What does it do, step by step?
| # | Step |
|---|---|
| 1 | Adds edumi.ac.in → 127.0.0.1 to the Windows hosts file (auto UAC prompt) |
| 2 | Generates SSL certificate if certs/ doesn't exist |
| 3 | Checks Redis is running (starts it if not) |
| 4 | Starts the LiveKit SFU server |
| 5 | Runs manage.py migrate |
| 6 | Runs manage.py collectstatic |
| 7 | Starts Celery worker (threads mode, background) |
| 8 | Starts Camera Service on port 8003 (background) |
| 9 | Starts Daphne HTTPS server on port 8002 (foreground) |
Use when Redis, Celery, and LiveKit are already running (e.g., after a code change).
.\run_https.batOr directly:
venv\Scripts\python.exe run_ssl_server.py# Terminal 1 — Redis
redis-server
# Terminal 2 — Celery worker
venv\Scripts\celery.exe -A school_project worker -l info -P threads
# Terminal 3 — Camera service
venv\Scripts\python.exe camera_service/serve.py
# Terminal 4 — LiveKit SFU
livekit-bin\livekit-server.exe --config config\livekit.yaml
# Terminal 5 — Django HTTPS (Daphne)
venv\Scripts\python.exe run_ssl_server.py# Without Docker
chmod +x start.sh && ./start.sh
# With Docker Compose
bash scripts/deploy.sh
# or
docker-compose up --buildOnce the server is running, open your browser and navigate to any of the following:
| URL | Purpose |
|---|---|
https://127.0.0.1:8002 |
Main application (IP direct) |
https://localhost:8002 |
Main application (localhost) |
https://edumi.ac.in:8002 |
Main application (named domain — requires hosts entry) |
https://127.0.0.1:8002/admin/ |
Django admin panel |
First visit: Chrome / Edge will show "Your connection is not private" if the certificate hasn't been trusted yet.
- Quick bypass: Click Advanced → Proceed to 127.0.0.1 (unsafe)
- Permanent fix: Run
scripts\trust_ssl_cert.bat(recommended)
The self-signed certificate triggers NET::ERR_CERT_AUTHORITY_INVALID in browsers. Install it as a trusted root CA to eliminate this permanently.
Windows (installs for all users):
:: Double-click:
scripts\trust_ssl_cert.bat# Or from an elevated PowerShell session:
powershell -ExecutionPolicy Bypass -File scripts\trust_ssl_cert.ps1Approve the UAC prompt, then perform a full restart of Chrome (chrome://restart).
Ubuntu / Debian:
sudo cp certs/edumi.crt /usr/local/share/ca-certificates/edumi.crt
sudo update-ca-certificatesmacOS:
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain certs/edumi.crtAfter trusting, the browser address bar will display a 🔒 Secure padlock.
The Docker Compose stack provisions: Nginx (SSL + reverse proxy), Django (Daphne), Camera Service, Celery Worker, Redis, and LiveKit.
# 1. Copy and configure environment
cp config/.env.example .env
# → Set DEBUG=False, a strong SECRET_KEY, LiveKit credentials, etc.
# 2. Build and launch the full stack
docker-compose up --build -d
# 3. Apply database migrations
docker-compose exec web python manage.py migrate
# 4. Create the admin superuser
docker-compose exec web python manage.py createsuperuser
# 5. Tail logs
docker-compose logs -fNginx handles SSL termination on port 443. Django runs on port
8002internally and is not exposed publicly. Nginx proxies/ws/and/livekit-proxy/as WebSocket upgrades.
| Service | Port | Protocol | Notes |
|---|---|---|---|
| Django / Daphne | 8002 | HTTPS / WSS | Main app — always use https:// |
| Camera Service (Waitress) | 8003 | HTTP | AI microservice — internal only |
| LiveKit SFU | 7880 | WS / HTTP | WebRTC server — internal only |
| Redis | 6379 | TCP | Channel layer + Celery broker |
| Nginx (production) | 443 | HTTPS | Reverse proxy + SSL termination |
Default admin credentials: Created during
python manage.py createsuperuser. No credentials are hardcoded in the codebase.
Firewall: Run
scripts\allow_firewall.batto open ports8002and8003in Windows Firewall for LAN access.
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create your branch:
git checkout -b feature/your-feature-name - Commit your changes:
git commit -m 'feat: add some feature' - Push to the branch:
git push origin feature/your-feature-name - Open a Pull Request
Please follow Conventional Commits for commit messages.
Built for better classrooms.
Run .\start_app.bat and go. 🚀
Made with ❤️ by GAuravgiy87 · tarunkumar-sys
This guide assumes you are starting from zero — a fresh PC with nothing installed. Follow every step in order. Sections are split by operating system.
- Open your browser and go to: https://python.org/downloads/
- Click the latest Python 3.11.x or 3.12.x release button
- Run the installer
⚠️ CRITICAL — On the first screen, check "Add Python to PATH" before clicking Install- Click "Install Now"
- After it finishes, open Command Prompt (
Win + R→ typecmd→ press Enter) - Verify:
python --version
pip --versionBoth should print version numbers. If you see 'python' is not recognized, restart your PC and try again.
- Go to: https://git-scm.com/download/win
- Download and run the installer — accept all defaults
- Verify in Command Prompt:
git --versionFFmpeg is required for all recording and video processing features.
- Go to: https://ffmpeg.org/download.html → Click Windows → Windows builds by BtbN
- Download
ffmpeg-master-latest-win64-gpl.zip - Extract the ZIP — you'll get a folder like
ffmpeg-master-latest-win64-gpl - Move the extracted folder to
C:\ffmpeg - Add FFmpeg to PATH:
- Press
Win + S→ search "Environment Variables" → click "Edit the system environment variables" - Click "Environment Variables" button
- Under System variables, find Path → click Edit
- Click New → type
C:\ffmpeg\bin→ click OK on all windows
- Press
- Open a new Command Prompt and verify:
ffmpeg -versionRedis is required for real-time WebSocket features and background task queuing.
Option A — Using WSL2 (Recommended):
- Open PowerShell as Administrator → run:
wsl --install- Restart your PC when prompted
- Open the Ubuntu app from the Start Menu, set a username and password
- Install Redis inside Ubuntu:
sudo apt update
sudo apt install redis-server -y
sudo service redis-server start
redis-cli ping # Should print: PONGOption B — Native Windows Redis:
- Download from: https://github.com/microsoftarchive/redis/releases
- Download
Redis-x64-3.x.x.msiand run the installer - Redis will start automatically as a Windows Service
- Verify in Command Prompt:
redis-cli ping- Go to: https://github.com/livekit/livekit/releases
- Download the latest
livekit-server_windows_amd64.zip - Extract it — you'll get
livekit-server.exe - You'll place this in the project folder later (Step 2.3 below)
Open Command Prompt in the folder where you want the project (e.g., Desktop):
cd %USERPROFILE%\Desktop
git clone -b new_edumi https://github.com/GAuravgiy87/Edumi2.git
cd Edumi2python -m venv venv
venv\Scripts\activateYour prompt will now start with (venv) — this means you're inside the virtual environment. Always activate it before running any Python commands.
mkdir livekit-binCopy livekit-server.exe (downloaded in Step 1.5) into the livekit-bin\ folder inside the project.
pip install -r requirements.txtThis installs ~52 packages including Django, OpenCV, face recognition, Daphne, Celery, and all other dependencies. This may take 5–10 minutes on first run.
copy config\.env.example .env
notepad .envFill in these required values:
# Generate a secret key with:
# python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
SECRET_KEY=paste-generated-key-here
DEBUG=True
ALLOWED_HOSTS=*
LIVEKIT_API_KEY=devkey
LIVEKIT_API_SECRET=secret-must-be-at-least-32-characters-long
LIVEKIT_URL=ws://localhost:8002/livekit-proxy
LIVEKIT_INTERNAL_URL=ws://localhost:7880
LIVEKIT_INTERNAL_HTTP_URL=http://localhost:7880
REDIS_URL=redis://localhost:6379/0
# Generate a face encryption key with:
# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
FACE_ENCRYPTION_KEY=paste-generated-key-here
FACE_MATCH_THRESHOLD=0.50
FACE_PRESENCE_DURATION=30
CAMERA_SERVICE_URL=http://localhost:8003
LOG_LEVEL=INFO
CSRF_TRUSTED_ORIGINS=https://localhost:8002,https://127.0.0.1:8002Save and close Notepad.
python manage.py migratepython manage.py createsuperuserEnter a username, email (optional), and password when prompted.
Double-click start_app.bat in the project folder, or run from PowerShell:
powershell -ExecutionPolicy Bypass -File start_app.ps1This automatically:
- Generates an SSL certificate
- Installs it as a trusted certificate in Windows
- Adds
edumi.ac.into your hosts file - Starts Redis, Celery, Camera Service, LiveKit, and Daphne
Navigate to any of:
https://localhost:8002
https://127.0.0.1:8002
https://edumi.ac.in:8002
If you see "Your connection is not private", click Advanced → Proceed to localhost (unsafe). To remove this warning permanently, run
scripts\trust_ssl_cert.bat.
# Update package lists
sudo apt update && sudo apt upgrade -y
# Install Python 3.11+
sudo apt install python3.11 python3.11-venv python3-pip -y
# Install Git
sudo apt install git -y
# Install FFmpeg
sudo apt install ffmpeg -y
# Install Redis
sudo apt install redis-server -y
sudo systemctl enable redis-server
sudo systemctl start redis-server
# Install dlib build dependencies (for face recognition)
sudo apt install cmake build-essential libopenblas-dev liblapack-dev libx11-dev libgtk-3-dev -y
# Install additional system libraries
sudo apt install python3-dev default-libmysqlclient-dev -yVerify everything is installed:
python3 --version # Python 3.11.x
ffmpeg -version # FFmpeg version
redis-cli ping # PONG
git --version # git version# Create directory in your project folder (do this after cloning)
# Download latest livekit binary
wget https://github.com/livekit/livekit/releases/latest/download/livekit_linux_amd64.tar.gz
tar -xzf livekit_linux_amd64.tar.gz
# Move to project's livekit-bin folder (after cloning below)# Clone
git clone -b new_edumi https://github.com/GAuravgiy87/Edumi2.git
cd Edumi2
# Place LiveKit binary
mkdir -p livekit-bin
mv ../livekit-server livekit-bin/
# Create virtual environment
python3.11 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Configure environment
cp config/.env.example .env
nano .env # Edit and fill in values (see Windows section above for details)
# Run migrations
python manage.py migrate
# Create admin user
python manage.py createsuperuser# Give execute permission
chmod +x start.sh
# Start everything
./start.shOr manually in separate terminals:
# Terminal 1 — Redis (already running as service, but if not:)
redis-server
# Terminal 2 — Celery
source venv/bin/activate
celery -A school_project worker -l info -P threads
# Terminal 3 — Camera Service
source venv/bin/activate
python camera_service/serve.py
# Terminal 4 — LiveKit
./livekit-bin/livekit-server --config config/livekit.yaml
# Terminal 5 — Django (Main App)
source venv/bin/activate
python run_ssl_server.pyAccess at: https://localhost:8002 or https://<your-lan-ip>:8002
For deploying EduMi on a cloud VPS (AWS, DigitalOcean, Hetzner, etc.) with a real domain and Let's Encrypt SSL.
# SSH into your server
ssh root@your-server-ip
# Update system
apt update && apt upgrade -y
# Install required packages
apt install python3.11 python3.11-venv python3-pip git ffmpeg redis-server \
nginx certbot python3-certbot-nginx cmake build-essential \
libopenblas-dev liblapack-dev libx11-dev -y
# Enable and start Redis
systemctl enable redis-server
systemctl start redis-server# Create a dedicated user (don't run as root in production)
adduser edumi
usermod -aG sudo edumi
su - edumi
# Clone the project
git clone -b new_edumi https://github.com/GAuravgiy87/Edumi2.git
cd Edumi2
# Download LiveKit binary
mkdir -p livekit-bin
cd livekit-bin
wget https://github.com/livekit/livekit/releases/latest/download/livekit_linux_amd64.tar.gz
tar -xzf livekit_linux_amd64.tar.gz
rm livekit_linux_amd64.tar.gz
cd ..
# Create virtual environment and install dependencies
python3.11 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Configure environment for production
cp config/.env.example .env
nano .envEdit .env for production:
SECRET_KEY=<generate-strong-key>
DEBUG=False
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
# Use your real domain in CSRF origins
CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
LIVEKIT_API_KEY=<strong-random-key>
LIVEKIT_API_SECRET=<strong-random-secret-32-chars>
LIVEKIT_URL=wss://yourdomain.com/livekit-proxy
LIVEKIT_INTERNAL_URL=ws://localhost:7880
LIVEKIT_INTERNAL_HTTP_URL=http://localhost:7880
REDIS_URL=redis://localhost:6379/0
FACE_ENCRYPTION_KEY=<generate-fernet-key>
CAMERA_SERVICE_URL=http://localhost:8003
LOG_LEVEL=WARNING# Run migrations and collect static files
python manage.py migrate
python manage.py collectstatic --noinput
python manage.py createsuperusersudo nano /etc/nginx/sites-available/edumiPaste this configuration:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
client_max_body_size 2G;
location /static/ {
alias /home/edumi/Edumi2/staticfiles/;
}
location /media/ {
alias /home/edumi/Edumi2/database/media/;
}
location /livekit-proxy/ {
proxy_pass http://localhost:7880/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location / {
proxy_pass http://localhost:8002;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}# Enable the site
sudo ln -s /etc/nginx/sites-available/edumi /etc/nginx/sites-enabled/
sudo nginx -t # Test config
sudo systemctl reload nginx
# Get a free SSL certificate from Let's Encrypt
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.comCreate service files so all components restart automatically on server reboot:
sudo nano /etc/systemd/system/edumi-web.service[Unit]
Description=EduMi Django Web Server
After=network.target redis.service
[Service]
User=edumi
WorkingDirectory=/home/edumi/Edumi2
Environment="PATH=/home/edumi/Edumi2/venv/bin"
ExecStart=/home/edumi/Edumi2/venv/bin/python run_ssl_server.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo nano /etc/systemd/system/edumi-celery.service[Unit]
Description=EduMi Celery Worker
After=redis.service
[Service]
User=edumi
WorkingDirectory=/home/edumi/Edumi2
Environment="PATH=/home/edumi/Edumi2/venv/bin"
ExecStart=/home/edumi/Edumi2/venv/bin/celery -A school_project worker -l info -P threads
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo nano /etc/systemd/system/edumi-camera.service[Unit]
Description=EduMi Camera AI Service
After=network.target
[Service]
User=edumi
WorkingDirectory=/home/edumi/Edumi2
Environment="PATH=/home/edumi/Edumi2/venv/bin"
ExecStart=/home/edumi/Edumi2/venv/bin/python camera_service/serve.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo nano /etc/systemd/system/edumi-livekit.service[Unit]
Description=LiveKit WebRTC SFU Server
After=network.target
[Service]
User=edumi
WorkingDirectory=/home/edumi/Edumi2
ExecStart=/home/edumi/Edumi2/livekit-bin/livekit-server --config config/livekit.yaml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target# Enable and start all services
sudo systemctl daemon-reload
sudo systemctl enable edumi-web edumi-celery edumi-camera edumi-livekit
sudo systemctl start edumi-web edumi-celery edumi-camera edumi-livekit
# Check status
sudo systemctl status edumi-webCause: Python was not added to PATH during installation.
Fix:
# Check if Python is installed
where python
# If not found, reinstall Python and CHECK "Add Python to PATH"
# Or manually add: C:\Users\<YourName>\AppData\Local\Programs\Python\Python311\
# to your System Environment Variables → PATHWindows Fix: The project uses dlib-bin (pre-compiled wheel). If it still fails:
pip install --upgrade pip setuptools wheel
pip install dlib-bin
pip install face_recognitionLinux Fix: Install build dependencies first:
sudo apt install cmake build-essential libopenblas-dev liblapack-dev libx11-dev -y
pip install dlib
pip install face_recognitionWindows (native Redis):
# Check if Redis service is running
sc query Redis
# Start it
net start RedisWindows (WSL2):
# In Ubuntu terminal
sudo service redis-server startLinux:
sudo systemctl start redis-server
sudo systemctl enable redis-server # Auto-start on bootThis is expected for self-signed certificates. Solutions:
Quick bypass (Chrome): Click Advanced → Proceed to localhost (unsafe)
Permanent fix (Windows):
scripts\trust_ssl_cert.batThen fully restart Chrome: go to chrome://restart
Permanent fix (Linux):
sudo cp certs/edumi.crt /usr/local/share/ca-certificates/edumi.crt
sudo update-ca-certificatesChecklist:
- Is the camera service running on port 8003?
curl http://localhost:8003/health
- Is the RTSP URL correct? Test it directly:
ffplay rtsp://username:password@camera-ip:554/live - Is
CAMERA_SERVICE_URL=http://localhost:8003set in.env? - Check firewall — port 8003 must be open locally
- Camera must be reachable from the server's network
Checklist:
- Is LiveKit running?
.\livekit-bin\livekit-server.exe --config config\livekit.yaml
- Check
LIVEKIT_API_KEYandLIVEKIT_API_SECRETin.envmatchconfig\livekit.yaml - Verify the secret is at least 32 characters long
- For LAN access, make sure ports
7880and7881are open in Windows Firewall:scripts\allow_firewall.bat
# Delete the old database and start fresh
del database\db.sqlite3
python manage.py migrate
python manage.py createsuperuserpython manage.py collectstatic --noinputThen hard refresh the browser with Ctrl + Shift + R.
# Find and kill the process using port 8002
$proc = Get-NetTCPConnection -LocalPort 8002 -ErrorAction SilentlyContinue
if ($proc) { Stop-Process -Id $proc.OwningProcess -Force }This is prevented by the chunked HLS recording system. If it still happens:
- Check that FFmpeg is correctly installed and in PATH:
ffmpeg -version - The recording folder must exist and be writable:
icacls database\media\recordings /grant Everyone:F /T - Chunks are saved every 10 seconds — if the server crashes mid-chunk, only the last 10 seconds may be lost. Previous chunks are always safe.
# Run this once in an elevated PowerShell:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSignedThen run the script again.
# Make sure Redis is running first, then:
venv\Scripts\celery.exe -A school_project worker -l info -P threadsCheck that REDIS_URL=redis://localhost:6379/0 is correctly set in .env.
All application logs are written to the terminal where the server runs. For persistent logs:
# Linux — check systemd logs
sudo journalctl -u edumi-web -f
sudo journalctl -u edumi-celery -f
# Or check application log files
tail -f logs/edumi.logAfter setup, verify each component:
[ ] python --version → Python 3.11+
[ ] pip --version → pip 23+
[ ] ffmpeg -version → FFmpeg installed
[ ] redis-cli ping → PONG
[ ] livekit-server --version → LiveKit version
[ ] https://localhost:8002 → EduMi login page loads
[ ] Admin login works → /admin/ accessible
[ ] Camera feed visible → Control room shows live feed
[ ] Recording works → Start/stop creates chunks
[ ] Publish modal opens → Clean layout, no trim inputs
[ ] Meeting connects → LiveKit WebRTC session starts
[ ] Student can join meeting → Participant list shows student
Still stuck? Open an issue on GitHub with your OS, error message, and the output of python --version and pip list.