From 15f62b6d81e205ba09c3c69fe79de8bbfa54a8ce Mon Sep 17 00:00:00 2001 From: Joachim Hummel Date: Mon, 19 Oct 2026 19:02:20 +0200 Subject: [PATCH] Add /snapshot.jpg endpoint --- README.md | 3 +++ app.py | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/README.md b/README.md index 99c3a85..aa319c7 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,9 @@ Danach erreichbar unter: | `http://:8080/` | HTML-Seite mit Live-Stream | | `http://:8080/stream` | MJPEG-Stream | | `http://:8080/stream.mjpg` | MJPEG-Stream (vehicle-counter kompatibel) | +| `http://:8080/snapshot.jpg` | Einzelbild (aktueller Frame als JPEG) | + +Beispiel: `curl -o foto.jpg http://:8080/snapshot.jpg` ## Autostart mit systemd diff --git a/app.py b/app.py index 203f440..7ea9482 100644 --- a/app.py +++ b/app.py @@ -3,6 +3,7 @@ app.py – Raspberry Pi Camera MJPEG Stream Server Startet rpicam-vid als Singleton-Prozess und verteilt Frames per Flask. Erreichbar unter /stream und /stream.mjpg (vehicle-counter kompatibel). +Einzelbild des aktuellen Frames unter /snapshot.jpg. .env-Variablen: APP_HOST Bind-Adresse (default: 0.0.0.0) @@ -218,6 +219,16 @@ def stream(): return _mjpeg_response() +@app.route("/snapshot.jpg") +def snapshot(): + with grabber.lock: + frame = grabber.frame + if frame is None: + return Response("Noch kein Frame verfügbar", status=503, mimetype="text/plain") + return Response(frame, mimetype="image/jpeg", + headers={"Cache-Control": "no-store"}) + + # ── Start ───────────────────────────────────────────────────────────────────── def _shutdown(sig, frame): print("[cam] Beende …", flush=True)