A webapp for viewing bird sightings captured by ESP32-CAM microcontrollers. Displays bird images as animated GIFs with date/time and species information.
- Real-time updates via WebSocket - see new birds as they're detected
- Animated GIFs automatically generated from 16-frame captures
- Filtering by bird species, date range, and birdhouse
- Responsive design for desktop and mobile
- REST API for integration with other tools
- Multi-box ready architecture for multiple birdhouses
- Python 3.9+
- HiveMQ Cloud account (or other MQTT broker)
cd tiny-birdiary
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
cd backend
pip install -r requirements.txt# Copy example config
cp .env.example .env
# Edit .env with your MQTT credentials
nano .env # or use your preferred editorRequired settings in .env:
MQTT_HOST=your-cluster.hivemq.cloud
MQTT_PORT=8883
MQTT_USER=your_username
MQTT_PASSWORD=your_password
TOPIC_IMAGE=birdiary/image
TOPIC_CLASSIFICATION=birdiary/classification# From backend directory
python run.pyOpen http://localhost:8000 in your browser.
┌─────────────────┐ MQTT ┌────────────────────────────┐
│ ESP32-CAM │───────────────▶│ TinyBirdiary Backend │
│ (Birdhouse) │ │ ├── MQTT Subscriber │
└─────────────────┘ │ ├── SQLite Database │
│ ├── GIF Generator │
│ └── REST API + WebSocket │
└──────────────┬─────────────┘
│
┌──────────▼──────────┐
│ Web Browser │
│ (Frontend) │
└─────────────────────┘
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/sightings |
List sightings (paginated) |
| GET | /api/sightings/{id} |
Get sighting details |
| GET | /api/sightings/{id}/gif |
Get the GIF file |
| GET | /api/sightings/{id}/images/{seq} |
Get individual frame |
| GET | /api/birds |
List all bird species |
| GET | /api/boxes |
List all birdhouses |
| GET | /api/stats |
Get statistics |
| WS | /ws/live |
Real-time updates |
/api/sightings supports:
bird_name- Filter by species (partial match)box_id- Filter by birdhousefrom_date- Start date (YYYY-MM-DD)to_date- End date (YYYY-MM-DD)page- Page number (default: 1)limit- Items per page (default: 20, max: 100)
tiny-birdiary/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI app
│ │ ├── config.py # Configuration
│ │ ├── database.py # SQLAlchemy setup
│ │ ├── models.py # Database models
│ │ ├── schemas.py # Pydantic schemas
│ │ ├── mqtt_service.py # MQTT subscriber
│ │ ├── gif_generator.py # GIF creation
│ │ ├── websocket_manager.py # Real-time updates
│ │ └── routers/
│ │ └── sightings.py # API endpoints
│ ├── data/
│ │ ├── birdiary.db # SQLite database
│ │ ├── gifs/ # Generated GIFs
│ │ └── images/ # Raw frames
│ ├── requirements.txt
│ ├── .env.example
│ ├── Dockerfile
│ └── run.py
├── frontend/
│ ├── index.html
│ ├── css/styles.css
│ └── js/app.js
├── docker-compose.yml
└── README.md
# Build and run
docker-compose up --build -d
# View logs
docker-compose logs -f
# Stop
docker-compose down- Bird Detection: ESP32-CAM detects a bird and runs classification
- MQTT Messages:
- Classification (bird name) is sent to
birdiary/classification - 16 images are sent sequentially to
birdiary/image
- Classification (bird name) is sent to
- Backend Processing:
- Receives classification → creates new sighting record
- Receives images → stores frames to disk
- On next classification → generates GIF from frames
- Frontend Display:
- WebSocket receives real-time notification
- Gallery updates automatically with new sighting
The architecture supports multiple birdhouses:
- Update microcontroller to use topics like
birdiary/{box_id}/image - Backend will extract box_id from topic and store per-box
- Frontend already has box filtering built-in
# Run with auto-reload
cd backend
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# API docs at http://localhost:8000/docsMIT License - See LICENSE file for details.