Skip to content

alinjfz/xiao-esp32s3-camera

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

XIAO ESP32-S3 Security Camera

Self-hosted security camera — from bare silicon to browser in one repo.
ESP32-S3 firmware → Raspberry Pi backend → live MJPEG stream in your browser. No cloud. No subscription.

Python C++ Platform Server License

Demo

Add a screenshot here — take one of your running dashboard and save it as docs/assets/dashboard.png.
See docs/assets/ for instructions on adding screenshots and demo GIFs.

Why I built this

Commercial IP cameras require cloud accounts, subscriptions, and send your footage to third-party servers. This project replaces all of that with a $15 microcontroller and a Raspberry Pi you already own. Everything runs on your LAN; Caddy handles HTTPS so the dashboard is still secure.

Architecture

Browser (HTTPS via Caddy)
       │
       ▼
Flask + SocketIO  (:5001)
       │  REST / WebSocket (Socket.io)
       ▼
WebSocket Server  (:8765)
       │  WS frames  [V=video | A=audio]
       ▼
ESP32-S3  ── OV2640 camera
          ── PDM microphone
          ── HC-SR501 PIR

Dual-core FreeRTOS design: core 0 streams frames (no WDT), core 1 handles control & WiFi (WDT active). A wsMutex semaphore serialises all WebSocket calls between cores.
Full details → docs/ARCHITECTURE.md

Features

Feature Details
Live MJPEG stream Browser-native, no plugin required
Real-time audio PCM 16 kHz → Web Audio API (iOS & desktop)
Motion detection PIR sensor with 60 s warmup and 5-sample debounce filter
Auto recording Motion-triggered recording with audio mux (ffmpeg → .mp4)
Timelapse Server-side frame capture at configurable intervals
Video library List, play, and download all recordings from the dashboard
SHA-256 login Password hashed client-side via crypto.subtle (HTTPS required)
HTTPS / TLS Caddy handles TLS termination; HSTS enforced
JWT sessions 24-hour signed tokens; rate-limited login (10 req/min)
Thread-safe streaming FreeRTOS mutex protects all WebSocket calls across cores
Per-core watchdog WDT on loop core only; stream core exempt from resets
Dark-mode dashboard Responsive SPA; no framework dependencies

Tech Stack

Layer Technologies
Firmware C++, Arduino ESP32 v3, FreeRTOS, esp-camera (OV2640), WebSocketsClient, ArduinoJson
Protocols WebSocket, MQTT TLS, MJPEG over HTTP, PCM audio (single-byte frame prefix)
Backend Python 3.9+, Flask 3, Flask-SocketIO, asyncio, OpenCV (headless), ffmpeg
Frontend HTML5, vanilla JS, Web Audio API, Socket.io 4, crypto.subtle SHA-256
Security SHA-256 hashing, JWT (PyJWT), HTTPS/TLS, HSTS, Caddy reverse proxy
Infrastructure Raspberry Pi (any 3B+/4/5), systemd service, Caddy, python-dotenv

Hardware

Component Model Notes
Camera node Seeed XIAO ESP32-S3 Sense OV2640 + PDM mic expansion board
Motion sensor HC-SR501 PIR Wired to GPIO 2
Server Raspberry Pi 3B+ / 4 / 5 Any model with USB-C or micro-USB power
Storage MicroSD 32 GB+ For Pi OS + video recordings
Power (ESP32) USB-C 5V/2A
Power (Pi) USB-C 5V/3A

Quick Start

  1. Clone:

    git clone https://github.com/alinjfz/xiao-esp32s3-camera.git
  2. Configure firmware: open firmware/xiao_esp32s3_camera.ino and set:

    const char* ssid     = "YOUR_WIFI_SSID";   // 2.4 GHz only
    const char* password = "YOUR_WIFI_PASSWORD";
    const char* raspi_ip = "YOUR_PI_IP";        // or "raspberrypi.local"
  3. Flash: Arduino IDE → Tools → PSRAM → OPI PSRAM → Upload
    ⚠️ PSRAM setting is mandatory — without it esp_camera_init() fails with error 0x105.

  4. Pi setup:

    cd server
    python3 -m venv venv && source venv/bin/activate
    pip install -r requirements.txt
    cp .env.example .env && nano .env   # set ADMIN_PASSWORD, SECRET_KEY, JWT_SECRET
    python raspberry_pi_server.py
  5. Open browser: https://raspberrypi.local/home

Documentation

Known Limitations

  • No 5 GHz WiFi — ESP32-S3 hardware supports 2.4 GHz only
  • PSRAM mandatory — must enable Tools → PSRAM → OPI PSRAM; without it camera init fails
  • Local-only by default — remote access requires Caddy + domain or port forwarding
  • Single camera — architecture supports one ESP32 node; multi-camera would need refactoring

Version History

Version Description
v1 Initial MQTT-based system with I2S audio and Flask dashboard
v2 Fix I2S/watchdog/framesize compilation errors; add WebSocket; 56% power reduction
v3 Emphasise PSRAM initialisation order; OPI PSRAM setting is critical
v4 Add diagnose.py health-check tool; comprehensive troubleshooting docs
v5 Major refactor: dark-mode SPA, HTTPS/Caddy, SHA-256 auth, MJPEG streaming
v6 Thread-safe WebSocket (FreeRTOS mutex), per-core WDT, 5-sample PIR debounce, rate-limited login, settings validation

License

MIT — see LICENSE

About

Self-hosted security camera: ESP32-S3 firmware + Raspberry Pi server + live MJPEG stream. No cloud. No subscription.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors