Files
vogelalbum/docs/installation.md
T
christian c11fe9ab04 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.
2026-10-15 14:30:02 +00:00

147 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Installation
<sub>[← zurück zum Überblick](../README.md) · [alle Kapitel](README.md)</sub>
Zwei Wege zum selben Ziel. **Mit Docker** braucht es einen Befehl und keine
Python-Umgebung; **ohne Docker** sieht man mehr und kann einzelne Teile
austauschen.
## Welcher Weg ist meiner?
Vogelalbum besteht aus zwei Teilen, die getrennt laufen können: der **Sammlung**
(Django, zeigt Arten, XP und Abzeichen) und der **Erkennung** (schaut in die
Kamera und meldet Sichtungen). Daraus ergeben sich drei sinnvolle Aufbauten —
und für jeden gibt es genau eine Datei:
| Dein Fall | Datei | Was läuft |
|---|---|---|
| **Eine Kamera im Garten, ein Rechner im Keller.** Der Normalfall, und der richtige Anfang. | `docker-compose.heim.yml` | Sammlung **und** Erkennung auf einer Maschine |
| **Die Sammlung soll öffentlich erreichbar sein**, die Kamera bleibt zu Hause. | `docker-compose.yml` | nur die Sammlung, mit nginx für die Fotos |
| **Der Rechner mit Sicht auf die Kamera** liefert an eine Sammlung woanders. | `docker-compose.detector.yml` | nur die Erkennung |
Die letzten beiden gehören zusammen: Sie sind dieselbe Anlage, aufgeteilt auf
zwei Orte. So läuft auch <https://vogelalbum.gaertner.onl> — Sammlung bei einem
Hoster, Erkennung im Heimnetz.
🔑 **Nach außen muss dafür kein Port offen sein.** Die Verbindung geht nur in
eine Richtung: Die Erkennung meldet ausgehend an die Sammlung, die Sammlung
erreicht die Kamera nie. Kein Portforwarding, kein Tunnel, kein DynDNS.
⚠️ **Wo die Erkennung laufen kann:** `ai-edge-litert` gibt es als fertiges
Wheel für **x86_64 und arm64**. Ein **Pi Zero trägt sie nicht** — dem fehlt
nicht das Wheel, sondern die Rechenleistung; er ist die *Kamera*seite, siehe
[pi/README.md](../pi/README.md).
### Getestet auf
Zwei Geräte, wie sie in vielen Hausnetzen stehen. Beide mit dem Schnellstart
oben eingerichtet, aus einem frischen Klon und mit leerem Build-Zwischenspeicher:
| | **Intel N100** | **Raspberry Pi 4 Model B** |
|---|---|---|
| | 16 GB, Debian, x86_64 | 4 GB, Ubuntu 26.04, aarch64 |
| Images bauen (einmalig) | 69 s | 467 s (knapp 8 min) |
| Sammlung erreichbar nach | 5 s | 49 s |
| **Ein Bild bestimmen** | **~30 ms** | **42 ms** (Median aus 18 Messungen, 35–53 ms) |
| Arbeitsspeicher im Betrieb | — | 1,1 von 3,7 GB |
| Temperatur unter Last | — | 54 °C, keine Drosselung |
🔑 **Der Pi 4 langweilt sich dabei.** Bei 4 Bildern pro Sekunde und
`--classify-every=2` stehen rund **500 ms** je bestimmtem Bild zur Verfügung —
er braucht 42. Er könnte also jedes Bild bestimmen statt jedes zweite und wäre
immer noch bei einem Sechstel. Dass ARM hier so gut mithält, liegt an den
int8-quantisierten Modellen; gerechnet hatten wir mit einem Vielfachen.
Der Preis auf dem Pi sind die acht Minuten Bauzeit und die knappe Minute bis
zur ersten Seite. Beides fällt genau einmal an.
⚠️ **Ungetestet:** Raspberry Pi 5 (sollte schneller sein), Pi 4 mit nur 2 GB,
und 32-Bit-Systeme (dort gibt es kein `ai-edge-litert`-Wheel — Raspberry Pi OS
muss die 64-Bit-Ausgabe sein). Rückmeldungen zu anderer Hardware sind
willkommen, gern als Issue.
Wer gar kein Docker will: [ohne Docker](#schnellstart-ohne-docker) weiter
unten. Und wer nur schauen will, wie es aussieht, braucht nicht einmal eine
Kamera — siehe [Ohne Kamera ausprobieren](#ohne-kamera-ausprobieren).
## Schnellstart mit Docker
Der kürzeste Weg — Sammlung und Erkennung auf einer Maschine, ohne venv, ohne
Modelle von Hand, ohne systemd:
```bash
git clone https://gitea.gaertner.onl/christian/vogelalbum.git && cd vogelalbum
cp .env.beispiel .env # VOGELALBUM_SOURCE und ein Token eintragen
docker compose -f docker-compose.heim.yml up -d
```
Der erste Start baut beide Images (rund eine Minute) und legt den Artenkatalog
an: **148 Arten mit Steckbriefen und 15 Abzeichen.** Die Sammlung steht danach
sofort; die Referenzfotos aus Wikipedia holt der Container im Hintergrund nach
und tropfen über die nächsten Minuten ein.
Danach läuft die Sammlung auf <http://localhost:8000> und der Detector schaut
in die Kamera. Zwei Zeilen in der `.env` müssen stimmen:
| Variable | was rein muss |
|---|---|
| `VOGELALBUM_SOURCE` | Stream-URL der Kamera, z.B. `http://vogelkamera.local:8080/stream` |
| `VOGELALBUM_INGEST_TOKEN` | ein selbst ausgedachtes Geheimnis, `openssl rand -base64 32` |
Alles andere hat brauchbare Vorgaben; den Django-`SECRET_KEY` erzeugt der
Container beim ersten Start selbst und legt ihn aufs Volume.
Noch keine Kamera? Die Kameraseite steht in **[pi/README.md](../pi/README.md)** —
ein Raspberry Pi Zero W mit Kameramodul reicht. Alternativ ein ESP32-S3 mit
Kameramodul: **[esp32cam/README.md](../esp32cam/README.md)**, deutlich billiger
und mit externer Antenne, was der Bildrate mehr hilft als jede Auflösung.
```bash
docker compose -f docker-compose.heim.yml logs -f detector # was sieht er?
docker compose -f docker-compose.heim.yml down # anhalten
```
Sammlung und Rohbilder liegen in Docker-Volumes und überleben ein
`up --build`. Wer die Sammlung öffentlich hosten und nur die Erkennung zu
Hause laufen lassen will, nimmt die beiden anderen Dateien aus der
[Tabelle oben](#welcher-weg-ist-meiner): `docker-compose.yml` beim Hoster,
`docker-compose.detector.yml` zu Hause. Das Deployment der Sammlung steht in
[Betrieb](betrieb.md).
## Schnellstart ohne Docker
Voraussetzungen: Python 3.11+, rund 500 MB Platte, eine Kamera die MJPEG,
RTSP oder Einzelbilder liefert.
```bash
git clone https://gitea.gaertner.onl/christian/vogelalbum.git && cd vogelalbum
python3 -m venv venv
./venv/bin/pip install -r requirements-detector.txt -r requirements-web.txt
./scripts/fetch_models.sh # ~10 MB, liegen nicht im Repo
./scripts/fetch_testdata.sh # drei Beispielfotos, optional
cd web
../venv/bin/python manage.py migrate
../venv/bin/python manage.py seed_dex # 148 Arten, 15 Abzeichen
../venv/bin/python manage.py fetch_reference_images # Wikipedia-Fotos, ~5 min
../venv/bin/python manage.py runserver 0.0.0.0:8000
```
Dann in einem zweiten Terminal:
```bash
./venv/bin/python -m detector watch --source "http://<kamera>:8080/stream"
```
### Ohne Kamera ausprobieren
```bash
cd web
../venv/bin/python manage.py demo_data # 21 Tage Beispieldaten
../venv/bin/python manage.py demo_data --clear
```
Die Demo-Sichtungen benutzen die Wikipedia-Referenzfotos, sind also klar als
Attrappe erkennbar. **Vor dem Echtbetrieb `--clear` laufen lassen**, sonst
mischen sich Demo- und Kameradaten.