A live, hand-illustrated collage of the birds outside your window — named by ear.
A single $17 USB microphone in your window turns the birds outside into a living collage. Belkins BirdNET listens through the mic, lets Cornell's BirdNET name every passing call, and blooms each species onto the screen as a hand-painted kachō-e illustration — sized by how often it's been heard and repainted within seconds of each new detection.
500 bundled illustrations across 250 species, a Gemini pipeline to restyle them for your region, an optional e-ink frame for your wall — and one read-only SQLite file at the heart of it all.
Belkins BirdNET is a standalone build of BirdNET-Pi; the live-collage concept is inspired by AvianVisitors. Kudos, license, and full Cornell attribution are below.
The Living Gallery — a dark nocturne theme (with a light day theme), where every detected bird is spotlit. Collage · Index · Stats · Atlas.
A handful of the 500 bundled kachō-e illustrations — every species ships in a perched and a flight pose.
From a microphone in the window to a hand-painted bird on the wall — every arrow is real data flow.
flowchart LR
classDef cap fill:#fde68a,stroke:#d97706,color:#3f2d00;
classDef det fill:#bfdbfe,stroke:#2563eb,color:#0b2447;
classDef sto fill:#c7f9e5,stroke:#0d9488,color:#06372b;
classDef ill fill:#fbcfe8,stroke:#db2777,color:#4a0d2b;
classDef disp fill:#ddd6fe,stroke:#7c3aed,color:#2a1259;
classDef fwd fill:#fecaca,stroke:#dc2626,color:#4c0519;
classDef frm fill:#fed7aa,stroke:#ea580c,color:#451a03;
subgraph LISTEN [" Listen "]
mic["USB lavalier mic"]:::cap
rec["BirdNET-Pi recorder"]:::cap
end
subgraph IDENT [" Identify "]
model["BirdNET 6K v2.4<br/>6,522 labels"]:::det
ana["birdnet_analysis.py"]:::det
end
subgraph CORE [" Store + Read API "]
db[("birds.db<br/>SQLite")]:::sto
media["By_Date<br/>mp3 + spectrogram"]:::sto
api["birdnet-api.php"]:::sto
cut["cutout.php<br/>image resolver"]:::sto
end
subgraph ART [" Illustrate (optional) "]
gemini["Gemini 2.5<br/>Flash Image"]:::ill
pregen["pregen.py"]:::ill
cutpy["cutout.py<br/>BiRefNet matte"]:::ill
illus["500 illustrations<br/>250 species"]:::ill
end
subgraph SHOW [" Show "]
ui["Collage UI<br/>apt.js"]:::disp
web["web/ React shell"]:::disp
cast["birdcast<br/>SSE :8090"]:::disp
caddy["Caddy + PHP-FPM<br/>birdnet.local"]:::disp
end
subgraph WALL [" Wall frame "]
bw["BirdWeather<br/>GraphQL"]:::frm
shoot["shoot.py"]:::frm
disp["display.py"]:::frm
inky["Inky 13.3in<br/>e-ink Spectra-6"]:::frm
end
subgraph OUT [" Forward "]
cf["Cloudflare Tunnel"]:::fwd
ha["Home Assistant"]:::fwd
mqtt["MQTT bridge"]:::fwd
end
mic --> rec -->|"WAV segment"| ana
model --> ana
ana -->|"detection row"| db
ana -->|"clip + png"| media
ana -. "emit_detected" .-> cast
db --> api
db --> cast
media --> api
illus --> cut
gemini --> pregen --> cutpy --> illus
api --> ui
cut --> ui
api --> web
cast -. "bird.detected, under 3s" .-> web
ui --> caddy
web --> caddy
caddy --> cf
api --> ha
api --> mqtt
ui -->|"1200x1600 shot"| shoot
bw --> shoot
shoot --> disp --> inky
| 500 bundled illustrations |
250 species (perched + flight) |
6,522 BirdNET model labels |
under 3s detection → screen |
| 158 photo-cutout fallbacks |
3 off-LAN forwarding recipes |
13.3" Spectra-6 e-ink panel |
~$70 mic + Pi build cost |
| Qty | Description | Price | Link | Notes |
|---|---|---|---|---|
| 1 | Raspberry Pi (4B / 5 / Zero 2 W) | ~$35–80 | Amazon | RPi0W2 note |
| 1 | Micro SD card (≥32 GB) | ~$10 | Amazon | |
| 1 | USB lavalier microphone | $16.95 | Amazon | |
| 1 | Pi power supply | ~$10 | — |
Optional: a Gemini API key to restyle illustrations, and an eBird API key to filter species by region.
Use Raspberry Pi Imager → Raspberry Pi OS Lite (64-bit). In the customisation dialog set a username, WiFi SSID + password, hostname birdnet, and enable SSH with password auth. Plug the USB mic into the Pi, place the capsule in a window, and boot.
Assumes passwordless sudo (the Raspberry Pi OS Lite default).
ssh <your-username>@birdnet.local
curl -s https://raw.githubusercontent.com/Belkins/belkins-birdnet/main/newinstaller.sh | bashClones this repo, installs BirdNET-Pi, and symlinks the Belkins BirdNET overlay into the Caddy web root. Takes 20–40 minutes and reboots when done.
- Collage:
http://birdnet.local/ - Stock BirdNET-Pi UI:
http://birdnet.local/index.php - The menu button (top-right) opens an admin overlay with settings, system, log, and tool panels.
The repo ships with 500 bundled illustrations. To restyle them or generate a set for your own region:
pip install -r ~/BirdNET-Pi/avian/scripts/requirements.txt
export GEMINI_API_KEY='your-key' # image generation requires billing enabled
# generate on a cream ground → cut the ground off → rebuild the collage masks
python3 ~/BirdNET-Pi/avian/scripts/pregen.py --labels ~/BirdNET-Pi/model/labels.txt --force
python3 ~/BirdNET-Pi/avian/scripts/cutout.py
python3 ~/BirdNET-Pi/avian/scripts/build_masks.pyFilter to your region with --ebird-region US-CA (needs EBIRD_API_KEY). The full pipeline, prompt, reference images, and per-species tuning live in avian/scripts/README.md; the style lives in prompt.template.md.
New work in this build: a stdlib Server-Sent-Events spine so detections paint the instant BirdNET writes them.
avian/realtime/birdcast.py—POST /emitin,GET /eventsout, ~500-event replay ring buffer, readsbirds.dbread-only.web/— a Vite + React + TypeScript collage shell that seeds from the snapshot API, subscribes to the SSE stream, and paints in each new bird (Canvas2D fade + scale, no re-pack). Runs with no backend at all vianpm run dev:mock.
# on the Pi — additive, idempotent, non-destructive. Brings up the SSE spine +
# the React collage at /collage (and the auto-gen watcher below, if its env is set).
bash deploy-christina.shdeploy-realtime.sh is the spine-only subset if you don't want the collage yet.
The collage ships 250 illustrated species. When BirdNET hears one that isn't bundled, the auto-gen watcher generates its kachō-e illustration on the fly and paints it in — no human in the loop.
detection → forwarder (Pi) ──HTTPS──▶ birdgen (Railway) ──▶ Gemini + cream-key cutout
│
collage ◀── cutout.php 302 ◀── /asset/<slug>.png ◀───────┘ (frontend retries → paints)
services/birdgen/— a small FastAPI service that deploys to Railway: a Bearer-authPOST /detectedwebhook, a single-flight queue,pregen.gen_one+ the cream-key cutout, an SQLite-lease dedup state machine (queued → generating → done/dead), andGET /asset/<slug>.pngoff a persistent volume. The Gemini key lives only here — never on the Pi.avian/realtime/forwarder.py— a Pi-side daemon that subscribes to the birdcast SSE, drops bundled / low-confidence (<0.70) detections, and forwards genuinely-new species to Railway (plus a reconcile sweep every 6 h that heals anything the live stream missed). Holds only a rotatable webhook secret.avian/api/cutout.php— withAV_RAILWAY_ASSET_BASEset, a long-tail miss302-redirects to the Railway asset (unset → unchanged behavior).avian/realtime/railway_liveness.py— a 6-hourly systemd timer that pushes a phone alert (ntfy) if the Railway service ever goes dark.avian/api/regen.php— the repaint gesture: anyone on the LAN can ask the museum to repaint a plate from the bird dossier (repaint ↺). The old plate stays on the wall until its replacement passes every QA gate (never-worse, atomic swap, previous plate archived to_prev/); presses are cooled down per species (15 min) and globally, spend is fenced by a $6/month manual sub-budget inside the $20 ledger, and the endpoint stays dark until armed with pool-env credentials (AV_RAILWAY_API_BASE+AV_REGEN_SECRETin the php-fpm pool — the secret never reaches a browser). The popup's control budget is constitutional: seedocs/POPUP-BUDGET.md.
# deploy the generator (needs a Railway account + a billing-enabled Gemini key)
cd services/birdgen
railway up
railway volume add -m /data/assets
railway variables set GEMINI_API_KEY=… WATCHER_WEBHOOK_SECRET=…
railway domain
# then on the Pi, wire it (same secret + the Railway URL):
CHRISTINA_RAILWAY_BASE=https://<svc>.up.railway.app \
CHRISTINA_WEBHOOK_SECRET=<secret> bash deploy-christina.shCost: ~$0.04 per genuinely-new species, on-demand. Generation requires a billing-enabled Gemini key; the worker is single-flight, deduped, and degrades gracefully — if Railway is down the collage keeps running, just without new art.
Three independent recipes in avian/forwarding/:
- Cloudflare Tunnel — a public HTTPS URL with no port-forwarding.
- Home Assistant — a REST sensor exposing the latest detection.
- MQTT bridge — publishes every new detection to your broker.
An optional e-ink frame mirrors the last 24h of birds onto a panel by your window — in the nocturne or day theme. Build it from frame/. It can run off your own BirdNET mic, or standalone from BirdWeather for any ZIP code with no mic at all.
Left running on a wall screen, or printed to the 13.3" Spectra-6 e-ink frame — same composition, six inks, day or night.
avian/ # everything Belkins BirdNET adds to BirdNET-Pi
├── frontend/ # static HTML/JS/CSS for the collage
├── assets/ # bundled kachō-e illustrations + photo-cutout fallbacks
├── api/ # PHP shims served by BirdNET-Pi's PHP-FPM (cutout.php 302)
├── scripts/ # generate → cutout (creamkey) → masks pipeline + prompt
├── realtime/ # birdcast SSE spine + forwarder + liveness monitor
└── forwarding/ # optional HA / MQTT / Cloudflare configs
web/ # next-gen React + TS collage shell (live SSE)
services/birdgen/ # Railway: on-demand kachō-e generator (Gemini + cream-key)
frame/ # optional e-ink wall display
deploy-christina.sh # one-shot full-stack deploy on the Pi (spine + collage + watcher)
Everything outside avian/, web/, services/, and frame/ is upstream BirdNET-Pi.
Belkins BirdNET stands on the work of others:
- AvianVisitors by Twarner491 — the original live-collage idea, the kachō-e bird treatment, and the overlay this build grew from. Thank you for the inspiration. 🐦
- BirdNET-Pi (Nachtzuster · Patrick McGuire) — the recording + detection foundation.
- The K. Lisa Yang Center for Conservation Bioacoustics, Cornell Lab of Ornithology — the BirdNET model itself.
CC-BY-NC-SA-4.0, inherited from BirdNET-Pi. Non-commercial use only. See the BirdNET-Pi README for full Cornell attribution.
BirdNET-Lite and the BirdNET model are © the K. Lisa Yang Center for Conservation Bioacoustics, Cornell Lab of Ornithology. BirdNET-Pi is © Patrick McGuire. Belkins BirdNET is a derivative work distributed under the same CC-BY-NC-SA-4.0 terms — see
LICENSE.
Fork · Watch · Open an issue
Made by Belkins · inspired by AvianVisitors · built on the shoulders of BirdNET-Pi and the Cornell Lab of Ornithology.














