2026-08-05 15:43:04 +00:00
|
|
|
|
# usb-camera-webui
|
|
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
Live MJPEG video feed from a USB webcam, served through a minimal web UI, running on a
|
|
|
|
|
|
Raspberry Pi 5.
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
## Quick start
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-08-06 09:25:02 +09:00
|
|
|
|
# Install the V4L2 Python bindings
|
2026-08-06 01:17:26 +09:00
|
|
|
|
sudo apt install -y python3-v4l2
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
# Run directly
|
|
|
|
|
|
python3 -m camera.app --host 0.0.0.0 --port 8080
|
|
|
|
|
|
```
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
Open http://localhost:8080 in a browser.
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
## Systemd service
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
The app runs natively on the Pi via a systemd unit.
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
### Install
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
```bash
|
2026-08-06 09:25:02 +09:00
|
|
|
|
# Install the V4L2 Python bindings
|
2026-08-06 01:17:26 +09:00
|
|
|
|
sudo apt install -y python3-v4l2
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
# Copy the service unit
|
|
|
|
|
|
sudo cp camera-webui.service /etc/systemd/system/
|
|
|
|
|
|
sudo systemctl daemon-reload
|
|
|
|
|
|
sudo systemctl enable --now camera-webui
|
2026-08-06 00:44:19 +09:00
|
|
|
|
```
|
2026-08-06 01:17:26 +09:00
|
|
|
|
|
|
|
|
|
|
### Check status
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sudo systemctl status camera-webui
|
|
|
|
|
|
journalctl -u camera-webui --follow
|
2026-08-06 00:44:19 +09:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
### Uninstall
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-08-06 01:17:26 +09:00
|
|
|
|
sudo systemctl disable --now camera-webui
|
|
|
|
|
|
sudo rm /etc/systemd/system/camera-webui.service
|
|
|
|
|
|
sudo systemctl daemon-reload
|
2026-08-06 00:44:19 +09:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
## Architecture
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
```
|
|
|
|
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────┐
|
|
|
|
|
|
│ V4L2 mmap │───▶│ capture.py │───▶│ MJPEG │
|
|
|
|
|
|
│ (V4L2 API) │ │ (frame loop)│ │ server │
|
|
|
|
|
|
└──────────────┘ └──────────────┘ │ :8080 │
|
|
|
|
|
|
└──────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
┌─────▼─────┐
|
|
|
|
|
|
│ Browser │
|
|
|
|
|
|
│ (MJPEG img)│
|
|
|
|
|
|
└───────────┘
|
|
|
|
|
|
```
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
- **`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.
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
## 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) |
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
## Dependencies
|
2026-08-06 00:44:19 +09:00
|
|
|
|
|
2026-08-06 01:17:26 +09:00
|
|
|
|
- `python3-v4l2` — V4L2 Python bindings (system package, `apt install python3-v4l2`)
|
|
|
|
|
|
- No pip packages needed — the server uses Python's standard library only
|