Klarbildbot v1.0 — AI-Bildaufbereitung (Freistellen + Upscaling) als Telegram-Bot
- Telegram-Bot (Polling) mit Inline-Menue: Klarbild x2/x4, Freistellen, kombiniert - Upscaling via OpenCV dnn_superres (FSRCNN default, EDSR optional), gekachelt - Freistellen via rembg (isnet-general-use, Alpha-Matting) - Picdrop-Batch via SFTP (/picdrop) - Health-Server (aiohttp) fuer Coolify, Zugriffsschutz via ALLOWED_USER_IDS - Dockerfile backt Modelle (SR von raw.githubusercontent, rembg von HF-Mirror) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNQ8ghPfzAfsyVYd6HgFb6
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""Zentrale Konfiguration aus Umgebungsvariablen."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _get_bool(name: str, default: bool = False) -> bool:
|
||||
val = os.getenv(name)
|
||||
if val is None:
|
||||
return default
|
||||
return val.strip().lower() in {"1", "true", "yes", "on", "ja"}
|
||||
|
||||
|
||||
def _get_int(name: str, default: int) -> int:
|
||||
try:
|
||||
return int(os.getenv(name, str(default)))
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
# --- Telegram ---------------------------------------------------------------
|
||||
BOT_TOKEN: str = os.getenv("BOT_TOKEN", "").strip()
|
||||
|
||||
# Kommagetrennte Liste erlaubter Telegram-User-IDs. Leer = jeder darf (nur
|
||||
# fuer Tests empfohlen). /start zeigt jedem seine ID, damit man hier eintraegt.
|
||||
_allowed = os.getenv("ALLOWED_USER_IDS", "").replace(";", ",")
|
||||
ALLOWED_USER_IDS: set[int] = {
|
||||
int(x) for x in (p.strip() for p in _allowed.split(",")) if x.strip().isdigit()
|
||||
}
|
||||
|
||||
# --- Bild-Pipeline ----------------------------------------------------------
|
||||
MODELS_DIR: Path = Path(os.getenv("MODELS_DIR", "/app/models"))
|
||||
WORK_DIR: Path = Path(os.getenv("WORK_DIR", "/tmp/klarbild"))
|
||||
|
||||
# rembg-Modell fuers Freistellen: isnet-general-use (gut), u2net, u2netp (leicht),
|
||||
# birefnet-general (beste Qualitaet, schwer). Wird beim Build vorgeladen.
|
||||
REMBG_MODEL: str = os.getenv("REMBG_MODEL", "isnet-general-use")
|
||||
|
||||
# OpenCV dnn_superres: "fsrcnn" (schnell, Default) oder "edsr" (mehr Detail,
|
||||
# aber auf CPU sehr langsam ~40s/Kachel -> nur fuer starke Boxen empfohlen).
|
||||
UPSCALE_MODEL: str = os.getenv("UPSCALE_MODEL", "fsrcnn").lower()
|
||||
|
||||
# Optionales Real-ESRGAN-ONNX-Backend (fuer GPU/starke Boxen). Wenn aktiv und
|
||||
# Modelldatei vorhanden, wird es statt OpenCV genutzt.
|
||||
ENABLE_REALESRGAN: bool = _get_bool("ENABLE_REALESRGAN", False)
|
||||
REALESRGAN_ONNX: Path = Path(
|
||||
os.getenv("REALESRGAN_ONNX", str(MODELS_DIR / "realesrgan_x4.onnx"))
|
||||
)
|
||||
|
||||
# Speicherschutz auf kleinen Boxen (CX33: 8GB, keine GPU):
|
||||
# Laengste Kante des Eingangsbildes vor dem Upscalen begrenzen.
|
||||
MAX_INPUT_EDGE: int = _get_int("MAX_INPUT_EDGE", 1600)
|
||||
# Kachelgroesse fuer das Upscalen (kleiner = weniger RAM, mehr Overhead).
|
||||
TILE_SIZE: int = _get_int("TILE_SIZE", 256)
|
||||
# Deckel fuer die Ausgabe-Megapixel (Sicherheitsnetz gegen OOM).
|
||||
MAX_OUTPUT_MP: float = float(os.getenv("MAX_OUTPUT_MP", "80"))
|
||||
|
||||
# Nach dem Upscalen leichte Entrauschung + Schaerfung ("Klarbild"-Finish).
|
||||
POST_DENOISE: bool = _get_bool("POST_DENOISE", True)
|
||||
POST_SHARPEN: bool = _get_bool("POST_SHARPEN", True)
|
||||
|
||||
# JPEG-Qualitaet fuer zurueckgesendete Fotos (Freistellen liefert immer PNG).
|
||||
JPEG_QUALITY: int = _get_int("JPEG_QUALITY", 95)
|
||||
|
||||
# --- Health-Server ----------------------------------------------------------
|
||||
HEALTH_PORT: int = _get_int("PORT", 8080)
|
||||
|
||||
# --- Picdrop (SFTP) ---------------------------------------------------------
|
||||
PICDROP_HOST: str = os.getenv("PICDROP_HOST", "ftps.picdrop.com")
|
||||
PICDROP_PORT: int = _get_int("PICDROP_PORT", 22)
|
||||
PICDROP_USER: str = os.getenv("PICDROP_USER", "")
|
||||
PICDROP_PASSWORD: str = os.getenv("PICDROP_PASSWORD", "")
|
||||
PICDROP_ENABLED: bool = bool(PICDROP_USER and PICDROP_PASSWORD)
|
||||
|
||||
|
||||
def validate() -> None:
|
||||
if not BOT_TOKEN:
|
||||
raise SystemExit("FEHLER: Umgebungsvariable BOT_TOKEN ist nicht gesetzt.")
|
||||
WORK_DIR.mkdir(parents=True, exist_ok=True)
|
||||
Reference in New Issue
Block a user