Skip to main content

preen

Groom your photo library — automatically find and name every bird.

Preen scans your macOS Photos library, detects birds with YOLO, identifies species with SuperPicky's OSEA classifier (10,964 species), and writes bilingual keywords and captions.

Features

  • Scans entire Photos library including iCloud photos
  • YOLO multi-bird detection — finds all birds in a photo
  • OSEA species identification with GPS-based eBird regional filtering
  • Keywords: 白鹭 (Little Egret) + pinyin bailu per species
  • Captions: 白鹭, 苍鹭 (Little Egret, Grey Heron)
  • Parallel iCloud downloads via PhotoKit (no Photos.app dependency for reads)
  • SQLite checkpoint — pause/resume, incremental or full rescan
  • Auto-retries failed iCloud exports on next run
  • Supports JPEG, HEIC, JXL, AVIF, and RAW formats (ARW, CR2, CR3, NEF, DNG, RAF)

Requirements

  • macOS with Photos.app
  • Python 3.11+

Installation

pipx install birdpreen

Or with pip:

pip install birdpreen

On first scan, model files (~260 MB) are automatically downloaded from HuggingFace.

Usage

# Scan new photos (incremental)
preen scan

# Full library rescan
preen scan --full

# Dry run — detect and identify without writing
preen scan --dry-run

# Custom confidence threshold (default: 80%)
preen scan --threshold 65

# Process in batches
preen scan --batch-size 500

# Adjust parallel iCloud downloads (default: 16)
preen scan --workers 32

# Regional filter for photos without GPS (uses AVONET distribution data)
preen scan --country CN

# Regional filter using eBird species lists (more curated, supports subnational)
preen scan --region US-CA

# Scan a Shanghai photo library with English-only captions
preen scan --region CN-31 --caption-format "{en}" --keyword-format "{en} {latin}"

# Scan UK photos with Latin names, slash-separated
preen scan --country GB --caption-format "{en} ({latin})" --caption-separator " / "

# Stricter threshold when no regional filter matches (default: 90%)
preen scan --global-threshold 95

# Rescan unidentified birds with a lower global threshold
# Only re-processes photos where birds were detected but not identified
preen scan --threshold 60 --global-threshold 85

# Check progress
preen status

# Reset checkpoint (auto-creates backup)
preen reset

# Restore checkpoint from latest backup
preen restore

Regional species filtering

When photos have GPS, preen automatically filters species using a two-level fallback: AVONET 1×1° grid → country-level eBird list → global. For photos without GPS, use --country or --region:

  • --country XX — queries AVONET distribution data using a bounding box. Covers 49 countries including CH, HK, TW, NP where eBird lists aren't bundled.
  • --region XX or --region XX-YY — uses curated offline eBird species lists. Supports 51 countries + 92 subnational regions (all US states, CN provinces, AU states). Falls back to country-level if subnational file not found.

Caption and keyword format

The --caption-format flag controls how each species appears in the photo description. The --keyword-format flag controls which fields become individual keywords (space-delimited). Available placeholders:

Placeholder Example
{cn} 白鹭
{cn_trad} 白鷺
{en} Little Egret
{latin} Egretta garzetta
{pinyin} bailu

Tuning --workers

The --workers flag controls how many iCloud photos are downloaded in parallel (default: 16). The scan output shows a queue indicator like q:12/16 — ready/total. "Ready" means downloaded and waiting for the GPU; "total" is the queue size.

  • If ready often drops to 0, downloads can't keep up — increase workers
  • If queue is often full (e.g. q:16/16), GPU is the bottleneck — check for other GPU-intensive processes
  • If you have plenty of RAM (each queued image uses ~50-100MB), 32 workers is safe
  • For sequential processing (most reliable), use --workers 1

Credits

  • OSEA bird classification model (10,964 species) by Sun Jiao
  • Bird identification logic (OSEA classifier, AVONET geographic filtering, eBird species data) extracted from SuperPicky
  • YOLO11 segmentation model by Ultralytics
  • Photos library access via PhotoKit through PyObjC

Metadata

Release files for birdpreen 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for birdpreen 0.5.1
File Size Uploaded Provenance Actions
birdpreen-0.5.1.tar.gz 31.3 MB Without provenance Details for birdpreen-0.5.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for birdpreen 0.5.1
File Interpreter ABI Platform Actions
birdpreen-0.5.1-py3-none-any.whl Python 3 none any Details for birdpreen-0.5.1-py3-none-any.whl

Total release size: 62.8 MB

Release files / birdpreen-0.5.1.tar.gz

Download URL birdpreen-0.5.1.tar.gz
Size 31.3 MB
Tags Source
SHA-256 checksum
How to use checksums
a521c485060644d00c8f2f6170b978599cd1c005ec5b9acb446dbd382b69324c
BLAKE2b-256 checksum
How to use checksums
511d0a11c6062a3a1961e7ba024837c046fd4a1d1a967819f2904b1f3be199ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release files / birdpreen-0.5.1-py3-none-any.whl

Download URL birdpreen-0.5.1-py3-none-any.whl
Size 31.5 MB
Tags Python 3
SHA-256 checksum
How to use checksums
24976f399bad9e6f3b505dea1ba0c396899222ea89f3217659a0e023d4e7b05c
BLAKE2b-256 checksum
How to use checksums
be68fafcc19a0bbd932cb083a93e333c419f3280d5e84ba6b9a435aed2897433
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Security for birdpreen 0.5.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page