github tphakala/birdnet-go nightly-20260418
Nightly Build nightly-20260418

4 hours ago

This nightly is a stabilization release focused on cutting memory use back to pre-nightly-20260414 levels. Steady-state RAM on a typical single-source deployment drops by roughly half, thanks to reclaiming the job-queue archive, pooling hot-path audio buffers, and releasing timezone polygon data after lookup. It also brings audio source labels to the detection UI, an in-feed quick-review action, a behavioural fix to /api/v2/search that consumers of that endpoint should read, and a batch of search, basepath, notification, and guest-dashboard fixes.

New Features

Audio Source Labels in the Detection UI

Detection views now display the human-readable source name (e.g. "Garden feeder") instead of a raw RTSP URL or device ID. The desktop detections table gains a new Source column at lg and above, mobile detection cards show the source name inline after the timestamp, and the Search view recognises a new source: filter that maps to the existing location API parameter. The API's DetectionResponse.source field is now a structured SourceInfo object (id, type, displayName) instead of a plain string, aligning with the realtime/SSE path that already used the structured form. Detections whose source cannot be resolved from the live AudioSource table now fall back to the configured source name in settings instead of showing an ID (#1681 by @jasonmadigan, #2757, addresses #1494).

Quick Review from the Action Menu

Detection cards and list rows now expose Correct / Incorrect items at the top of the action menu, so verification status can be set without opening the detection. The dashboard CardActionMenu and list ActionMenu have been merged into a single component with a variant prop, and a / badge is shown next to the matching item when the detection is already reviewed. The items are hidden when the detection is locked or the user lacks review permission (#2809, closes #2712).

Memory & Performance

  • Drop completed-job retention in the action queue - the archived-jobs slice was pinning roughly 45-100 SaveAudioAction PCM buffers at about 2.88 MB each. Completed and failed jobs are now discarded on the next cleanup tick, reclaiming about 130 MB of steady-state heap on a single-source deployment (#2787).
  • Release the timezone finder after first resolve - tzf polygon data (~32 MB) was kept for the lifetime of the process despite only being needed once at startup. It's now freed after the initial timezone lookup (#2803).
  • Pool AudioCore hot-path allocations through buffer.Manager - the router, capture path, HLS/stream frame buffers, and AnalysisBuffer.Read windows now draw from pooled, refcounted buffers instead of allocating per frame. Reduces GC pressure and per-source memory churn (#2788, #2793, #2794, #2796).
  • Sound-level monitoring no longer runs when disabled - the sound-level pipeline was always running and consuming CPU and memory even with the feature switched off in settings. It's now skipped entirely when disabled, and starts or stops correctly on hot-reload of the toggle (#2802).

Behavioural Change (API consumers)

  • /api/v2/search now returns "correct" instead of "verified" in the verified response field for reviewed detections, matching the vocabulary already used everywhere else in the API (including /api/v2/detections). External scripts that match the literal string "verified" need to update to "correct" (alongside the existing "false_positive" and "unverified"). The request-side verifiedStatus filter parameter on the same endpoint has changed in the same direction: pass "correct" to select reviewed detections. The previously documented "verified" value was never actually accepted by the validator, so no working client could have been relying on it (#2801, fixes #2769).
  • DetectionResponse.source is now an object, not a string - see the Audio Source Labels section above for the new shape. The old string form was only used in a handful of REST paths; SSE/realtime consumers already received the structured form.

Bug Fixes

Search & Detections

  • Search view no longer shows "Unverified" for already-reviewed detections - both the response field and the filter dropdown now speak the canonical "correct" vocabulary (#2801).
  • Search by common name works against any configured display locale - common-to-scientific resolution now happens server-side, and /api/v2/detections search was extended to match the same way. The earlier client-side shim has been removed (#2805, #2808, supersedes #2782).
  • Sort-dropdown race on rapid search resubmits - the last submitted sort now wins instead of whichever response arrived first (#2807).
  • Taxonomy synonyms UI copy clarified to make clear synonyms affect image lookups only, not detection matching (#2800).

Audio & Streaming

  • HLS frame corruption under contention - hlsConsumer.Write now copies frame data before sending on the channel, preventing readers from racing on the caller's buffer (#2792).
  • Extended Capture clip tails truncated - SaveAudioAction now defers its capture-buffer read until the tail window is actually available, fixing "Failed to read capture buffer for audio export" under Extended Capture (#2798, fixes #2789).

Dashboard, Wizard & Authentication

  • Guest dashboard restored when authentication is enabled - dashboard settings can now be read unauthenticated so the public dashboard renders again without forcing a login (#2763).
  • Notifications and quiet-hours reachable on the guest dashboard - the guest path now unlocks the notification feed and the quiet-hours read endpoints (#2775).
  • Sidebar locale choice preserved on unrelated saves - changing an unrelated setting no longer reverted the UI language (#2764).
  • Wizard now persists UI locale to the backend - the language picked during first-run setup is written through, not just held in browser state (#2765).
  • Defensive guards for missing source.models and duplicate timeline keys - prevents UI crashes on older data or mixed-source configurations (#2761).

Basepath & Reverse Proxy

  • Header-only basepath stripped for proxied callback routes - fixes auth callbacks and similar routes behind reverse proxies that inject X-Forwarded-Prefix (#2780, fixes #2778).
  • Dashboard anchors, RawPath sync, and settings hot-reload race under basepath - several basepath-related inconsistencies ironed out (#2785).

Notifications & Webhooks

  • Unread count no longer includes toast-flagged notifications - InMemoryStore.GetUnreadCount was blindly incrementing on save; it now walks the same filter path List uses, so the counter matches the list endpoint. A typed Count(filter) method replaces the guest pagination loop (#2777).
  • CSRF token now sent on audio POST + opt-out auto-add for synonym form (#2781, fixes #2768, #2767).

Database

  • Reconcile stale unique indexes before AutoMigrate - prevents migration failures when an older schema left a unique index around that conflicts with the new column shape (#2804).

Telemetry & Reliability

  • Suppress context.Canceled noise for database operations - cancellation on shutdown no longer reports as a Sentry error (#2772).
  • Silence MQTT disconnect floods and floor the jobqueue stop timeout (#2774).
  • Circuit breaker for BirdWeather uploads + exponential backoff for suppressor reminders - transient upstream failures no longer cascade into notification storms (#2773).
  • Suppress capture-buffer warmup noise + tag Sentry events with process uptime - cleaner startup logs and easier to tell cold-start events apart from steady-state ones (#2762).

Internationalization

  • Dutch compound nouns corrected in main settings labels (commit d6c76ca).
  • Source column localized across all supported locales (#1681 by @jasonmadigan).

Don't miss a new birdnet-go release

NewReleases is sending notifications on new releases.