Skip to content

User-configurable model directory - #987

Open
Josef-Haupt wants to merge 1 commit into
mainfrom
model-directory
Open

User-configurable model directory#987
Josef-Haupt wants to merge 1 commit into
mainfrom
model-directory

Conversation

@Josef-Haupt

Copy link
Copy Markdown
Member

Summary

The birdnet library resolves its model directory from BIRDNET_APP_DATA once, at import time. settings.apply_model_directory() now runs at package import — before anything can import birdnet — and decides the directory for every entry point (GUI, CLIs, frozen, source, Docker):

  1. An already-set BIRDNET_APP_DATA wins, and fails fast with a clear message when the path is unusable — automation (CI, field deployments, Docker) wants determinism, not fallbacks.
  2. The directory picked in the GUI's new settings-tab field (persisted in gui-settings.json) applies in any run mode. If it is unavailable at startup — the classic case: the data drive isn't plugged in — the default is used for the session and the GUI shows a warning instead of crashing inside import birdnet.
  3. Frozen app default: %LOCALAPPDATA%\BirdNET-Analyzer-GUI\models. Models are a multi-GB re-downloadable cache and must not sync with domain roaming profiles; the small settings/state/logs stay in Roaming. From source or Docker nothing changes: the library's own default stands, so pip installs, CI caches and the baked Docker image keep their existing model stores.

Picking a directory probes it with a real test write (Windows os.access lies about ACLs): unusable → rejected; read-only but populated → accepted with a warning, since a pre-seeded read-only field setup is valid (analysis works, downloads don't); under 2 GB free → a warning that a first model download may not fit.

Nine new localization keys across all 11 languages. The PyInstaller runtime hook in the build repo shrinks to GUI_VERSION only (companion change there).

Verification

  • Full suite: 634 passed, 1 skipped. New tests/test_model_directory.py covers the precedence (env > setting > frozen default > library default), the fail-fast env case, the fallback warning, and the probe verdicts; a subprocess test proves the resolver runs at package import (verified to fail when the __init__ call is removed).
  • GUI tests pass in CI's environment (no pywebview/plotly).

Note: merges independently of #981, but both touch gui/utils.py (open_window) — whichever goes second may need a trivial conflict resolution.

🤖 Generated with Claude Code

…cal AppData

The birdnet library resolves its model directory from BIRDNET_APP_DATA once,
at import time. settings.apply_model_directory() now runs at package import -
before anything can import birdnet - and decides it for every entry point:

1. An already-set BIRDNET_APP_DATA wins and fails fast when unusable
   (automation wants determinism, not fallbacks).
2. The directory picked in the GUI's settings tab (gui-settings.json) is
   applied in any run mode; when it is unavailable at startup (e.g. an
   unplugged data drive) the default is used for the session and the GUI
   shows a warning.
3. Otherwise the frozen app defaults to %LOCALAPPDATA%\BirdNET-Analyzer-GUI\
   models - models are a multi-GB re-downloadable cache that must not sync
   with domain roaming profiles, unlike the small settings/state/logs in
   Roaming. From source or Docker the library's own default stands, so pip
   installs, CI caches and the baked Docker image keep their model stores.

The settings tab gets the directory field with select/reset buttons. A picked
directory is probed with a real test write: unusable ones are rejected,
read-only but populated ones are accepted with a warning (a pre-seeded field
setup is valid - analysis works, downloads don't), and under 2 GB free space
a warning notes that a first model download may not fit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 24, 2026 14:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants