WebRTC Video Call App

A minimal but production-ready React + Node.js WebRTC video call application that enables two laptops on different networks to stream live video/audio to each other using peer-to-peer connections.

🎯 Features

  • P2P Video/Audio Streaming: Media never touches the backend server
  • Cross-Network Support: Works between different networks using ngrok tunneling
  • Real-time Signaling: WebSocket-based signaling server for WebRTC negotiation
  • Modern UI: Built with React, TypeScript, and Tailwind CSS
  • STUN Support: Uses Google's free STUN servers for NAT traversal

🧩 Tech Stack

Frontend

  • React 18 + Vite
  • TypeScript
  • Tailwind CSS
  • Native WebRTC APIs

Backend

  • Node.js + Express
  • WebSocket (ws library)
  • In-memory room management

🚀 Quick Start

Prerequisites

  • Node.js 18+ and npm
  • ngrok (for cross-network calls)
  • Two devices with cameras and microphones

Installation

  1. Clone and install dependencies:
# Install backend dependencies
cd server
npm install

# Install frontend dependencies
cd ../client
npm install

Running the Application

Step 1: Start the Signaling Server

cd server
npm run dev

The server will start on http://localhost:8080 with:

  • Health check: http://localhost:8080/healthz
  • WebSocket endpoint: ws://localhost:8080/ws

Step 2: Expose Server with ngrok (for cross-network calls)

In a new terminal:

ngrok http 8080

Copy the WSS URL (e.g., wss://abc123.ngrok.io/ws) - you'll need this for the frontend.

Note: For local testing on the same network, you can use ws://localhost:8080/ws directly.

Step 3: Start the Frontend

In a new terminal:

cd client
npm run dev

The frontend will start on http://localhost:3000

Using the App

  1. On Laptop 1:

    • Open http://localhost:3000
    • Enter the ngrok WSS URL (e.g., wss://abc123.ngrok.io/ws)
    • Enter a room ID (e.g., room-123)
    • Click "Join Room"
    • Allow camera/microphone permissions
  2. On Laptop 2:

    • Open http://localhost:3000 (or the ngrok URL if using HTTPS)
    • Enter the same ngrok WSS URL
    • Enter the same room ID
    • Click "Join Room"
    • Allow camera/microphone permissions
  3. Video Call:

    • Both users should see each other's video/audio streams
    • The connection is peer-to-peer (media doesn't go through the server)

📁 Project Structure

Gestr/
├── server/                 # Backend signaling server
│   ├── index.js           # Express + WebSocket server
│   └── package.json
├── client/                 # Frontend React app
│   ├── src/
│   │   ├── components/    # React components
│   │   │   ├── RoomJoin.tsx
│   │   │   └── VideoCall.tsx
│   │   ├── hooks/         # Custom hooks
│   │   │   └── useWebRTC.ts
│   │   ├── App.tsx
│   │   └── main.tsx
│   └── package.json
└── README.md

🔧 Configuration

Backend

  • Port: Default 8080 (set via PORT environment variable)
  • WebSocket Path: /ws
  • Health Check: /healthz

Frontend

  • Port: Default 3000 (configured in vite.config.ts)
  • Signaling URL: Entered by user in the UI

WebRTC

  • STUN Servers: Google's free STUN servers
    • stun:stun.l.google.com:19302
    • stun:stun1.l.google.com:19302
  • TURN: Not included (can be added later for restrictive NATs)

🌐 Network Requirements

  • HTTPS/WSS: Required for camera/microphone access in browsers
  • ngrok: Provides HTTPS/WSS tunnel for cross-network calls
  • Firewall: Ensure WebRTC ports are not blocked (typically UDP 1024-65535)

🐛 Troubleshooting

Camera/Microphone Not Working

  • Ensure you're using HTTPS/WSS (not HTTP/WS)
  • Check browser permissions
  • Try a different browser (Chrome/Firefox recommended)

Connection Fails

  • Verify ngrok is running and URL is correct
  • Check that both users are using the same signaling URL and room ID
  • Check browser console for errors
  • Ensure firewall allows WebRTC traffic

No Video/Audio

  • Check that both peers have joined the same room
  • Verify STUN servers are accessible
  • For restrictive NATs, consider adding TURN servers

📝 Development

Backend Scripts

  • npm run dev - Start with nodemon (auto-reload)
  • npm start - Start production server

Frontend Scripts

  • npm run dev - Start development server
  • npm run build - Build for production
  • npm run preview - Preview production build

🔒 Security Notes

  • This is a minimal implementation for demonstration
  • In production, consider:
    • Authentication/authorization
    • Rate limiting
    • Input validation
    • TURN server for restrictive networks
    • HTTPS certificates

📄 License

MIT

Share this project:

Updates