126 lines
4.6 KiB
Markdown
126 lines
4.6 KiB
Markdown
# Webcam
|
||
|
||

|
||
|
||
Zwei kleine Python-Tools für MJPEG-Kameras:
|
||
|
||
- **`relay.py`** – holt den MJPEG-Stream jeder Kamera nur **einmal** ab und stellt ihn für beliebig viele Zuschauer per HTTP bereit (gedacht für den Betrieb hinter einem Reverse Proxy wie Zoraxy).
|
||
- **`webcam.py`** – Kommandozeilenwerkzeug, um einen MJPEG-Stream zu testen, Einzelbilder/Frames zu speichern oder live anzuzeigen.
|
||
|
||
## Voraussetzungen
|
||
|
||
- Python 3
|
||
- [`requests`](https://pypi.org/project/requests/)
|
||
- Optional für `webcam.py --show`: `opencv-python` und `numpy`
|
||
|
||
```bash
|
||
pip install requests
|
||
pip install opencv-python numpy # nur für --show
|
||
```
|
||
|
||
## Relay (`relay.py`)
|
||
|
||
### Konfiguration
|
||
|
||
Die Konfiguration erfolgt über eine `.env`-Datei neben `relay.py` oder über Umgebungsvariablen (echte Umgebungsvariablen haben Vorrang).
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
| Variable | Beschreibung | Standard |
|
||
|---|---|---|
|
||
| `CAMERA_<name>` | Stream-URL einer Kamera, eine Zeile pro Kamera. Der Name wird Teil der URL (`/cam1/`). | – (mindestens eine nötig) |
|
||
| `SETUP_<name>` | Optional: Konfigurations-URL der Kamera (z. B. `http://IP/control?var=framesize&val=11`). Das Relay ruft sie auf, wenn im Frontend „Setup“ geklickt wird. | – |
|
||
| `PORT` | Port, auf dem der Relay lauscht | `8000` |
|
||
| `AUTH_USER` / `AUTH_PASS` | Optional: Basic-Auth. Nur sinnvoll mit HTTPS (z. B. in Zoraxy). | aus |
|
||
|
||
Beispiel:
|
||
|
||
```ini
|
||
CAMERA_cam1=http://192.168.1.8:8080/stream.mjpg
|
||
CAMERA_cam2=http://192.168.1.9:8080/stream.mjpg
|
||
PORT=8000
|
||
#AUTH_USER=benutzername
|
||
#AUTH_PASS=geheim
|
||
```
|
||
|
||
> `.env` enthält ggf. Zugangsdaten – nicht ins Repository einchecken.
|
||
|
||
### Starten
|
||
|
||
```bash
|
||
python3 relay.py
|
||
```
|
||
|
||
### Als systemd-Dienst
|
||
|
||
`webcam-relay.service` liegt im Repository. Pfade und Benutzer (`/home/joachim/git/webcam`, `joachim`) bei Bedarf in der Datei anpassen.
|
||
|
||
Der Dienst nutzt das System-Python (`/usr/bin/python3`). Dort muss `requests` installiert sein, auch wenn es z. B. in Conda oder einem venv schon vorhanden ist:
|
||
|
||
```bash
|
||
sudo apt install python3-requests
|
||
```
|
||
|
||
```bash
|
||
sudo cp webcam-relay.service /etc/systemd/system/
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable --now webcam-relay
|
||
```
|
||
|
||
Status und Logs:
|
||
|
||
```bash
|
||
systemctl status webcam-relay
|
||
journalctl -u webcam-relay -f
|
||
```
|
||
|
||
### Endpunkte
|
||
|
||
| Pfad | Beschreibung |
|
||
|---|---|
|
||
| `/` | Web-Frontend: Übersicht aller Kameras |
|
||
| `/<name>/` | Web-Frontend: große Ansicht einer Kamera, die anderen als Vorschau-Leiste |
|
||
| `/status.json` | Online-Status aller Kameras (wird vom Frontend alle 5 s abgefragt) |
|
||
| `/<name>/stream.mjpg` | Livestream (`multipart/x-mixed-replace`) |
|
||
| `/<name>/snapshot.jpg` | Aktuelles Einzelbild |
|
||
| `/stream.mjpg`, `/snapshot.jpg` | Alias für die erste Kamera (Abwärtskompatibilität) |
|
||
| `/health` | Status aller Kameras (`200` wenn alle liefern, sonst `503`); ohne Authentifizierung erreichbar |
|
||
|
||
### Web-Frontend
|
||
|
||
Das Frontend liegt in `frontend.html` (reines HTML/CSS/JS, keine Abhängigkeiten) und wird vom Relay ausgeliefert. Änderungen an der Datei wirken sofort, ohne Neustart.
|
||
|
||
- Raster mit Live-Streams aller Kameras, Klick auf den Namen öffnet die große Ansicht
|
||
- Statuspunkt und Hinweis „Kamera offline“ pro Kamera, automatisches Neuverbinden
|
||
- Buttons für Foto (Download) und Vollbild
|
||
- Hell/Dunkel passend zum System
|
||
- Streams werden getrennt, solange der Tab im Hintergrund ist
|
||
- Alle Links sind relativ, daher funktioniert es auch unter einem Proxy-Prefix wie `/webcam/`
|
||
|
||
### Funktionsweise
|
||
|
||
- Pro Kamera läuft ein Hintergrund-Thread, der den Stream liest und die JPEG-Frames anhand der Marker `FFD8`/`FFD9` ausschneidet.
|
||
- Bei Verbindungsfehlern wird nach 3 Sekunden automatisch neu verbunden.
|
||
- Alle Zuschauer bekommen jeweils das neueste Frame – die Kamera wird unabhängig von der Zuschauerzahl nur einmal belastet.
|
||
- Der Header `X-Accel-Buffering: no` verhindert Pufferung durch den Proxy.
|
||
|
||
## Stream-Tool (`webcam.py`)
|
||
|
||
```bash
|
||
python3 webcam.py # Verbindung testen, Frame-Infos ausgeben
|
||
python3 webcam.py --snapshot bild.jpg # ein Einzelbild speichern
|
||
python3 webcam.py --save frames/ -n 50 # 50 Frames als JPEG speichern
|
||
python3 webcam.py --show # Live-Fenster (q oder Esc beendet)
|
||
python3 webcam.py --url http://IP:PORT/stream.mjpg
|
||
```
|
||
|
||
| Option | Beschreibung |
|
||
|---|---|
|
||
| `--url` | Stream-URL (Standard ist in `webcam.py` hinterlegt) |
|
||
| `--snapshot DATEI` | Ein Frame speichern und beenden |
|
||
| `--save ORDNER` | Frames im Ordner speichern |
|
||
| `-n N` | Nach N Frames beenden (`0` = endlos) |
|
||
| `--show` | Live-Fenster anzeigen (OpenCV) |
|