Real-time eye tracking and drowsiness alert system built with Python (FastAPI + MediaPipe + OpenCV) and Next.js (TypeScript + Tailwind CSS).
This system continuously monitors a user's eyes in real-time to prevent accidents caused by falling asleep. It utilizes a combination of frontend web technologies for capturing video and backend computer vision models for analysis.
- Video Capture (Frontend): The system opens the user's webcam via the browser's
navigator.mediaDevices.getUserMediaAPI. - Streaming via WebSockets: The React frontend (
Next.js) periodically captures screenshots from the video feed (default 10 Frames Per Second). It converts each frame into a Base64-encoded JPEG and sends it to the Python backend over a WebSocket connection (ws://localhost:8000/ws). - Face Mesh Detection (Backend): The FastAPI backend receives the image and processes it using Google's MediaPipe Face Mesh. This machine learning model detects 478 3D facial landmarks in real-time.
- Eye Aspect Ratio (EAR) Calculation: The system specifically tracks 6 landmarks around each eye. It calculates the EAR, which represents the openness of the eye:
EAR = (||p2−p6|| + ||p3−p5||) / (2 × ||p1−p4||)- When eyes are normally open, EAR is generally between
0.3and0.4. - When eyes close, the EAR drops significantly below a threshold (default
0.25).
- When eyes are normally open, EAR is generally between
- Drowsiness Alert Trigger: If the average EAR of both eyes stays below
0.25for 20 consecutive frames (about 2 seconds), the system flags the user as drowsy. - Instant Feedback: The backend immediately sends an alert signal back through the WebSocket. The frontend reacts by playing a loud dual-tone alarm (using the Web Audio API) and flashing a red "DROWSY" warning on the screen until the user opens their eyes.
drowsiness-detection/
├── backend/
│ ├── main.py # FastAPI + WebSocket server
│ ├── drowsiness_detector.py # EAR detection logic (MediaPipe)
│ ├── requirements.txt # Python dependencies
│ └── .gitignore # Ignores venv and __pycache__
├── src/
│ ├── app/ # Next.js App Router (page.tsx, layout.tsx, globals.css)
│ └── components/
│ └── DrowsinessMonitor.tsx# Main UI component for webcam and WebSockets
├── package.json # Node dependencies and scripts
├── tailwind.config.ts # Tailwind CSS v3 configuration
├── postcss.config.mjs # PostCSS configuration
└── next.config.mjs # Next.js 14 configuration
The backend handles the computer vision algorithms.
cd backend
# Create a virtual environment
python3 -m venv venv
# Activate the virtual environment
# On Mac/Linux:
source venv/bin/activate
# On Windows:
# venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Start the FastAPI server
uvicorn main:app --host 0.0.0.0 --port 8000 --reloadThe WebSocket server runs at ws://localhost:8000/ws.
The frontend captures the webcam feed and displays the UI. Open a new terminal instance in the root directory of the project:
# Install Node dependencies
npm install
# Start development server
npm run devOpen http://localhost:3000 in your browser.
- Go to
http://localhost:3000. - Click ▶ Start Monitoring.
- Allow camera access when prompted by the browser.
- Ensure your face is clearly visible. If you close your eyes for ~2 seconds, the alarm will sound!
Python— 3.xfastapi— v0.111.0 (Async web framework)uvicorn[standard]— v0.30.1 (ASGI server)mediapipe— v0.10.14 (Face mesh landmark detection)opencv-python-headless— v4.10.0.84 (Image decoding)scipy— v1.13.1 (Euclidean distance computation)numpy— v1.26.4 (Array operations)
next— v14.2.5 (React framework using App Router)react— v18.xtailwindcss— v3.4.1 (Utility-first CSS)typescript— v5.x (Type safety)
| Parameter | Location | Default | Description |
|---|---|---|---|
EAR_THRESHOLD |
backend/drowsiness_detector.py |
0.25 |
EAR below this = eyes closed |
CONSECUTIVE_FRAMES |
backend/drowsiness_detector.py |
20 |
Frames before alert triggers |
FPS |
frontend/components/DrowsinessMonitor.tsx |
10 |
Frame rate to server |
| Beep frequency | frontend/components/DrowsinessMonitor.tsx |
880Hz |
Alarm pitch |
| Issue | Fix |
|---|---|
| Camera not opening | Allow camera permission in browser |
| WebSocket error | Make sure backend is running on port 8000 |
| EAR always low | Improve lighting; face the camera directly |
| No face detected | Ensure face is within camera frame |
mediapipe install fails |
Use Python 3.8–3.11 (not 3.12+) |