AI-powered hummingbird surveillance based in Bartlett. Focused exclusively on Ruby-throated hummingbirdsβthe only ones fast (and chaotic) enough to matter.
Monitoring nectar activity and tracking unauthorized flight in real time.
A Raspberry Pi with a USB camera, a bird classifier that knows 964 species, and a GPT-4o that writes captions with zero supervision. What could go wrong.
When a Ruby-throated Hummingbird hits the feeder, the system:
- detects it through a multi-stage AI pipeline (motion, color, species classification)
- records a 25-second clip with audio β because the wing buzz is evidence
- GPT-4o analyzes the actual video frames and writes a caption about what the bird is doing
- checks the weather so it can work that into the commentary
- and posts it to Facebook, Twitter/X, Bluesky, Instagram, and TikTok simultaneously before the bird even leaves
Follow the operation: Facebook | Bluesky | X | Instagram | Website
My wife showed me an AI hummingbird cam online. I looked at the Raspberry Pi collecting dust on my desk and said:
"Hold my nectar β I can build that."
...and now I accidentally run a full-blown hummingbird surveillance state out of my backyard in Bartlett, TN.
- Multi-stage detection pipeline β motion, HSV color filtering, and a MobileNetV2 bird classifier running locally on the Pi. It went through an embarrassing phase of reporting leaves, shadows, and personal betrayal before we got here.
- Records with sound β 25-second clips (5s pre-roll + 20s post-detection) because you need the wing buzz for the full experience
- GPT-4o writes the captions β unhinged, slightly suggestive, occasionally better than anything a human would write. Never explains its own jokes.
- Vision-based captions β GPT-4o actually looks at the video frames and describes what the bird is doing. Hovering, feeding, fighting, flexing β it sees it all.
- Weather-aware commentary β pulls real-time weather from OpenWeatherMap so captions can reference the 97-degree heat or the surprise rain. Context matters.
- Multi-platform posting β auto-posts to Facebook, Twitter/X, Bluesky, Instagram, and TikTok simultaneously. Configure whichever platforms you want β the system auto-discovers what's enabled and posts everywhere at once.
- AI comment replies β GPT-4o monitors Facebook comments and fires back witty replies autonomously. Rate-limited so it doesn't go feral.
- Morning briefings β sunrise check-in with yesterday's tally. Posted with a live camera snapshot. The feeders are full. The operation is active.
- Goodnight recaps β daily stats, peak activity hour, and whether we broke the all-time record. Celebrates milestones at 100, 250, 500, and 1000+ lifetime detections.
- Weekly digest β auto-generated recap with a 6-image thumbnail collage, total visits, trends, and busiest day. Posted to all platforms on your configured day.
- Feeding pattern predictions β tracks historical visit patterns by hour and estimates when the next hummingbird will show up. Confidence levels and everything.
- AI-powered insights β GPT-4o analyzes your analytics data and generates narrative summaries about feeding trends, peak hours, and activity patterns.
- Live dashboard β real-time camera feed, audio, detection states, analytics, system vitals. Full mission control energy.
- Trains itself β label frames as "bird" or "not bird" from the dashboard. Teach it to stop falling for leaves.
- Self-healing β camera unplugged? It retries every 10 seconds. Failed Facebook post? Queued for retry. App restart? Picks up where it left off.
- Night mode β auto sleep at sunset, auto wake before sunrise. Even surveillance operations need rest.
- B-Hyve mister control β connects to an Orbit B-Hyve sprinkler system via cloud API and WebSocket. Automated sunrise-relative watering schedule keeps feeders misted on interval. Start/stop from the dashboard. Watering events are logged and correlated with bird sightings.
- Comprehensive analytics β weather-activity correlations, multi-bird counting, behavior classification (hovering, feeding, fighting, flexing), position heatmaps, activity streaks, year-over-year comparisons, and monthly trend analysis.
- Feeder management β track refills, nectar production, days since last refill, and active feeder count. Log entries with optional backdated timestamps.
- Public website β backyardhummers.com with live camera feed, interactive Chart.js stats, gallery, and analytics synced from the Pi to SiteGround via SSH.
- One-button updates β git pull, reinstall deps, restart service. From the dashboard. Because manual deployments are beneath us.
- Raspberry Pi 3B+ (or newer) β the field agent
- USB webcam with built-in mic β eyes and ears
- 32GB+ SD card β evidence storage
- Power supply (5V/2.5A minimum) β keeps the operation running
- Hummingbird feeder β the honeypot (technically nectarpot)
Grab Raspberry Pi Imager:
- OS: Raspberry Pi OS (64-bit) Lite
- Settings: hostname
hummingbirdcam, usernamepi, WiFi, enable SSH
Plug in the USB camera, power on, wait 2 minutes:
sudo apt install -y git && git clone https://github.com/LeeOtts/LocalHummingBirdCam.git && cd LocalHummingBirdCam && python3 -m venv --system-site-packages venv && source venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txtcd ~/LocalHummingBirdCam
sudo cp scripts/hummingbird.service /etc/systemd/system/
sudo cp scripts/hummingbird-updater.service /etc/systemd/system/
sudo cp scripts/hummingbird-sudoers /etc/sudoers.d/hummingbird
sudo chmod 440 /etc/sudoers.d/hummingbird
chmod +x scripts/auto_update.sh
sudo systemctl daemon-reload
sudo systemctl enable hummingbirdcp .env.example .env
nano .envFor Azure OpenAI (recommended):
OPENAI_API_KEY=your-azure-api-key
AZURE_OPENAI_ENDPOINT=https://your-resource.cognitiveservices.azure.com/
AZURE_OPENAI_DEPLOYMENT=gpt-4o
AZURE_OPENAI_API_VERSION=2024-12-01-preview
For direct OpenAI:
OPENAI_API_KEY=sk-your-key-here
Facebook (required for full experience):
source venv/bin/activate
python scripts/setup_facebook_token.pyGrab your App ID, App Secret, and short-lived token. The script converts it to a permanent token.
Twitter/X (optional): Create a Twitter Developer app, get your API keys and access tokens, add them to .env.
Bluesky (optional): Generate an app password at bsky.app/settings/app-passwords, add your handle and password to .env.
Instagram (optional): Requires a Meta Business Suite account. Get your INSTAGRAM_BUSINESS_ACCOUNT_ID and INSTAGRAM_USER_ID from Meta Business Suite, add them to .env. Uses the same Facebook Page Access Token.
TikTok (optional): Create a TikTok Developer app, complete OAuth to get your access and refresh tokens, add them to .env. Use scripts/tiktok_auth.py to help with the OAuth flow.
The system auto-discovers which platforms are configured and posts to all of them.
sudo systemctl start hummingbirdhttp://hummingbirdcam.local:8080
Starts in Test Mode so you don't accidentally spam your page on day one. Disable it when you're ready to go live.
The detection pipeline β four layers of increasingly paranoid verification:
-
Motion + Color (~1ms) β Scans every frame for movement in the right size range, then checks for iridescent green, ruby-red, and rufous-orange hummingbird colors. Fast, cheap, and only slightly paranoid. Requires 5 consecutive frames to trigger β no more single-leaf meltdowns.
-
Bird Species Classifier (~1-2 sec on Pi) β MobileNetV2 trained on 964 bird species. Runs fully local on the Pi, no cloud needed. The "prove you're actually a hummingbird" checkpoint.
-
Record + Post β 25 seconds of evidence. GPT-4o analyzes the frames, checks the weather, writes the caption, and blasts it to Facebook, Twitter/X, Bluesky, Instagram, and TikTok. The bird has no idea it's internet famous on five platforms.
Hit http://hummingbirdcam.local:8080 β welcome to mission control:
- Live camera feed with detection overlays and real-time audio surveillance
- Detection status indicators:
- Green = hummingbird confirmed, recording in progress
- Yellow = motion detected, investigating
- Blue = running verification
- Red = rejected (nice try, leaf)
- Purple = night mode, system sleeping
- Red glow = camera error, retrying
- Camera controls β rotation, test recording, mic test
- Training interface β label frames to make the classifier smarter
- Clip browser β review, play, delete, or admire your regulars
- Analytics panel β feeding patterns, hourly distribution, next-visit predictions, weather correlations, behavior breakdown, position heatmaps, AI-generated insights
- Feeder management β log refills and nectar production, track days since last refill, active feeder count
- B-Hyve mister controls β start/stop watering, connection status, schedule configuration (interval, run time, offset), today's watering times
- Social engagement β likes, shares, comments, follower trends across platforms
- System stats β uptime, detections today, posts today, cooldowns, schedule, git version
- Hardware vitals β CPU temp, RAM usage, disk space
- Live logs β because something always breaks eventually
- One-click update β pull latest code and restart without SSH
Everything lives in .env. See .env.example for full details.
| Setting | Default | What It Does |
|---|---|---|
OPENAI_API_KEY |
API key (Azure or OpenAI) | |
AZURE_OPENAI_ENDPOINT |
Azure endpoint URL (blank = direct OpenAI) | |
AZURE_OPENAI_DEPLOYMENT |
gpt-4o |
Azure model deployment name |
AZURE_OPENAI_API_VERSION |
2024-12-01-preview |
Azure API version |
FACEBOOK_PAGE_ID |
Your Facebook page ID | |
FACEBOOK_PAGE_ACCESS_TOKEN |
Permanent page token | |
TWITTER_API_KEY |
Twitter/X API key | |
TWITTER_API_SECRET |
Twitter/X API secret | |
TWITTER_ACCESS_TOKEN |
Twitter/X access token | |
TWITTER_ACCESS_SECRET |
Twitter/X access secret | |
BLUESKY_HANDLE |
Bluesky handle (e.g. you.bsky.social) |
|
BLUESKY_APP_PASSWORD |
Bluesky app password | |
INSTAGRAM_BUSINESS_ACCOUNT_ID |
Instagram Business account ID | |
INSTAGRAM_USER_ID |
Instagram user ID | |
INSTAGRAM_MAX_POSTS_PER_DAY |
10 |
Daily Instagram post limit |
TIKTOK_CLIENT_KEY |
TikTok Developer app client key | |
TIKTOK_CLIENT_SECRET |
TikTok Developer app client secret | |
TIKTOK_ACCESS_TOKEN |
TikTok OAuth access token | |
TIKTOK_REFRESH_TOKEN |
TikTok OAuth refresh token | |
TIKTOK_MAX_POSTS_PER_DAY |
10 |
Daily TikTok post limit |
TIKTOK_PRIVACY_LEVEL |
PUBLIC_TO_EVERYONE |
TikTok video privacy setting |
OPENWEATHERMAP_API_KEY |
OpenWeatherMap API key (free tier) | |
AUTO_REPLY_ENABLED |
false |
GPT-4o auto-replies to Facebook comments |
AUTO_REPLY_MAX_PER_HOUR |
10 |
Rate limit for AI comment replies |
WEEKLY_DIGEST_ENABLED |
false |
Post weekly recap with thumbnail collage |
WEEKLY_DIGEST_DAY |
sunday |
Day of week to post the digest |
VISION_CAPTION_ENABLED |
true |
GPT-4o analyzes frames for captions |
CAMERA_TYPE |
usb |
usb, picamera, or auto |
USB_CAMERA_INDEX |
0 |
Which /dev/video to use |
CAMERA_ROTATION |
0 |
0, 90, 180, 270 degrees |
AUDIO_ENABLED |
true |
Record sound with clips |
AUDIO_DEVICE |
default |
ALSA mic device (arecord -l to list) |
VISION_VERIFY_ENABLED |
true |
Use bird classifier to confirm |
TEST_MODE |
true |
Record but don't post (disable when ready) |
MOTION_THRESHOLD |
15.0 |
Motion sensitivity |
COLOR_MIN_AREA |
300 |
Min hummingbird-colored pixels |
COLOR_MAX_AREA |
5000 |
Max (rejects big objects) |
DETECTION_COOLDOWN_SECONDS |
60 |
Seconds between detections |
MAX_POSTS_PER_DAY |
10 |
Daily Facebook post limit |
CLIP_PRE_SECONDS |
5 |
Pre-detection buffer |
CLIP_POST_SECONDS |
20 |
Post-detection recording |
VIDEO_WIDTH |
1920 |
Video resolution width |
VIDEO_HEIGHT |
1080 |
Video resolution height |
VIDEO_FPS |
15 |
Frames per second |
VIDEO_BITRATE |
5000000 |
Video bitrate (bps) |
MAX_CLIPS_DISK_MB |
2000 |
Auto-delete oldest clips above this |
NIGHT_MODE_ENABLED |
true |
Auto sleep at sunset, wake at sunrise |
LOCATION_LAT |
35.1495 |
Your latitude |
LOCATION_LNG |
-89.8733 |
Your longitude |
LOCATION_TIMEZONE |
America/Chicago |
Your timezone |
LOCATION_NAME |
Bartlett, TN |
Shown on dashboard and posts |
WAKE_BEFORE_SUNRISE_MIN |
30 |
Minutes before sunrise to wake up |
SLEEP_AFTER_SUNSET_MIN |
30 |
Minutes after sunset to sleep |
WEB_PORT |
8080 |
Dashboard port |
BHYVE_EMAIL |
Orbit B-Hyve account email | |
BHYVE_PASSWORD |
Orbit B-Hyve account password | |
BHYVE_STATION |
1 |
Which zone to monitor (1-based, 0 = any) |
BHYVE_RUN_MINUTES |
5 |
Duration per watering cycle |
BHYVE_MAX_RUN_MINUTES |
30 |
Safety cap on watering duration |
BHYVE_SCHEDULE_ENABLED |
true |
Automated sunrise-relative watering |
BHYVE_SCHEDULE_OFFSET_HOURS |
3 |
Hours after sunrise to start watering |
BHYVE_SCHEDULE_INTERVAL_HOURS |
3 |
Hours between watering cycles |
WEBSITE_REMOTE_HOST |
SiteGround SSH hostname for website sync | |
WEBSITE_REMOTE_USER |
SiteGround SSH username | |
WEBSITE_REMOTE_PORT |
SiteGround SSH port | |
WEBSITE_REMOTE_PATH |
public_html |
Remote path for website files |
Access the dashboard and SSH from anywhere using Tailscale β no port forwarding required.
Setup on the Pi:
bash scripts/setup_tailscale.shThis installs Tailscale, enables Tailscale SSH, and prints your Tailscale IP. Follow the authentication URL that appears to log in to your Tailscale account.
Access remotely from any device on your Tailscale network:
http://<tailscale-ip>:8080 # Dashboard
ssh pi@<tailscale-hostname> # SSH
Show Tailscale status on the dashboard by adding to .env:
TAILSCALE_ENABLED=true
Optional β public sharing via Tailscale Funnel:
bash scripts/setup_tailscale.sh --funnelSecurity tip: Set
WEB_PASSWORDin.envwhen enabling remote access β without it, anyone on your Tailscale network can view the dashboard.
| What | How |
|---|---|
| Is it running? | sudo systemctl status hummingbird |
| Restart | sudo systemctl restart hummingbird |
| Stop | sudo systemctl stop hummingbird |
| Live logs | journalctl -u hummingbird -f |
| Camera check | ls /dev/video* |
| List mics | arecord -l |
| Pi temp | vcgencmd measure_temp |
| Set timezone | sudo timedatectl set-timezone America/Chicago |
| Dashboard | http://hummingbirdcam.local:8080 |
LocalHummingBirdCam/
βββ main.py # The brains of the operation
βββ config.py # Every knob and dial
βββ schedule.py # Sunrise/sunset automation
βββ camera/
β βββ stream.py # USB + Pi Camera with rotation
β βββ recorder.py # Video + audio capture via ffmpeg
βββ detection/
β βββ detector.py # Base detector interface
β βββ motion_color.py # Motion + HSV color filtering
β βββ custom_classifier.py # Lightweight retraining
β βββ vision_verify.py # MobileNetV2 bird classifier (TFLite)
βββ analytics/
β βββ behavior.py # Behavior classification
β βββ patterns.py # Feeding patterns, predictions, AI insights
βββ bhyve/
β βββ monitor.py # Orbit B-Hyve cloud API + WebSocket
β βββ scheduler.py # Automated sunrise-relative watering
βββ data/
β βββ sightings.py # SQLite sightings database
βββ social/
β βββ poster_manager.py # Multi-platform auto-discovery & routing
β βββ comment_generator.py # GPT-4o caption generation
β βββ comment_responder.py # AI auto-replies to Facebook comments
β βββ facebook_poster.py # Facebook Graph API posting
β βββ twitter_poster.py # Twitter/X via tweepy
β βββ bluesky_poster.py # Bluesky via AT Protocol
β βββ instagram_poster.py # Instagram via Meta Graph API
β βββ tiktok_poster.py # TikTok video posting
β βββ engagement.py # Social metrics tracking
β βββ digest.py # Weekly recap with thumbnail collage
βββ web/
β βββ dashboard.py # Flask dashboard + live feed
β βββ static/ # Banner and static assets
βββ website/ # Public website (backyardhummers.com)
β βββ index.html # Landing page with live feed
β βββ stats.html # Interactive analytics (Chart.js)
β βββ gallery.html # Video gallery
β βββ js/ # Frontend scripts
β βββ css/ # Stylesheets
β βββ data/ # Exported analytics (site_data.json)
βββ scripts/
β βββ setup_facebook_token.py # Facebook token setup
β βββ tiktok_auth.py # TikTok OAuth flow
β βββ generate_site_data.py # Sync analytics to website
β βββ auto_update.sh # Git pull + restart
β βββ hummingbird.service # systemd service
β βββ hummingbird-updater.service # Auto-update service
β βββ hummingbird-updater.timer # Update timer
β βββ hummingbird-sudoers # Passwordless restart perms
β βββ install_dependencies.sh # Full system setup
βββ tests/ # Unit tests
βββ models/ # Bird classifier (auto-downloaded)
βββ clips/ # Hummingbird evidence
βββ training/ # Labeled frames for retraining
βββ logs/ # Rotating log files
This started as "I can do that" and turned into a multi-stage AI surveillance pipeline with five-platform social media posting, weather-aware vision captions, autonomous comment replies, feeding pattern predictions, weekly digests, a B-Hyve mister keeping the feeders fresh on schedule, a public website with interactive analytics, and a GPT that writes better captions than I do.
It is absolutely over-engineered. It will never not be over-engineered. That is the point.
Follow along:
- Website: backyardhummers.com
- Facebook: facebook.com/backyard.hummers
- Bluesky: backyardhummers.bsky.social
- Twitter/X: x.com/backyardhummers
- Instagram: instagram.com/backyard.hummers
- Source code: github.com/LeeOtts/LocalHummingBirdCam