Skip to content

sudo-devKm/webrtc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WebRTC VoIP Application

A full-stack real-time voice calling application built with WebRTC, featuring peer-to-peer audio communication, user authentication, and real-time presence management.

CI Frontend: Vercel Backend: Render

Live demo: webrtc-seven-alpha.vercel.app  ·  API health: webrtc-74h2.onrender.com/health

The backend is on Render's free tier and spins down after ~15 minutes of inactivity — the first request after a nap can take up to 30s to wake it back up.

📸 Screenshots

Login Dashboard
Login screen Dashboard
Incoming call Active call
Incoming call Active call

Call screenshots were captured with two automated browser sessions placing a real call end-to-end (real signaling, ICE negotiation, and media tracks) — the green test pattern is Chromium's synthetic fake camera feed used for headless capture, not a rendering bug.

📋 Table of Contents

🎯 Application Overview

This WebRTC VoIP application enables users to:

  • Register and authenticate securely
  • Discover other online users in real-time
  • Initiate and receive voice calls using peer-to-peer WebRTC
  • Accept, reject, or end calls
  • Maintain call history and user presence status

The application follows a client-server architecture with peer-to-peer communication for media streaming:

  • Server handles authentication, user management, signaling, and presence
  • Clients communicate directly via WebRTC for audio/video without media passing through the server

🛠 Technology Stack

Backend

Layer Technology
Runtime Node.js v18+
Framework Express.js 5.x
Language TypeScript 5.x
Database MongoDB 9.x
Cache/Session Redis 5.x
Real-time Socket.IO 4.x
Authentication JWT + Argon2
Logging Winston
Validation Zod

Frontend

Layer Technology
Framework Angular 21
Language TypeScript 5.x
Styling Tailwind CSS 4.x
Components DaisyUI 5.x
Real-time Socket.IO Client 4.x
State RxJS Observables
HTTP Angular HttpClient
Routing Angular Router

DevOps & Tools

  • Containerization: Docker & Docker Compose
  • Version Control: Git
  • Package Manager: npm
  • Build Tool: Angular CLI & TypeScript Compiler

🏗 System Architecture

High-Level Overview

┌─────────────────────────────────────────────────────────────┐
│                      Frontend (Angular)                      │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │   Login      │  │  Dashboard   │  │   Call UI    │       │
│  │  Component   │  │  Component   │  │  Component   │       │
│  └──────────────┘  └──────────────┘  └──────────────┘       │
│          ▲                                    ▲               │
│          │                                    │               │
│  ┌───────────────────────────────────────────────────┐       │
│  │  Angular Services Layer                            │       │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────────────┐  │       │
│  │  │  Auth   │  │  Call   │  │  WebRTC Service │  │       │
│  │  │ Service │  │ Service │  │  (Peer Conn.)   │  │       │
│  │  └─────────┘  └─────────┘  └─────────────────┘  │       │
│  │  ┌─────────────────────┐  ┌─────────────────┐   │       │
│  │  │  Socket Service     │  │  HTTP Service   │   │       │
│  │  │  (Real-time)        │  │  (API calls)    │   │       │
│  │  └─────────────────────┘  └─────────────────┘   │       │
│  └───────────────────────────────────────────────────┘       │
└──────────────┬──────────────────────┬───────────────────────┘
               │                      │
         HTTP/REST            WebSocket (Socket.IO)
               │                      │
              ▼                       ▼
┌──────────────────────────────────────────────────────────────┐
│                  Backend (Node.js/Express)                   │
│  ┌────────────────────────────────────────────────────────┐ │
│  │ Authentication & Middleware Layer                     │ │
│  │ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐   │ │
│  │ │  Auth    │ │ Request  │ │  Error Handling      │   │ │
│  │ │Middleware│ │   ID     │ │  & Validation        │   │ │
│  │ └──────────┘ └──────────┘ └──────────────────────┘   │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │ API Routes Layer                                      │ │
│  │ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐   │ │
│  │ │  /auth   │ │  /calls  │ │  /users              │   │ │
│  │ │  Routes  │ │  Routes  │ │  Routes              │   │ │
│  │ └──────────┘ └──────────┘ └──────────────────────┘   │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │ Service Layer                                         │ │
│  │ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐   │ │
│  │ │  User    │ │  Call    │ │  Signaling Service   │   │ │
│  │ │ Service  │ │ Service  │ │  (WebRTC Signaling)  │   │ │
│  │ └──────────┘ └──────────┘ └──────────────────────┘   │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │ Data Access & Integration Layer                       │ │
│  │ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐   │ │
│  │ │MongoDB   │ │  Redis   │ │  Socket.IO Adapter   │   │ │
│  │ │Database  │ │  Cache   │ │  (Pub/Sub)           │   │ │
│  │ └──────────┘ └──────────┘ └──────────────────────┘   │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │ Logging & Monitoring                                  │ │
│  │ ├─ Winston Logger with Daily Rotation                │ │
│  │ ├─ Request ID Tracking                               │ │
│  │ └─ Error & Performance Monitoring                    │ │
│  └────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
               ▲                      ▲
               │                      │
         REST API              WebSocket (Signaling)
               │                      │
        ┌──────┴──────┬───────────────┴──────┐
        ▼             ▼                       ▼
    ┌────────┐   ┌────────┐            ┌─────────────┐
    │MongoDB │   │ Redis  │            │Socket.IO    │
    │Database│   │ Cache  │            │ Pub/Sub via │
    │        │   │        │            │Redis Adapter│
    └────────┘   └────────┘            └─────────────┘

Peer-to-Peer Audio Streaming

┌──────────────────────────────────────┐        ┌──────────────────────────────────────┐
│        User A (Frontend)             │        │        User B (Frontend)             │
│  ┌────────────────────────────────┐  │        │  ┌────────────────────────────────┐  │
│  │ WebRTC Peer Connection         │  │        │  │ WebRTC Peer Connection         │  │
│  │ ┌──────────────────────────┐   │  │        │  │ ┌──────────────────────────┐   │  │
│  │ │ LocalStream (Microphone) │   │  │        │  │ │ LocalStream (Microphone) │   │  │
│  │ │ ┌──────────────────────┐ │   │  │        │  │ │ ┌──────────────────────┐ │   │  │
│  │ │ │ Audio Tracks (Raw)   │ │   │  │        │  │ │ │ Audio Tracks (Raw)   │ │   │  │
│  │ │ └──────────────────────┘ │   │  │        │  │ │ └──────────────────────┘ │   │  │
│  │ └──────────────────────────┘   │  │        │  │ └──────────────────────────┘   │  │
│  │            │                    │  │        │  │            │                    │  │
│  │            ▼                    │  │        │  │            ▼                    │  │
│  │ ┌──────────────────────────┐   │  │        │  │ ┌──────────────────────────┐   │  │
│  │ │ Add Tracks to Connection │   │  │        │  │ │ Add Tracks to Connection │   │  │
│  │ └──────────────────────────┘   │  │        │  │ └──────────────────────────┘   │  │
│  │            │                    │  │        │  │            │                    │  │
│  │            ▼                    │  │        │  │            ▼                    │  │
│  │ ┌──────────────────────────┐   │  │        │  │ ┌──────────────────────────┐   │  │
│  │ │ Codec & Encryption       │   │  │        │  │ │ Codec & Encryption       │   │  │
│  │ │ (OPUS, DTLS-SRTP)        │   │  │        │  │ │ (OPUS, DTLS-SRTP)        │   │  │
│  │ │ Remote Stream Reception  │   │  │        │  │ │ Remote Stream Reception  │   │  │
│  │ └──────────────────────────┘   │  │        │  │ └──────────────────────────┘   │  │
│  └────────────────────────────────┘  │        │  └────────────────────────────────┘  │
│                                       │        │                                       │
│              ▲                        │        │                      ▲                │
└──────────────┼────────────────────────┘        └──────────────────────┼────────────────┘
               │ SRTP Media Stream                                      │
               │ (Encrypted Audio Data)                                 │
               │                                                        │
               └─────────────────────────────────────────────────────────┘
                     Direct P2P Connection (ICE/STUN/TURN)

Signaling Channel (via Socket.IO + Backend):
┌─────────────────────────────────────────────────────────────────────────────────┐
│  1. User A sends offer via Socket.IO → Backend → User B                         │
│  2. User B sends answer via Socket.IO → Backend → User A                        │
│  3. Both exchange ICE candidates via Socket.IO → Backend                        │
│  4. Once connection established, media flows directly P2P                        │
└─────────────────────────────────────────────────────────────────────────────────┘

📁 Project Structure

webrtc/
├── backend/                          # Node.js/Express backend
│   ├── src/
│   │   ├── @types/                   # Global type definitions
│   │   ├── config/                   # Environment & configuration
│   │   ├── constants/                # Application constants
│   │   ├── exceptions/               # Custom exceptions
│   │   ├── libs/                     # Core libraries
│   │   │   ├── database/            # MongoDB connection
│   │   │   ├── logger/              # Winston logger
│   │   │   ├── redis/               # Redis client
│   │   │   └── socket/              # Socket.IO server & signaling
│   │   ├── middlewares/              # Express middlewares
│   │   │   ├── auth.middleware.ts
│   │   │   ├── error.handler.middleware.ts
│   │   │   ├── request-id.middleware.ts
│   │   │   └── validation.schema.middleware.ts
│   │   ├── models/                   # MongoDB schemas
│   │   │   ├── user.model.ts
│   │   │   └── call.model.ts
│   │   ├── routes/                   # API routes & controllers
│   │   │   ├── auth/
│   │   │   ├── call/
│   │   │   └── users/
│   │   ├── types/                    # TypeScript definitions
│   │   ├── utils/                    # Utility functions
│   │   ├── app.ts                    # Express app setup
│   │   └── index.ts                  # Entry point
│   ├── Dockerfile
│   ├── docker-compose.yaml
│   ├── package.json
│   ├── tsconfig.json
│   ├── nodemon.json
│   └── README.md
│
├── frontend/                         # Angular frontend
│   ├── src/
│   │   ├── app/
│   │   │   ├── components/           # Angular components
│   │   │   │   ├── login/           # Authentication UI
│   │   │   │   ├── dashboard/       # Main app interface
│   │   │   │   └── call/            # Call interface
│   │   │   ├── services/             # Angular services
│   │   │   │   ├── auth.ts          # Authentication service
│   │   │   │   ├── call.ts          # Call management
│   │   │   │   ├── socket.ts        # Socket.IO client
│   │   │   │   └── webrtc.ts        # WebRTC peer connection
│   │   │   ├── app.ts               # Root component
│   │   │   ├── app.config.ts        # App configuration
│   │   │   ├── app.routes.ts        # Route definitions
│   │   │   └── styles.css           # Global styles
│   │   ├── environments/             # Environment configs
│   │   ├── index.html
│   │   ├── main.ts
│   │   └── styles.css
│   ├── public/
│   ├── angular.json
│   ├── tailwind.config.js
│   ├── tsconfig.json
│   ├── package.json
│   └── README.md
│
├── SETUP.md                          # Setup and installation guide
└── README.md                         # This file

✨ Key Features

1. User Authentication & Authorization

  • Registration: Email, username, password
  • Login: JWT-based token authentication, stored in an httpOnly cookie
  • Session Management: Secure cookie handling
  • Password Security: Argon2 hashing

2. Real-Time Presence & User Discovery

  • Online/offline status tracking
  • Last seen timestamp
  • Real-time user list updates via Socket.IO
  • User profiles with avatars

3. WebRTC Voice Calling

  • Signaling: Socket.IO for offer/answer exchange
  • Media: Direct peer-to-peer audio streaming
  • Codecs: OPUS audio codec for high-quality compression
  • Security: DTLS-SRTP for encrypted media
  • NAT Traversal: ICE, STUN, and TURN support
  • Call Lifecycle: Initiate, accept, reject, end

4. Call Management

  • Call history tracking
  • Call status monitoring
  • Call duration tracking
  • In-call notifications
  • Missed call notifications

5. Database & Caching

  • Users: User profiles and authentication
  • Calls: Call history and metadata
  • Sessions: Redis for session management
  • Socket.IO Adapter: Redis pub/sub for horizontal scaling

6. Security Features

  • CORS protection
  • Helmet security headers
  • HPP (HTTP Parameter Pollution) protection
  • Input validation with Zod
  • Request size limiting
  • JWT expiry and refresh

7. Monitoring & Logging

  • Structured logging with Winston
  • Daily log rotation
  • Request ID tracking for tracing
  • Error logging and analytics

🚀 Quick Start

Prerequisites

  • Node.js v18+
  • npm v11+
  • MongoDB 6.0+
  • Redis 7.0+

1. Clone & Setup

git clone <repository-url>
cd webrtc

# Backend setup
cd backend
cp .env.example .env  # Configure environment variables
npm install
npm run dev

# Frontend setup (new terminal)
cd frontend
npm install
npm start

2. Access Application

3. Create Test Users

📚 Documentation

Main Docs

Key Topics by Documentation

Topic Location
Environment Setup SETUP.md → Environment Setup
Backend Installation SETUP.md → Backend Setup, backend/README.md
Frontend Installation SETUP.md → Frontend Setup, frontend/README.md
API Endpoints backend/README.md → API Endpoints
WebSocket Events backend/README.md → WebSocket Events
Database Models backend/README.md → Database Models
Components & Services frontend/README.md → Application Architecture
Docker Deployment SETUP.md → Docker Setup
Troubleshooting SETUP.md → Troubleshooting

🏛 Architecture Diagrams

Request Flow - User Authentication

1. Frontend Login Form
   ↓
2. POST /api/auth/login
   ├─ Email & Password
   ├─ Backend validates credentials
   └─ Sets JWT as an httpOnly cookie (x-app-authorization), valid for 1 day
   ↓
3. Subsequent API/Socket.IO requests
   ├─ Browser sends the cookie automatically (withCredentials: true)
   └─ Backend verifies the JWT and loads req.user from MongoDB
   ↓
4. On Cookie Expiry / Invalid Token
   ├─ Requests receive 401 Unauthorized
   └─ Frontend redirects to /login (see authGuard)

Request Flow - Call Initiation

1. User A clicks "Call User B"
   ↓
2. Frontend: GET /api/users/B (fetch user details)
   ↓
3. Frontend: Initialize WebRTC Peer Connection
   ├─ Request microphone permissions
   └─ Get local audio stream
   ↓
4. Frontend: Create SDP Offer
   ├─ Offer encoded with local ICE candidates
   └─ Offer sent to Backend via Socket.IO: "offer"
   ↓
5. Backend receives offer
   ├─ Validate sender & recipient
   └─ Forward offer to User B via Socket.IO: "offer"
   ↓
6. User B Frontend receives offer
   ├─ Initialize Peer Connection
   └─ Create SDP Answer
   ↓
7. User B sends answer to Backend
   └─ Backend forwards to User A
   ↓
8. Both peers exchange ICE Candidates
   ├─ Via Socket.IO: "ice-candidate"
   └─ Backend acts as signaling relay
   ↓
9. Connection Established
   ├─ Both RTCPeerConnection states: "connected"
   └─ Media flows directly P2P (SRTP encrypted)
   ↓
10. Call Active
    ├─ Audio streams through WebRTC
    └─ Call metadata stored in MongoDB via Backend

Data Flow - Presence Updates

Browser A (User Login)
   ↓
Socket.IO Connect
   ↓
Backend: User joins Socket.IO room
   ├─ Update user.socketId in MongoDB
   ├─ Update user.isActive = true
   └─ Update user.lastSeen = now
   ↓
Backend: Broadcast "user-joined" event
   ├─ Via Redis pub/sub to all instances
   └─ To all connected browsers
   ↓
Browser B, C, D (Other users)
   ├─ Receive "user-joined" event
   └─ Update online users list UI
   ↓
Browser A (User Logout/Disconnect)
   ├─ Socket.IO disconnect
   └─ Backend updates user.isActive = false
   ↓
Backend: Broadcast "user-left" event
   └─ To all connected browsers

🔄 Communication Flow

1. HTTP REST API Flow

Browser → Frontend Service → HTTP Request → Backend Route Handler
  ↓                                            ↓
  ├─ Authentication                    ├─ JWT Validation
  ├─ Error Handling                    ├─ Business Logic
  └─ Response Display                  └─ Database Query

2. WebSocket (Socket.IO) Flow

Browser ← Socket.IO Client ← Socket Event ← Backend Socket Server
  ↓                                            ↓
  ├─ Real-time Updates                 ├─ Broadcast to All
  ├─ Event Listeners                   ├─ Broadcast to User
  └─ Instant Response                  └─ Broadcast to Room

3. WebRTC Peer Connection Flow

Browser A RTCPeerConnection ←→ Network Stack ←→ Browser B RTCPeerConnection
  ├─ Microphone Audio          (Direct P2P)          ├─ Speaker Audio
  ├─ Codec (OPUS)                                    ├─ Codec (OPUS)
  ├─ Encryption (DTLS-SRTP)   (Encrypted)            ├─ Decryption
  └─ NAT Traversal (ICE)      (via STUN/TURN)        └─ NAT Traversal

👨‍💻 Development Guide

Backend Development

Running in Development:

cd backend
npm run dev  # Uses nodemon for auto-reload

Available Scripts:

  • npm run dev - Start with nodemon (development)
  • npm run build - Compile TypeScript
  • npm start - Run compiled code

Key Libraries:

  • Express.js - HTTP server framework
  • Socket.IO - Real-time bidirectional communication
  • Mongoose - MongoDB object modeling
  • IORedis - Redis client
  • Winston - Logging library
  • Zod - TypeScript-first schema validation

Frontend Development

Running in Development:

cd frontend
npm start  # Starts ng serve on port 4200

Available Scripts:

  • npm start - Start dev server
  • npm run build - Production build
  • npm run watch - Build in watch mode
  • npm test - Run unit tests

Key Libraries:

  • Angular 21 - Framework
  • RxJS - Reactive programming
  • Tailwind CSS - Utility CSS
  • DaisyUI - Component library
  • Socket.IO Client - Real-time communication

Common Development Tasks

Add a New API Endpoint

  1. Create controller in backend/src/routes/[feature]/controllers/
  2. Add validation schema in backend/src/routes/[feature]/validation/
  3. Create service method in service layer
  4. Add route in backend/src/routes/[feature]/[feature].route.ts
  5. Register route in backend/src/routes/index.ts

Add a New Frontend Component

cd frontend
ng generate component components/[component-name]

Add a New Database Model

  1. Create schema in backend/src/models/[model].model.ts
  2. Add Mongoose schema and interfaces
  3. Create service for business logic
  4. Expose via API routes

Add a New Socket.IO Event

  1. Define event handler in backend/src/libs/socket/signaling.service.ts
  2. Emit event from Socket instance
  3. Add listener in frontend/src/app/services/socket.ts
  4. Handle event in component

🔒 Security Considerations

Backend Security

  • ✅ JWT tokens with expiry
  • ✅ Argon2 password hashing
  • ✅ CORS configured per environment
  • ✅ Helmet security headers
  • ✅ Input validation with Zod
  • ✅ Request ID tracking
  • ✅ Error messages don't leak sensitive info

Frontend Security

  • ✅ HTTPS enforced in production
  • ✅ JWT tokens not stored in localStorage (uses memory)
  • ✅ CORS properly configured
  • ✅ XSS protection via Angular sanitization
  • ✅ No sensitive data logged
  • ✅ Secure WebRTC with DTLS-SRTP

WebRTC Security

  • ✅ DTLS-SRTP encryption for media
  • ✅ ICE to prevent address leakage
  • ✅ TURN server for privacy
  • ✅ No unencrypted STUN

📊 Performance Optimization

Backend

  • Redis caching for sessions
  • MongoDB indexing on frequently queried fields
  • Compression middleware
  • Connection pooling
  • Horizontal scaling via Socket.IO Redis adapter

Frontend

  • Lazy loading of routes
  • Change detection optimization
  • Tree-shaking of unused code
  • Gzip compression
  • CDN ready

WebRTC

  • Adaptive bitrate for audio
  • OPUS codec for efficient compression
  • ICE candidate filtering
  • Connection timeout handling

🚢 Deployment

Docker Deployment

cd backend
docker-compose up

Starts:

  • Backend on :3000
  • MongoDB on :27017
  • Redis on :6379

Production Checklist

  • Set NODE_ENV=production
  • Use strong JWT secrets
  • Enable HTTPS
  • Configure CORS for production domain
  • Set database backups
  • Enable monitoring and logging
  • Configure firewall rules
  • Use environment variables for secrets
  • Set up rate limiting
  • Configure reverse proxy (nginx)

📞 Support & Troubleshooting

Common Issues

WebRTC Connection Fails:

  • Check firewall allows UDP
  • Verify STUN/TURN configuration
  • Check browser permissions
  • Review backend logs

Call Audio Not Working:

  • Check microphone permissions
  • Verify media permissions in browser
  • Check browser console for errors
  • Test with different browser

Backend Won't Start:

  • Check MongoDB is running
  • Check Redis is running
  • Verify .env file is configured
  • Check port 3000 is available

Frontend Won't Connect:

  • Verify backend is running
  • Check API URL in environment config
  • Check CORS configuration
  • Review browser console

See SETUP.md for detailed troubleshooting.

📝 Contributing

  1. Create a feature branch
  2. Make changes following code style guidelines
  3. Test thoroughly
  4. Submit pull request
  5. Request code review

📄 License

ISC

👥 Team

Created as part of the km-learn WebRTC learning project.


Last Updated: January 15, 2026

Useful Resources:

About

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors