Eine Kamera am Vogelhaus, ein Rechner der erkennt wer da war — und eine Sammlung, die sich von allein fuellt. Zwei neuronale Netze: eines findet den Vogel im Bild, eines bestimmt die Art. 148 heimische Arten, auf Deutschland eingeschraenkt und neu normiert — ohne diese Einschraenkung wird aus einer Kohlmeise eine nordamerikanische Schwesterart. Daraus entsteht ein Sammelalbum: nummerierte Seiten, gefundene Arten in Farbe, fehlende als Schatten, dazu Erstfang, Punkte, Stufen und 15 Abzeichen. Laeuft vollstaendig auf eigener Hardware. Kein Cloud-Dienst, kein Konto, keine Telemetrie; die Bilder verlassen das eigene Netz nicht. Zwei getrennt deploybare Teile: die Sammlung als Django-Anwendung, die Erkennung als eigener Dienst. Der Erkennungs-Dienst fragt selbst an und braucht deshalb weder eine erreichbare Adresse noch einen offenen Port — er laeuft hinter einem gewoehnlichen Router. Dabei: Firmware fuer Raspberry Pi und ESP32-S3, Anbindung an Home Assistant ueber MQTT, Oberflaeche auf Deutsch und Englisch, Einstellungen je Kamera aus dem Browser, und ein Weg fuer Fotos von unterwegs. AGPL-3.0.
101 lines
4.1 KiB
YAML
101 lines
4.1 KiB
YAML
# Vogelalbum zu Hause: Sammlung und Erkennung auf einer Maschine.
|
|
#
|
|
# cp .env.beispiel .env # VOGELALBUM_SOURCE eintragen
|
|
# docker compose -f docker-compose.heim.yml up -d
|
|
#
|
|
# Danach laeuft die Sammlung auf http://localhost:8000 und der Detector
|
|
# schaut in die Kamera. Kein venv, keine Modelle von Hand, kein systemd.
|
|
#
|
|
# Warum eine eigene Datei und nicht ein Profil in docker-compose.yml? Die
|
|
# andere Datei beschreibt das oeffentliche Hosting der Web-App allein (dort
|
|
# gibt es keine Kamera im Netz). Beide Faelle brauchen andere Vorgaben —
|
|
# in einer Datei mit Schaltern waeren beide schwerer zu lesen.
|
|
|
|
name: vogelalbum
|
|
|
|
services:
|
|
web:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
restart: unless-stopped
|
|
environment:
|
|
DJANGO_DEBUG: "0"
|
|
# Ohne gesetzten Schluessel erzeugt der Entrypoint beim ersten Start
|
|
# einen und legt ihn aufs Volume. Wer einen eigenen will, traegt ihn
|
|
# in die .env ein.
|
|
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:-}
|
|
DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:-*}
|
|
DJANGO_CSRF_TRUSTED_ORIGINS: ${DJANGO_CSRF_TRUSTED_ORIGINS:-}
|
|
# Derselbe Token, den der Detector als Bearer schickt. Fuer eine
|
|
# einzelne Kamera reicht das — 'manage.py camera add' braucht man erst
|
|
# ab der zweiten.
|
|
VOGELALBUM_INGEST_TOKEN: ${VOGELALBUM_INGEST_TOKEN:?bitte in der .env setzen}
|
|
# Beides MUSS aufs Volume zeigen, sonst sind Sammlung und Fotos nach
|
|
# jedem Neubau weg.
|
|
SQLITE_DIR: /data
|
|
MEDIA_ROOT: /data/media
|
|
volumes:
|
|
- vogelalbum-data:/data
|
|
ports:
|
|
- "${VOGELALBUM_PORT:-8000}:8000"
|
|
|
|
detector:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.detector
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- web
|
|
environment:
|
|
VOGELALBUM_SOURCE: ${VOGELALBUM_SOURCE:?Stream-URL der Kamera, siehe .env.beispiel}
|
|
# Im selben Compose-Netz erreichbar — nichts davon muss nach aussen offen sein.
|
|
VOGELALBUM_API: http://web:8000
|
|
VOGELALBUM_TOKEN: ${VOGELALBUM_INGEST_TOKEN:?bitte in der .env setzen}
|
|
# 'detector' ignoriert Bewegung und laesst das Modell entscheiden.
|
|
# Noetig, sobald die Kamera auf etwas dauerhaft Bewegtes schaut — eine
|
|
# Hecke im Wind loest sonst rund um die Uhr aus. Mit ruhigem Hintergrund
|
|
# spart 'motion' Rechenzeit.
|
|
VOGELALBUM_GATE: ${VOGELALBUM_GATE:-detector}
|
|
VOGELALBUM_SAVE_TO: /daten/rohdaten
|
|
VOGELALBUM_PROTOKOLL: /daten/protokoll.csv
|
|
# Kamera mit Infrarot? Dann hier "1" setzen, sonst pausiert die Analyse
|
|
# nachts von selbst.
|
|
VOGELALBUM_NACHTSICHT: ${VOGELALBUM_NACHTSICHT:-}
|
|
# Live-Bild: der Detector verteilt seinen eigenen Bildstrom weiter,
|
|
# damit Zuschauer der Kamera nichts wegnehmen. Leer = aus.
|
|
VOGELALBUM_LIVE_PORT: ${VOGELALBUM_LIVE_PORT:-0}
|
|
command:
|
|
- watch
|
|
- --classify-every=2
|
|
- --cooldown=5
|
|
- --min-bird-frames=1
|
|
- --verbose
|
|
# 🔴 Hier stand bis zum 09.10.2026 "${VOGELALBUM_LIVE_PORT:-0}:..." — und damit
|
|
# war der Schnellstart aus dem README fuer jeden kaputt, der die .env so
|
|
# liess wie sie ist: Compose weist "0:0" mit "missing a target port" ab,
|
|
# noch bevor irgendetwas gebaut wird.
|
|
#
|
|
# Aufgefallen ist es nie, weil jeder, der das je gestartet hat, den Port
|
|
# gesetzt hatte. Der Standardweg war der einzige ungetestete.
|
|
#
|
|
# Deshalb jetzt eine gueltige Portnummer als Vorgabe. Ob tatsaechlich
|
|
# etwas lauscht, entscheidet VOGELALBUM_LIVE_PORT in der Umgebung oben: auf 0
|
|
# startet der Detector keinen Live-Server, dann fuehrt diese
|
|
# Veroeffentlichung ins Leere — das stoert nicht. Wer den Port aendert,
|
|
# aendert beide Seiten mit derselben Variablen.
|
|
ports:
|
|
- "${VOGELALBUM_LIVE_PORT:-8131}:${VOGELALBUM_LIVE_PORT:-8131}"
|
|
volumes:
|
|
- vogelalbum-rohdaten:/daten
|
|
|
|
volumes:
|
|
# Diese Namen sind neu und duerfen es sein: Wer mit dieser Datei anfaengt,
|
|
# hat noch keine Daten.
|
|
#
|
|
# ⚠️ Wer den Namen an einer LAUFENDEN Anlage aendert, muss die Daten
|
|
# mitnehmen — siehe die Anleitung in docker-compose.yml. Ein Volume-Name
|
|
# ist kein Text, sondern eine Adresse.
|
|
vogelalbum-data:
|
|
vogelalbum-rohdaten:
|