AI-powered drowsiness detection that watches your eyes so you don't have to.
SleepGuard runs entirely in your browser — no installs, no accounts, no API keys. It uses your webcam and MediaPipe FaceMesh to track your eye openness in real time, and fires a loud alarm the moment you start dozing off while watching content.
Start here. The
improved-version/directory is the recommended, fully-featured build.
git clone https://github.com/RabbaniHacker/sleepguard.git
cd sleepguard/improved-version
python3 -m http.server 3000
# Open http://localhost:3000 in ChromeThe root index.html / app.js / style.css is retained as a single-file MVP reference — useful for understanding the original algorithm or embedding, but it lacks persistence, calibration accuracy, and the multi-signal scoring of V2.
| Feature | Root (MVP) | improved-version/ V2 |
|---|---|---|
| 🧠 MediaPipe FaceMesh (468 landmarks) | ✅ | ✅ |
| 👁️ EAR drowsiness detection | ✅ | ✅ |
| 📊 PERCLOS (60s rolling window) | ✅ | ✅ |
| 🔊 Sound + Voice + Flash + Vibrate alerts | ✅ | ✅ |
| 🖼️ Picture-in-Picture float window | ✅ | ✅ |
| 🎬 Built-in video player (drag & drop) | ✅ | ✅ |
| 🎯 EAR Calibration | 2-step | 4-step (eyes + mouth + yawn) |
| 🥱 Yawn / MAR detection | — | ✅ calibrated MAR threshold |
| 🙆 Head-pose detection (nodding) | — | ✅ |
| 💡 Low-light warning banner | — | ✅ |
| 💾 Settings persistence (localStorage) | — | ✅ auto-save on change |
| 📈 Session history (IndexedDB) | — | ✅ |
| 🌗 Light/dark theme | — | ✅ |
| 📱 PWA (installable, offline SW) | — | ✅ |
| 🗂️ Modular ES modules | No (IIFE) | ✅ |
- Chrome (required for Picture-in-Picture)
- A webcam
- Python 3 (just to serve the files — no install needed)
git clone https://github.com/RabbaniHacker/sleepguard.git
cd sleepguard/improved-version
python3 -m http.server 3000Open http://localhost:3000 in Chrome and allow camera access.
Why a local server? MediaPipe loads WASM files via CDN which requires a proper HTTP origin — opening
index.htmldirectly viafile://won't work.
Click 🎯 Calibrate while monitoring is active:
- Eyes Open — look at the camera naturally (3s)
- Eyes Closed — close your eyes gently (3s) → EAR threshold auto-set
- Mouth Relaxed — neutral face (3s) → baseline MAR recorded
- Yawn — open mouth wide (3s) → yawn MAR threshold auto-set
Calibration is saved to localStorage and restored on next visit.
Every ~1 second the camera frame is sampled at 8×8 pixels (Rec.601 luminance). If average brightness drops below ~16% (40/255), a non-intrusive amber banner appears:
💡 Lighting too low — move somewhere brighter for reliable detection
The banner can be dismissed and re-evaluated automatically.
- Click ▶ Start Monitoring
- Click 🖼️ Float Over VLC — opens a Picture-in-Picture webcam window
- Switch to VLC (or any app)
- The floating eye-tracker window stays on top while you watch
- Fall asleep → alarm + voice alert + screen flash fires immediately
Webcam Feed
│
▼
MediaPipe FaceMesh ──→ 468 facial landmarks per frame
│
├── EAR (Eye Aspect Ratio) ──→ 0-40 pts
├── PERCLOS (60s window) ──→ 0-40 pts
├── MAR / Yawn detection ──→ 0-10 pts
└── Head Pose (pitch drop) ──→ 0-10 pts
│
▼
Drowsiness Score (0-100) → gauge display
│
Raw EAR < threshold for > alertDelay seconds?
│
▼
ALERT! 🚨
Eye Aspect Ratio (EAR):
EAR = (‖p2−p6‖ + ‖p3−p5‖) / (2 × ‖p1−p4‖)
False-positive safety: A normal blink (~150ms at 30fps ≈ 4 frames) is ×18 shorter than the 3s alertDelay. Normal PERCLOS (~15-20%) adds only ~7-10 pts — far below alert range.
| Setting | Range | Default | Description |
|---|---|---|---|
| EAR Threshold | 0.12 – 0.28 | 0.21 | Eye openness cutoff |
| Alert Delay | 1s – 10s | 3s | How long eyes must stay closed |
| Alert Volume | 0% – 100% | 80% | Alarm volume |
| Yawn Sensitivity | 0.20 – 0.80 | 0.50 | MAR threshold (auto-set by calibration) |
| Sound Alert | on/off | on | Loud beeping alarm |
| Screen Flash | on/off | on | Flashes screen red |
| Voice Alert | on/off | on | "Wake up!" via Speech Synthesis |
| Vibration | on/off | on | Vibrates device (mobile) |
| Yawn Detection | on/off | on | Enables MAR scoring |
| Head Pose | on/off | on | Enables pitch-drop scoring |
| Technology | Usage |
|---|---|
| MediaPipe FaceMesh | 468-point landmark detection via WebAssembly |
| Web Audio API | Procedural alarm generation |
| Speech Synthesis API | Voice wake-up alerts |
| Picture-in-Picture API | Floating camera window |
| Web Workers | Background thread to prevent tab throttling |
| Screen Wake Lock API | Prevents screen from dimming |
| Notification API | OS-level alert notifications |
| Canvas API | Face mesh overlay + EAR graph + brightness sampling |
| localStorage | Settings + calibration persistence |
| IndexedDB | Session history |
| Service Worker | PWA offline support |
sleepguard/
├── index.html # Root MVP — single file, simple reference
├── app.js # Root MVP — all logic in one IIFE
├── style.css # Root MVP — styles
├── README.md
└── improved-version/ # ← PRIMARY: modular ES-module rewrite
├── index.html # App shell, all modals, low-light banner
├── style.css # Dark/light theme, glassmorphism UI
├── manifest.json # PWA manifest
├── sw.js # Service worker (offline + PWA install)
└── src/
├── app.js # Entry point: init, controls, calibration
├── state.js # Centralized state + pub/sub
├── detector.js # MediaPipe setup + per-frame processing
├── analyzer.js # EAR, MAR, head-pose, drowsiness score
├── camera.js # Camera init, brightness sampling, PiP, wake lock
├── audio.js # Web Audio alarm, voice, keepalive
├── storage.js # localStorage (settings+calibration) + IndexedDB (history)
└── ui.js # DOM updates, graph, gauge, settings modal
Bug reports, ideas, and pull requests are very welcome.
- Fork the repo
- Create your branch:
git checkout -b feature/your-idea - Commit:
git commit -m "Add your feature" - Push:
git push origin feature/your-idea - Open a Pull Request
MIT — free to use, modify, and distribute.
Made with ❤️ · Stay awake, stay safe