Vogelalbum 1.0.0

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.
This commit is contained in:
christian committed 2026-10-14 18:55:23 +00:00
commit cc9e0786c2
189 files changed
+29792

No files matched your search

+100
View File
@@ -0,0 +1,100 @@
# 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: