Skip to content

Download progress - #984

Merged
Josef-Haupt merged 8 commits into
mainfrom
download-progress
Aug 17, 2026
Merged

Download progress#984
Josef-Haupt merged 8 commits into
mainfrom
download-progress

Conversation

@Josef-Haupt

Copy link
Copy Markdown
Member

No description provided.

Copilot AI lite review requested due to automatic review settings August 17, 2026 12:56
Josef-Haupt and others added 7 commits August 17, 2026 14:59
Models are fetched on first use inside birdnet.load; the library's tqdm bar
goes to stderr, which the frozen GUI diverts to the log file, so a first-run
download of several hundred MB looked like a hang. gui.utils.download_progress
registers birdnet's scoped download callback for the duration of an analysis:
with a gr.Progress it drives the bar (fraction plus MB counts, unknown sizes
keep the bar visible), without one it announces the download as a toast, and
a retry is surfaced as a warning. UI failures inside the callback are logged,
never raised - an exception escaping it aborts the download in the library.
The CLI keeps the library's tqdm bar unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
They import gui.utils, which imports pywebview at module level; the
gui-tests extra in CI has no pywebview, so the module stubs it before the
import, like test_startup_imports does. Also keeps test_settings.py free of
unrelated additions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The library's scoped callback registration is a plain set/restore, so two
overlapping GUI events (single-file and multi-file analysis run as separate
gradio events) could misroute updates and leave a stale callback registered
after both finished. The adapter now keeps one sink per handler thread and
registers a single dispatcher with the library while any sink is active;
the library invokes the callback synchronously on the thread that called
birdnet.load, so the thread id identifies the event. Covered by a test that
interleaves two events. The species tab, whose first run downloads the geo
model, is wrapped as well; the train, embeddings and search tabs still show
nothing during a first-run download.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A preset or params file can set the slider without changing the model, so
the model-change handler never resets it. The slider's own change handler
now returns it to 1.0 whenever the selected model does not take a
sensitivity, so the disabled slider always shows the value the analysis uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

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.

Pull request overview

This PR improves first-run UX and model-compatibility handling by surfacing BirdNET model download progress in the GUI and by making “sensitivity” explicitly a BirdNET 2.4/custom-classifier-only control across CLI, core analysis, and GUI.

Changes:

  • Add a GUI-scoped download progress dispatcher that routes birdnet library download events to Gradio progress bars/toasts.
  • Introduce supports_sensitivity / effective_sensitivity to drop sensitivity for BirdNET 3.x/Perch (with warnings) and disable the GUI sensitivity slider accordingly.
  • Update docs, localization strings, and add tests covering both download progress routing and sensitivity slider behavior.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
birdnet_analyzer/gui/utils.py Adds download progress routing + sensitivity-slider enable/disable & restore logic.
birdnet_analyzer/gui/analysis.py Wraps analysis run in download_progress(...) so model downloads show progress during analysis.
birdnet_analyzer/gui/species.py Wraps species list generation in download_progress() for download visibility.
birdnet_analyzer/model_utils.py Adds sensitivity support helpers and enforces an effective sensitivity in inference.
birdnet_analyzer/analyze/core.py Normalizes sensitivity early so params/resume metadata reflect the effective value.
birdnet_analyzer/cli.py Updates --sensitivity help text to reflect BirdNET 3.0/Perch behavior.
birdnet_analyzer/lang/en.json Adds localized strings for “downloading model” and “download retrying”.
birdnet_analyzer/lang/de.json Same localization additions (German).
birdnet_analyzer/lang/fi.json Same localization additions (Finnish).
birdnet_analyzer/lang/fr.json Same localization additions (French).
birdnet_analyzer/lang/id.json Same localization additions (Indonesian).
birdnet_analyzer/lang/pt-br.json Same localization additions (Portuguese - Brazil).
birdnet_analyzer/lang/ru.json Same localization additions (Russian).
birdnet_analyzer/lang/se.json Same localization additions (Northern Sami).
birdnet_analyzer/lang/tlh.json Same localization additions (Klingon).
birdnet_analyzer/lang/zh_CN.json Same localization additions (Simplified Chinese).
birdnet_analyzer/lang/zh_TW.json Same localization additions (Traditional Chinese).
docs/breaking-changes.rst Documents sensitivity being ignored for BirdNET 3.0 and GUI slider behavior.
pyproject.toml Switches birdnet dependency to a direct GitHub tarball reference.
tests/test_model_utils.py Adds unit tests for sensitivity support and inference sensitivity dropping.
tests/gui/test_sensitivity_slider.py Adds GUI test verifying slider disable/restore behavior across model choices.
tests/gui/test_download_progress.py Adds GUI test verifying birdnet download progress callback routing and concurrency behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

import warnings
from collections.abc import Callable
from contextlib import suppress
from contextlib import contextmanager, suppress

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed on the diagnosis, but this is pre-existing and out of scope here: gui.utils has imported webview at module level since long before this PR, and every test that reaches it stubs sys.modules['webview'] first (documented in AGENTS.md; both new test modules in this PR do so). Making gui.utils importable without pywebview is a real improvement (open_window, _WINDOW typing, the folder/file dialogs) but a separate refactor — filing it as a follow-up rather than widening this PR.

Comment on lines +222 to +238
if update.status == "started" and progress is None:
gr.Info(label)
elif update.status == "progress" and progress is not None:
if update.bytes_total:
done = _format_bytes(update.bytes_done)
total = _format_bytes(update.bytes_total)
progress(
min(update.bytes_done / update.bytes_total, 1.0),
desc=f"{label} ({done} / {total})",
)
else:
progress(0.0, desc=f"{label} ({_format_bytes(update.bytes_done)})")
elif update.status == "retrying":
gr.Warning(
f"{loc.localize('progress-download-retrying')}: {name} - {update.error}"
)
# "failed": the library raises right after; the operation reports it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in 3629d8e: finished now drives the bar to 1.0 (progress events are throttled, so the last one can sit below 100%). Test asserts the final call is 1.0.

Progress events are throttled, so the last one can sit below 100%.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Josef-Haupt
Josef-Haupt merged commit b2022f1 into main Aug 17, 2026
10 checks passed
@Josef-Haupt
Josef-Haupt deleted the download-progress branch August 17, 2026 13:23
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