# usb-camera-webui Live MJPEG video feed from a USB webcam, served through a minimal web UI, running on a Raspberry Pi 5. ## Quick start ```bash # Ensure the v4l2 Python bindings are installed sudo apt install -y python3-v4l2 # Run directly python3 -m camera.app --host 0.0.0.0 --port 8080 ``` Open http://localhost:8080 in a browser. ## Systemd service The app runs natively on the Pi via a systemd unit. ### Install ```bash # Install the v4l2 Python bindings sudo apt install -y python3-v4l2 # Copy the service unit sudo cp camera-webui.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now camera-webui ``` ### Check status ```bash sudo systemctl status camera-webui journalctl -u camera-webui --follow ``` ### Uninstall ```bash sudo systemctl disable --now camera-webui sudo rm /etc/systemd/system/camera-webui.service sudo systemctl daemon-reload ``` ## Architecture ``` ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │ V4L2 mmap │───▶│ capture.py │───▶│ MJPEG │ │ (V4L2 API) │ │ (frame loop)│ │ server │ └──────────────┘ └──────────────┘ │ :8080 │ └──────────┘ │ ┌─────▼─────┐ │ Browser │ │ (MJPEG img)│ └───────────┘ ``` - **`capture.py`** opens `/dev/video0` via V4L2 mmap buffers, dequeues frames in a background thread, and stores them in a shared variable. - **`mjpeg.py`** serves the MJPEG stream (`multipart/x-mixed-replace`) via Python's built-in `http.server` with threading. Each client gets its own thread, and only new frames are sent. - **`app.py`** is the entry point: argument parsing, signal handling, and server launch. ## Hardware | Item | Details | |---|---| | Camera | Logitech C505 HD Webcam (`046d:08e3`) | | Device | `/dev/video0` (USB/UVC) | | Format | MJPEG 1280×720 | | Board | Raspberry Pi 5, Debian 12 (bookworm) | ## Dependencies - `python3-v4l2` — V4L2 Python bindings (system package, `apt install python3-v4l2`) - No pip packages needed — the server uses Python's standard library only