Skip to content

About

A living framed print that quietly reflects the birds heard in the garden — local BirdNET detection composed into an hourly editorial e-ink poster.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

Repository files navigation

Heard Today

A living piece of art that quietly reflects the birds visiting our garden.

This is not a dashboard, a smart display, or an IoT gadget. It is a framed editorial wildlife print that hangs beside the kitchen window and slowly evolves through the day as birds are heard in the garden. It never animates, never flashes, never notifies. It simply observes.

Mock-up of the framed print beside the window

How it works

A small pipeline of independent components, each replaceable without touching the others:

microphone → BirdNET → SQLite → composer → renderer → e-ink display
  1. Listen — BirdNET performs local inference on the Raspberry Pi. No audio ever leaves the device; only confirmed detections (species, confidence, timestamp) are stored.
  2. Accumulate — detections gather in SQLite through the day.
  3. Compose — once an hour, the previous 24 hours are aggregated by species and turned into a balanced, organic poster layout. The most-heard bird is largest; rarer visitors are smaller.
  4. Render — the layout is drawn as an editorial print (HTML/CSS → headless Chromium) from a curated library of transparent bird illustrations. No AI images are generated at runtime — the art is deterministic, consistent, offline, and free to produce.
  5. Display — the poster refreshes on a large colour e-ink panel, once per hour. That slow cadence is the point.

The only things ever shown are the artwork, the title (Heard / Today), and the species names. No numbers, no graphs, no statistics. Abundance is communicated through composition.

A poster produced by the current pipeline (with placeholder illustrations):

Sample rendered poster

Design principles

  • Calm technology — no interaction; changes are discovered, not pushed.
  • Slow computing — hourly refresh; nothing is instant.
  • Art first — it should be worth hanging even if it weren't smart.
  • Minimal data — names and artwork only.
  • Privacy by structure — recognition is local; no raw audio is retained.

Whenever an implementation choice arises, we prefer whichever option best preserves the illusion that this is simply a beautiful framed print quietly observing the garden.

Repository layout

src/heard_today/
  domain.py        Immutable, typed core values (Detection, Composition, …)
  config.py        One injected Settings object; the only reader of env vars
  interfaces.py    Protocols for every component boundary (the seams)
  assets.py        The illustration library (manifest-driven)
  audio/           Detectors: BirdNET (Pi) and a replay fake (Mac dev)
  database/        SQLite detection store + 24h aggregation
  composer/        Deterministic organic layout engine (pure)
  renderer/        HTML/CSS template → headless Chromium PNG
  display/          E-ink driver (Pi) and preview display (Mac dev)
  pipeline.py      The hourly refresh orchestrator
  scheduler.py     Slow, on-the-hour scheduling
  listener.py      The continuous detection loop
  factory.py       Composition root — the one place wiring happens
  cli.py           `heard` command-line entry points
  api/             Reserved for future read-only extensions
assets/birds/      Transparent bird illustrations + manifest.json
fonts/             Title & caption typefaces (optional; system fallback)
docs/              Architecture and decision records
scripts/dev/       Development helpers (placeholder asset generation)
tests/             Unit tests

Getting started (development, on a Mac)

Requires uv.

# Install with dev + rendering extras (no BirdNET / e-ink needed on a Mac)
uv pip install -e ".[dev,render]"

# Install the headless browser used for rendering
uv run playwright install chromium

# Generate placeholder illustrations (until the real library exists)
uv run python scripts/dev/generate_placeholder_assets.py

# Seed the database with a plausible stream of garden birds
uv run heard seed

# Compose, render, and open a poster
uv run heard preview

To watch it behave like the real thing, run the listener and the hourly refresh in two terminals:

uv run heard listen --replay     # writes fake detections continuously
uv run heard run                 # refreshes the preview poster every hour

On the Raspberry Pi

Install the hardware extras and use the real components:

uv pip install -e ".[render,audio,eink]"
uv run heard listen              # real BirdNET inference
uv run heard run --eink          # drive the e-ink panel hourly

(The BirdNET capture loop and e-ink output are documented stubs until the hardware is in hand — see src/heard_today/audio/birdnet.py and src/heard_today/display/eink.py.)

Quality

uv run ruff check .
uv run mypy
uv run pytest

Strong typing throughout, clear separation of concerns, dependency injection at the seams, and every component replaceable in isolation. See docs/ for the reasoning behind the major decisions.

Licence

MIT — see LICENSE.

About

A living framed print that quietly reflects the birds heard in the garden — local BirdNET detection composed into an hourly editorial e-ink poster.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages