feat: relay inversé, LED idle solid, luminosité manuelle, auto-flash lux
🚀 Deploy — JH Photomaton / 🔍 Vérification (push) Has been cancelled
🚀 Deploy — JH Photomaton / 🍓 Deploy sur le Pi (push) Has been cancelled

This commit is contained in:
2026-07-17 10:32:43 +02:00
parent 3de55821b7
commit 4b188ce819
8 changed files with 260 additions and 6 deletions
+44
View File
@@ -162,5 +162,49 @@ class PhotoboothService:
"""Lit l'état actuel depuis le fichier private.css (ou depuis la config)."""
return self._cfg.show_delete_button
async def get_liveview_snapshot(self) -> bytes | None:
"""Tente de recuperer une frame JPEG du liveview de photobooth-app.
Essaie dans l'ordre :
1. /api/stream/snapshot — endpoint snapshot direct (si disponible)
2. /stream.mjpg — flux MJPEG classique, extrait la premiere frame
3. /api/stream — flux MJPEG alternatif
Retourne des bytes JPEG ou None si rien n'est disponible.
"""
# 1. Snapshot direct
for path in ("/api/stream/snapshot",):
try:
async with httpx.AsyncClient(timeout=2.0) as client:
r = await client.get(f"{self._base}{path}")
if r.status_code == 200:
ct = r.headers.get("content-type", "")
if "jpeg" in ct or "image" in ct:
return r.content
except Exception as e:
logger.debug("Snapshot %s: %s", path, e)
# 2. Premiere frame d'un flux MJPEG
for path in ("/stream.mjpg", "/api/stream"):
try:
async with httpx.AsyncClient(timeout=3.0) as client:
async with client.stream("GET", f"{self._base}{path}") as resp:
if resp.status_code != 200:
continue
buf = b""
async for chunk in resp.aiter_bytes(4096):
buf += chunk
start = buf.find(b"\xff\xd8")
if start >= 0:
end = buf.find(b"\xff\xd9", start)
if end >= 0:
return buf[start:end + 2]
if len(buf) > 500_000:
break
except Exception as e:
logger.debug("MJPEG %s: %s", path, e)
return None
async def close(self):
await self._client.aclose()