Skip to content

Releases: tphakala/birdnet-go

BirdNET-Go 20261014

Choose a tag to compare

@tphakala tphakala released this 14 Oct 05:43
9642f74

This is the first regular release since 20260823, and a large one. You can now choose freely which detection models run, for example Perch v2 or BirdNET v3.0 on its own, or several side by side, and a long-standing bug that made the false positive filter discard valid detections is fixed, with automatic protection so the extra analysis cannot overload your device. This is also the first step toward the AGPL-3.0 license, after which BirdNET v2.4 becomes a model you install from the gallery instead of one built into BirdNET-Go. Live audio streaming is now built in and no longer runs FFmpeg, which makes it more reliable and lighter on the system. A new Privacy Guard keeps human speech out of your recordings far more reliably, bat calls can be slowed down so you can actually hear them, bat recordings are stored as FLAC, the setup wizard has been reworked, and you can find your station location by searching for a place. This release also includes every security fix from the 20261010 security release.

Before you upgrade

  • Upgrading from 20260823? Read the 20261010 notes first. All of its security changes are included here, and some need action: if you use the subnet login bypass behind a reverse proxy, list the proxy in security.trustedproxies; outbound integrations no longer use HTTP_PROXY or HTTPS_PROXY; and scripts that call the ntfy server check must use POST.
  • Expect higher CPU use with the false positive filter on. A bug fix makes the filter work as intended, which means more analysis at the stronger settings. See "False Positive Filter Fixed" below; a lower False Positive Filter Strength reduces the load.
  • Plan on staying on this release. It stores dynamic thresholds per species and stamps a version into your config. Older releases (20261010, 20260823) may fail to start on the updated data, so take a backup first if you might want to go back.

New Features

Choose Your Own Detection Models

This is part of the work to move BirdNET-Go to the AGPL-3.0 open source license (#4243). The BirdNET v2.4 model is licensed for non-commercial use only, so it cannot stay built into an AGPL-3.0 program. In a future release BirdNET v2.4 will no longer be embedded in BirdNET-Go and will instead be installed from the model gallery like the other models. In this release it is still built in and works exactly as before.

To get there, BirdNET v2.4 is no longer a required base model. Enable any combination of installed models in any order: a Perch v2 or BirdNET v3.0 station, a bat-only station, or several models side by side. Changes take effect without a restart. A model that fails to load no longer stops BirdNET-Go from starting; the dashboard shows a banner telling you whether no model is installed or one could not load, with a link to fix it. Existing installs keep exactly the models they run today: on first start your config is updated once to list BirdNET v2.4 explicitly, and nothing else changes (#4357, #4368, #4379, #4381, #4385, #4388, #4390, #4392).

False Positive Filter Fixed, With Automatic CPU Protection

The false positive filter confirms a detection by checking that it shows up in several overlapping analysis windows. The False Positive Filter Strength setting (Off, Lenient, Moderate, Balanced, Strict, Maximum) sets how much the windows overlap: a stronger setting means shorter steps between windows and more confirmations. Because of a bug introduced when the audio pipeline was rewritten, the analysis ignored the overlap setting and always moved in fixed 1.5 second steps, while the filter still expected the number of confirmations its strength asked for. At the stronger settings that number could never be reached, so valid detections were quietly thrown away as false positives (#4247, fixes #4096).

The analysis now runs at the step the filter strength calls for, so the filter works as designed. This means you may see noticeably higher CPU use after upgrading if False Positive Filter Strength is set to anything other than Off. At Maximum the analysis step drops from 1.5 seconds to 0.2 seconds, which is up to about 15 times more model runs per audio source and model. With the filter Off, nothing changes. If CPU load is too high, choose a lower False Positive Filter Strength under Settings > Analysis.

To keep a busy system from falling behind, the overlap is now partly dynamic. After each model starts, BirdNET-Go measures how long it takes to analyze audio on your hardware. Models analyze audio one at a time, so BirdNET-Go estimates how much of each second the analysis would be busy across all enabled models and audio sources. If the overlap your filter strength asks for fits within about 75% of that time, it is used unchanged. Only if it does not fit does BirdNET-Go lower the overlap, and only as far as needed to get back under that limit. This is a safety ceiling, not a target: on hardware that keeps up, nothing is reduced. Without this, a Raspberry Pi 4 running two models with a strong filter setting would saturate its CPU, overwrite audio before analyzing it, and stop producing detections. The reduced overlap is used only while needed and is never written to your settings, so it lifts again with fewer models or faster hardware. With the filter Off, overlap is not reduced.

The filter stays active while the overlap is reduced. Each strength setting requires a share of the analysis windows within about 6 seconds to agree (from 20% for Lenient to 70% for Maximum), and that share does not change. A reduced overlap means fewer windows, so the number of confirmations is recalculated from the windows the device actually produces, and some borderline detections may pass. Strict and Maximum always require at least two confirmations. Balanced drops to one only when the device cannot sustain any overlap, which Settings > Analysis reports as a device that cannot keep up. Lenient and Moderate ask for few confirmations to begin with and can drop to one with a smaller reduction. Settings > Analysis always shows the count in effect (#4545).

Settings > Analysis now shows what the filter really does: for each model, how many windows must agree and how often a new window starts. A notice tells you when the overlap has been reduced, and warns when even the smallest overlap is more than the device can handle, suggesting fewer models or audio sources (#4547). Overload warnings in the log are also accurate now: healthy multi-model stations no longer warn, and real audio loss is reported (#4555).

The false positive filter will keep improving in future releases, including new ways of telling real detections from false ones.

Model Health in the Notification Bell

If a model loads but fails on every piece of audio, for example a build that does not suit your hardware, the notification bell, dashboard, status page and health check now say so, naming the model and the cause. The bell also tells you when the model gallery has a better build for your hardware, so you no longer have to open the gallery to find it (#4433, #4435).

Privacy Guard

The privacy filter used to catch speech only when the bird model happened to rank "human" among its top results, which it often did not. Privacy Guard adds a small dedicated speech detector (Silero VAD) that listens for voices on every audio source and discards bird detections that contain speech, so conversations stay out of saved clips. Turn it on with Enable Privacy Guard under Settings > Filters > Privacy Filtering, and tune it with Privacy Guard Threshold (default 0.35). Its activity is shown under System > AI Models (#4181, #4182, #4183, #4185).

Built-In Live Audio Streaming

Live audio on the dashboard is now produced inside BirdNET-Go with a native HLS streamer, so FFmpeg is no longer needed for listening live. The stream is held in memory: no FFmpeg process per listener, no segment files written to disk or SD card, and no RAM disk or volume permissions to set up. Several listeners share one stream. The result is more reliable live streaming that uses fewer resources (#4220, #4222).

Bat Calls You Can Hear

Bat detections get an "Audible bat playback" mode that slows ultrasonic calls down 5x, 10x, 16x or 20x into the human hearing range, in the full audio player and on the detection cards. The original recording is not changed (#3743 by @alexbelgium).

Bat recordings are now stored as FLAC by default: lossless at the full sample rate and much smaller than WAV. A new Ultrasonic Format setting under Settings > Audio lets you keep WAV if you prefer (#4396).

Find Your Station Location by Searching

The Location tab under Settings > General has a "Search for a place" box above the station map. Type a town or address, pick a result, and the pin moves there instead of you zooming and panning from a world view. Searches go to Photon (OpenStreetMap data) and send only what you type, never your coordinates (#4534). A "Use browser location" button fills it in from your browser (#4308 by @sn3p).

Reworked Setup Wizard

The setup wizard now appears on new installs again and is much sturdier. Each step is saved as you go, your sound card and existing streams are kept, stream addresses and the BirdWeather token are checked before you continue, you are asked before leaving setup unfinished, and the whole wizard works with the keyboard and screen readers. It uses the same location map and search as Settings (#4465, #4481, #4483, #4488, #4490, #4491, #4492, #4494, #4495, #4497, #4499, #4525, #4526, #4528, #4529, #4531, #4541, #4544). The BirdWeather token is also checked before saving in Settings (#4502).

Pirate Weather

Pirate Weather is now available as a weather provider (#4360 by @turmacar).

Toward FFmpeg-Free Audio (Opt-In Previews)

Two more steps toward running BirdNET-Go without FFmpeg are ready for testing. Setting BIRDNET_STREAM_INGEST=native captures RTSP streams in BirdNET-Go itself, with AAC, Opus, MP3 and PCM audio and per-...

Read more

BirdNET-Go 20261010

Choose a tag to compare

@tphakala tphakala released this 10 Oct 10:48

This is a security release. It is built from release 20260823 with only security fixes and the dependency updates they need applied on top, so it carries none of the new features or other changes merged since 20260823; those arrive in the next regular release. Every installation should update. If you run subnet bypass behind a reverse proxy, read "Before you upgrade" first.

Before you upgrade

  • Subnet bypass behind a reverse proxy needs the proxy listed. The allowed-subnet login bypass (security.allowsubnetbypass) now honors a forwarded client address only when the request comes from a proxy listed in security.trustedproxies. If you reach BirdNET-Go through nginx, Caddy, Traefik, Home Assistant ingress, Tailscale Serve or a similar proxy and rely on the bypass, add the address the proxy connects from (for a proxy on the same host, 127.0.0.1 over IPv4 or ::1 over IPv6) to security.trustedproxies. The proxy must append X-Forwarded-For or overwrite X-Real-IP. List only the proxy's own address, not a range that also contains clients: a client inside a listed range is trusted as a proxy and can name any address. Clients that connect directly on your LAN are not affected. When forwarded headers keep the bypass from applying, the log says which peer to list.
  • Outbound integrations no longer use an environment proxy. Weather fetches, webhook notifications, the weather and eBird connection tests and the ntfy server check now go through a client that checks every destination address before connecting. These requests ignore HTTP_PROXY and HTTPS_PROXY, because a proxy would resolve the destination itself and bypass the check. Deployments that can only reach the internet through an egress proxy will see these integrations fail.
  • The ntfy server check is now a POST. GET /api/v2/notifications/check-ntfy-server?host= was replaced by POST /api/v2/notifications/check-ntfy-server with a JSON body {"host": "..."} and CSRF protection. The web UI is updated; external scripts that call the old GET need the same change.
  • Do not switch to this release from a development build. If you have run a :dev image or a build from the main branch, stay on it until the next regular release. Those builds change the dynamic threshold tables in a way this release cannot read, and it may fail to start.

Security

  • Subnet bypass decided on a verified client address. The allowed-subnet bypass and the automatic local-network check trusted CF-Connecting-IP, X-Forwarded-For and X-Real-IP from any loopback, link-local or private peer. A client on the same network or container network, or anyone reaching the app through a proxy that passed those headers through, could claim an address inside the bypass subnet and skip login. Forwarded headers now count only from a listed proxy, and every client-IP header it sends must name the same client (GHSA-wfpc-rhcf-754r). Reported by @Hama1cco.
  • Range filter rebuild and test require authentication. POST /api/v2/range/rebuild and POST /api/v2/range/species/test were reachable without login when authentication was configured and Private Mode was off (GHSA-8668-57p7-rjc9). Reported by @alex131125.
  • Recent detections limit capped. GET /api/v2/detections/recent accepted any limit and loaded that many detections into memory; it is now capped at 1000 (GHSA-g6wh-4rqg-w7qw). Reported by @alex131125.
  • Stream test host checks resolve names and reject numeric forms. The stream test endpoints blocked loopback and metadata destinations only for a few literal names. Decimal, hex, octal and short IPv4 forms, localhost. and DNS names resolving to blocked addresses are now rejected before probing (GHSA-2vxv-jv48-g3w7). Reported by @Yanyan-dd.
  • Webhook notifications guarded against SSRF. Webhook requests can no longer reach link-local or cloud metadata addresses (#4191, GHSA-85p4-7rfw-572f). Reported by @tonghuaroot.
  • Outbound probes guarded against SSRF, ntfy check protected by CSRF. Weather fetches, the weather and eBird connection tests and the ntfy server check now use the same guard (#4302, GHSA-hj22-g96h-fwvx). Reported by @tonghuaroot.
  • Dismissing the onboarding wizard requires access when authentication is configured (#4469).
  • Toolchain and dependencies. Built with Go 1.26.9, which carries the standard library security fixes released since 1.26.7, with golang.org/x/net v0.60.0, golang.org/x/crypto v0.57.0 and google.golang.org/grpc v1.83.2. Echo is updated to v4.16.0 (#4514).

Bug Fixes

  • No more crash when an SSE client disconnects. Server-sent event and streaming handlers no longer use a request context after Echo recycles it, which could crash the server or corrupt another request's response (#4293).
  • BirdWeather uploads keep their HTTP/2 health checks after the x/net update, now through the standard library configuration (#4401).

Notes

  • The web UI's map library (maplibre-gl 5.x) is listed by scanners under GHSA-jrc7-96c5-q579. BirdNET-Go never passes untrusted HTML to the map, so the issue cannot be triggered here; the next regular release ships the fixed 6.x version.

🛡️ VirusTotal Results:

BirdNET-Go 20260823

Choose a tag to compare

@tphakala tphakala released this 23 Aug 19:03

This release is built around a reworked model gallery. It now recommends the best model for your specific hardware, and, when your location resolves to a supported region, recommends a region-specific model that keeps only the species that actually occur there. On a Raspberry Pi class device those regional models cut peak memory use by roughly two thirds and inference latency by 15-30% while staying numerically identical on the species they keep. This release also adds the BirdNET v3.0 acoustic classifier as a developer preview, a new "Infrequent" species tracking category, pure-Go Opus clip export as the default (no FFmpeg required), and optional FFmpeg-free HLS live streaming. Several security fixes are included, along with a large batch of dashboard, analytics, and audio bug fixes.

New Features

Region-Aware, Hardware-Aware Model Gallery

The model gallery has been rebuilt around choosing the right model for your machine and your location. It detects your host hardware capabilities (CPU architecture, available RAM, Intel or NVIDIA GPU, OpenVINO) and recommends the best-fitting model variant, preselecting it in the install dialog with a short explanation of why, while always allowing a manual override. Variants are labelled in plain language (AMD64 CPU, ARM64 CPU, GPU (Intel), GPU (NVIDIA), Built-in) instead of raw precision codes, with a compatibility badge that explains, rather than silently hides, any build that cannot run on your hardware.

When your configured coordinates resolve to a supported region, the gallery recommends a region-specific model that includes only the species found in that region. These regional slices cut peak memory use by around 67% and latency by 15-30% on a Pi-class device while producing identical scores on the species they keep. You can also pick a region manually from coverage-map cards, and the gallery notifies you when your coordinates change enough that a different regional model would fit better. Installing, switching, uninstalling, and reinstalling a variant is handled safely with a download-before-delete lifecycle, so the running model is never removed until its replacement is verified, and a disk-space preflight runs before any download. Model downloads gain automatic failover to a Hugging Face mirror when the primary source is unreachable (#4034, #4037, #4076, #4077, #4078, #4079, #4081, #4099, #4111, #4123, #4124, #4125, #4126, #4127, #4129, #4132, #4133, #4134, #4141, #4153, #4158, #4160).

BirdNET v3.0 Acoustic Classifier (Developer Preview)

This release adds a working inference path for the BirdNET v3.0 acoustic classifier (EfficientNetV2-S backbone, 11,560 species, 32 kHz / 5 s window). It is a developer preview: BirdNET v2.4 remains the default, and v3.0 is clearly flagged as not the final GA release in the gallery. It is provided for testing and early evaluation, not for production use. Regional v3.0 variants are available in the catalog alongside the global model (#4028, #4126, #4132, #4160).

Infrequent Species Tracking

A new "Infrequent" species-novelty category joins the existing lifetime, new-this-year, and new-this-season highlights. It flags a species the moment it is detected again after an absence longer than a configurable threshold (default 14 days, absenceDays), and surfaces it the same way the other categories do: a dashboard badge, a highlight card entry, a dedicated alert event, and a notification template variable (#3791 by @alexbelgium).

Native Opus Clip Export by Default

This is part of a longer-term effort to make BirdNET-Go independent of FFmpeg by encoding advanced audio codecs in native Go. The pure-Go Opus encoder is now the default for .opus clip export, joining the native FLAC and WAV paths, so FFmpeg is no longer required to export those formats. The old opt-in BIRDNET_OPUS_ENCODER environment variable is gone; Opus now works out of the box, with FFmpeg kept only as a fallback for rare unsupported clip shapes. Native AAC and MP3 encoders, and fully Go-native audio streaming, are planned to follow (#4163, #4164).

FFmpeg-Free HLS Live Streaming (Opt-In)

As part of the same move toward FFmpeg independence, live stream playback can now run through a pure-Go, in-memory HLS muxer instead of FFmpeg, enabled with BIRDNET_HLS_ENCODER. The FFmpeg-based HLS path remains the default and is unchanged (#4004, #4012).

Per-Stream RTSP Media Mode

RTSP sources gain a per-stream media mode, defaulting to full-stream, giving finer control over how each stream is captured and served (#3963).

Security

  • CSRF token now enforced regardless of Sec-Fetch-Site. State-changing API requests are validated against the CSRF token even when the browser sends a same-origin Sec-Fetch-Site header, closing a gap where that header could be relied upon in place of the token (GHSA-9fhj-f35q-w532). Reported by @sec-reex (#4142).
  • Detection media endpoints require authentication in Private Mode. Audio and spectrogram media endpoints for detections now require authentication when Private Mode is enabled, so clips are not reachable without a session (GHSA-c7jx-552f-94hh). Reported by @ejhnsn (#4083).
  • pprof moved off the unauthenticated telemetry listener. The profiling endpoints are no longer exposed on the unauthenticated telemetry port, and block and mutex sampling are decoupled from debug: true so enabling debug logging does not silently start profiling (#4031, #4033).
  • Widget editor hidden from unauthenticated guests. The dashboard widget editor is no longer shown to visitors who are not logged in (#4113).
  • Blocked-field map enforced on settings PATCH. PATCH /api/v2/settings/:section now enforces the same blocked-field protections as the full settings update, so protected fields cannot be changed through the section endpoint (#4036).

Bug Fixes

Models & Detection

  • OpenVINO backend compiled into the Linux release binaries. The shipped Linux binaries now include the OpenVINO backend, so OpenVINO acceleration works without a custom build (#3961).
  • Species rarity lookup uses the active geomodel taxonomy. Rarity now resolves against the taxonomy of the active geomodel instead of a mismatched one (#3978, fixes #3973).
  • Dynamic thresholds tracked per species, not per model. Adaptive confidence thresholds are now keyed per species so one species no longer inherits another's threshold state (#4173).
  • Legacy Intel OpenVINO offload devices supported. Older Intel OpenVINO offload devices are now recognized (#4066 by @xitation).
  • Partial common-name search matches. Species search now matches partial common names instead of requiring a near-exact string (#4040 by @ejhnsn).

Dashboard & Analytics

  • Analytics species summary no longer aborts on NULL confidence. A species group whose detections all have NULL confidence no longer fails the scan and aborts the entire species summary (#4170).
  • False positives excluded from new-species detections. New-species highlights no longer count detections marked as false positives (#3981 by @Kerakis).
  • Patterns charts honor the species selection. All patterns charts now respect the selected species (#3915 by @Kerakis).
  • Time-of-day pattern covers the whole selected range. The time-of-day pattern chart now reflects the entire selected date range (#3969 by @Kerakis).
  • Species colors stay consistent across patterns charts. Species keep the same color across the patterns charts (#3910 by @Kerakis).
  • Analytics charts stop clipping labels and series. Chart labels and series near the plot edges are no longer cut off (#3911 by @Kerakis).
  • Hour axis no longer stretches past the last hour. (#3970 by @Kerakis)
  • Species selector fixes. The species selector now shows its checked state correctly (#3909 by @Kerakis), hides the toggle where species filtering does not apply (#3912 by @Kerakis), and no longer overlaps charts when the maximum number of species is selected (#3982 by @Kerakis).
  • Species thumbnails shown in the summary table by default. (#4047)
  • Custom config and manual inclusion badges resolve correctly. (#3980, fixes #3974)

Media & Images

  • Species image caching corrected. The image provider no longer caches the wrong species image or the wrong licence (#4048), sends a Wikimedia-compliant User-Agent and stops retrying past a refusal (#4045), and fetches species images off the request path so page loads are not blocked (#4046).
  • Download detection audio by ID. Detection audio downloads now resolve by detection ID (#4092 by @ejhnsn).
  • Request timeout errors preserved. Media request timeouts are no longer masked by a generic error (#4093 by @w3lld1).
  • Misleading UTC marker removed from downloaded filenames. (#4030 by @ejhnsn)

Audio & Streaming

  • RTSP restart backoff resets after stable recovery. A stream that recovers and runs stably no longer keeps a long restart backoff from an earlier failure (#4167).
  • Flapping RTSP liveness notifications coalesced. Rapidly flapping RTSP source liveness changes no longer spam notifications (#3966).
  • Corrupt BirdWeather soundscape FLAC repaired. (#3967)
  • MQTT reconnects after a failed initial connection. MQTT now retries the connection when the first attempt fails instead of giving up (#4065 by @Kerakis).

Database & Storage

  • v2 datastore promoted to primary once the legacy tail is reconciled. (#4169)
  • SQLite falls back to the default path when the configured path is blank. (#3987 by @dk1)
  • db-doctor recognizes precipitation columns. The database doctor no longer flags the precipitation columns on hourly_weathers as unexpected (#4053).
  • Retention cleanup is observable and hot-reloadable. Disk retention cleanup now reports what it freed and takes configuration changes without a restart (#4168).

Settings & Config

  • PUT settings merges instead of zeroing omitted fields. A full settings...
Read more

BirdNET-Go 20260716

Choose a tag to compare

@tphakala tphakala released this 16 Jul 19:52
e783b54

This is primarily a bug-fix release. It restores the range filter for arm64 (Raspberry Pi) Docker users whose species list had blown open to thousands of out-of-region species, closes an authentication middleware gap where a malformed Authorization header could let a protected handler run anyway, and fixes two database-migration edge cases that could delete a migrated database or crash-loop a fully migrated install on startup. It also adds cross-host install migration over SSH, stops the media API from showing broken audio/spectrogram players while an extended-capture clip is still being written, and corrects CPU temperature reporting on the Health page.

New Features

Cross-Host Install Migration over SSH

Moving BirdNET-Go to a new machine (for example a Raspberry Pi 4 to a Pi 5) no longer means copying files by hand and redoing the service setup. Run install.sh --migrate (or --migrate-from <host> to name the source non-interactively) on the new host and it pulls your config, SQLite database, and audio clips from the old host over SSH, then reconfigures the systemd service for the new machine while preserving your web port, TLS, metrics, and timezone settings. It verifies the old service is stopped, checks free disk space before the transfer, runs a SQLite integrity check, and never overwrites existing data on the target (any existing install is moved aside to a timestamped backup). apt + systemd Linux only; no macOS or Windows (#3934).

Security

  • Auth middleware now fails closed on bad credentials. A request to an auth-protected API route carrying a malformed Authorization header or an invalid token wrote a 401 but then still ran the route handler, because the abort was not propagated. The middleware now terminates the chain so protected handlers never execute after an authentication failure (#3930, fixes #3929).

Bug Fixes

Detection & Classification

  • Range filter restored on arm64 / Raspberry Pi Docker. On ONNX-only arm64 images the default rangefilter.model: latest silently failed to load, so the active species list jumped from around 100 for your location to 6000+ and out-of-range species started showing up. The latest default now auto-selects the shipped ONNX range-filter model, restoring the same regional filtering as before with no download. If you had gotten used to the unfiltered results, out-of-range species will be suppressed again (#3933, fixes #3932).

Audio & Streaming

  • FFmpeg RTSP timeouts now trigger the audio-only fallback. An RTSP source whose FFmpeg connection timed out without ever delivering data was treated as a clean end-of-stream, so the audio-only capture fallback never engaged and the stream went silent. That timeout is now detected and recorded so the fallback kicks in correctly (#3937, fixes #3936).

Media

  • Audio and spectrogram players no longer break for extended-capture clips. Detections that use Extended Capture emit their database entry and live update before the audio clip finishes writing, so the media API briefly raced the file: audio and spectrogram requests returned 404, the detections list showed a broken player until a manual reload, and the transient errors spammed the logs. Clips that are still within their capture window now return 503 with a Retry-After and the player waits them out on its own, while genuinely missing clips still return 404 (#3946).

System & Health

  • Correct CPU sensor used for the critical-temperature check. The Overview and Health pages could raise a false "Critical Temperature" alert when a non-CPU sensor read hotter than the CPU. Both pages now read the CPU thermal sensor specifically (#3941, fixes #3940).
  • Health page shows CPU temperature in the configured unit. The System > Health page always printed the CPU temperature in Celsius even when the dashboard was set to Fahrenheit; it now uses the configured unit, read per request so a unit change takes effect without a restart. As a side effect of consolidating the thermal readers, the cpu.temperature metric now reports the hottest valid zone, so on multi-zone or multi-socket systems it may read slightly higher after upgrade (#3945).

Database

  • Migration state detected correctly on startup. A leftover marker from an old bug (PR #2165) could make a legacy database look like a fully migrated v2 database, which deleted the real migrated sidecar and dropped the app back to legacy mode. That misdetection is fixed, and the detection now discriminates by row count so a completed-v2 install that still carries empty legacy tables is recognized as v2 instead of crash-looping on startup, while a genuinely legacy database with unmigrated data is still protected (#3926, #3947, fixes #3924).

🛡️ VirusTotal Results:

BirdNET-Go 20260713

Choose a tag to compare

@tphakala tphakala released this 13 Jul 17:04
2634943

This release makes Intel iGPU acceleration usable end to end: the OpenVINO backend can now offload BirdNET and Perch inference onto an Intel integrated GPU, and the container image and installer wire the GPU render device through automatically. It also promotes the built-in Go FLAC encoder to the default and drops the FFmpeg FLAC path, closes a token leak in the HTTP access logs, and fixes RTSP sources that stopped capturing when a camera rejected an audio-only handshake.

New Features

Intel iGPU Acceleration (OpenVINO)

The OpenVINO backend added in the previous release can now offload inference onto an Intel integrated GPU, not just the CPU. On amd64 hosts with a supported Intel iGPU the container installs the Intel GPU runtime and gets access to the render device, and both the container image and install.sh pass the host /dev/dri device through so OpenVINO can see the GPU out of the box (#3888 by @xconverge, #3907).

Which models can actually use the iGPU depends on the model file, and the shipped defaults are not iGPU-ready yet:

  • BirdNET ships as a TensorFlow Lite model, which cannot run on the iGPU. To accelerate BirdNET on an iGPU, switch to the fp32 ONNX model: BirdNET_v2.4_fp32.onnx.
  • Perch has shipped as ONNX from the start, but iGPU offload needs the no-DFT variant, where the DFT/spectrogram stage is moved out of the model graph so the rest can run on the GPU. Pick the model for your area from Perch-v2-Models/regional; for now you have to choose the correct region yourself.

Choosing these models will move into the UI in a later release. Until then, see the OpenVINO CPU/iGPU acceleration guide in the wiki for setup steps.

Native FLAC Encoding by Default

The built-in Go FLAC encoder, previously an opt-in preview behind BIRDNET_FLAC_ENCODER=native, is now the only FLAC encoder for both saved detection clips and BirdWeather soundscape uploads. FLAC (including EBU R128 loudness normalization) now encodes entirely in Go with no FFmpeg dependency; FFmpeg is still used for MP3, AAC, and Opus and for clip download transcoding. On a host without FFmpeg, a FLAC export setting now produces real .flac files instead of being silently downgraded to WAV (#3900).

Security

  • HLS/media tokens scrubbed from access logs. Signed HLS and media stream tokens embedded in request URLs were being written to the HTTP access log; they are now redacted from both the path and the query string there, closing a gap left by the earlier v2 API log scrubbing (#3861).

Bug Fixes

Audio & Streaming

  • RTSP sources recover when audio-only capture fails. After the audio-only RTSP handshake was introduced, some cameras that cannot set up the audio track in isolation stopped capturing entirely. Those streams now fall back automatically to the full RTSP stream (video is still discarded after decode), while cameras that already worked are unchanged (#3905).

Installer & Diagnostics

  • Installer runs systemd-analyze verify with sudo, so service-file validation no longer fails on permission errors during install (#3894).
  • Support dump tails logs fairly, giving each log file a fair share of the tail budget so a few large logs no longer crowd the others out of the dump (#3904).

🛡️ VirusTotal Results:

BirdNET-Go 20260712

Choose a tag to compare

@tphakala tphakala released this 12 Jul 15:42
594260c

This release brings hardware-accelerated inference through a new OpenVINO backend that runs BirdNET v2.4 and Perch v2 roughly twice as fast on a Raspberry Pi 5 and on Intel iGPUs, paired with a new AI Models & Inference page that shows what each model is doing in real time. It also adds an experimental BirdNET-Pi import so you can bring your detection history over from a Pi, a redesigned Analytics section with a batch of new pattern and exploration charts, and per-stream audio gain for RTSP sources. On the reliability side, USB sound cards now survive a reboot without losing capture, RTSP streams open correctly on FFmpeg 4.x (Debian 12), and the "Ignore this species" checkbox on a False Positive review finally works. Security hardening rounds it out: the public detection stream no longer leaks internal source details to anonymous clients, and HLS stream tokens are scrubbed from logs.

New Features

AI Models & Inference

BirdNET-Go now includes a native OpenVINO inference backend as an opt-in alternative to the ONNX Runtime CPU path. On ARMv8.2 CPUs with native half-precision (Cortex-A76, for example the Raspberry Pi 5) it runs the BirdNET v2.4 classifier at f16 roughly twice as fast as the CPU path, and it can also offload Perch v2 and the bat embedding extractor onto an Intel iGPU. A new hot-reloadable birdnet.backend preference (auto, onnx, openvino) selects it, the OpenVINO runtime is bundled in the container images, and any failure (missing library, unsupported CPU or model) falls back cleanly to ONNX Runtime, so default behavior is unchanged where OpenVINO does not apply (#3547, #3549, #3551, #3609, #3812).

A new AI Models & Inference page under System shows the detected hardware, the active inference backends and versions, and a card per loaded model with its identity, backend, quantization, species count, live latency and real-time-factor sparklines, approximate RAM use, and a "last heard" diagnostic feed. The page updates live and refreshes automatically when models are added, removed, or reloaded (#3563, #3566, #3571, #3577, #3585, #3603).

arm64 container images now ship a faster INT8 ONNX model by default instead of TensorFlow Lite; existing arm64 configs keep working with no migration, and custom .tflite models still load (#3544, #3864).

BirdNET-Pi Import (Experimental)

A new Import/Export page under System can import your detection history from an existing BirdNET-Pi birds.db. A guided wizard walks through selecting the source, choosing database-only or database-plus-audio mode, and then shows live progress with running, complete, cancelled, and failed states, plus a link to the imported detections when it finishes. Imports are idempotent, so re-running never creates duplicates. For containers, a new external-media mount lets you plug in a USB drive, SD card, or file share and have it appear inside the container without a restart (#3655, #3657, #3660, #3663, #3665, #3737, #3868).

This feature is marked Experimental in the UI. Native (non-container) import uses a permission-elevation flow for protected source files, and audio import is still being finalized. Please report problems on GitHub.

Redesigned Analytics (Preview)

The Analytics area has been reorganized into task-grouped Explore and Patterns sections with a batch of new visualizations: a seasonal density heatmap (date against time of day), a who-sings-when species ridgeline, a dawn-chorus onset tracker, a nocturnal activity clock, a per-species confidence distribution, a species accumulation curve, arrival and departure phenology, an acoustic succession streamgraph, and a year-over-year tracker (#3589, #3608, #3610, #3611, #3618, #3622, #3626, #3629, #3634, #3638, #3648, #3741, #3742, #3744).

Some of this is still in progress: the Weather, Soundscape, and Review analytics views and the source/microphone filter are hidden in this release and will return once they are finished (#3867).

Per-Stream Audio Gain

RTSP and network audio streams now have their own input-gain control in stream settings, mirroring the sound-card gain slider, and it takes effect without a restart. This release also fixes the case where a stream URL accidentally configured as a local sound card produced a live-audio failure with no explanation; such entries are now moved to the correct place automatically and the error message is actionable (#3779).

Cleaner UI When Clip Export Is Off

When clip export is disabled, no audio is saved, so the audio players and spectrograms that used to render empty or broken are now hidden across the dashboard, detections list, detail view, search, and the review modal, and cards collapse to a compact layout. Historical clips stay playable if you later turn export back on (#3760 by @fophillips, #3765).

Installer Reconfiguration

install.sh is now re-runnable: a new "Reconfigure settings" option lets you change the web port, TLS and access mode (direct, Let's Encrypt, or behind a reverse proxy), metrics exposure, audio device, timezone, and locale on an existing install, then regenerates the service and restarts with a config backup and rollback on failure. Fresh installs no longer bind ports 80, 443, and 8090 by default (they are now opt-in), so they stop colliding with an existing web server, and updates preserve your existing bindings (#3675, #3685, #3879).

Restart-Required Notifications

Settings that cannot take effect until a restart (web server and TLS, database, logging, and TLS certificate operations) now show a clear restart banner with the specific reason, instead of saving silently with no indication (#3531).

Smaller Extras

  • User-editable model catalog. The model catalog is now a JSON file in your config directory that you can edit; it is seeded on first run and, if you leave it untouched, refreshes automatically on upgrade (#3605).
  • Native FLAC normalization (opt-in preview). With the experimental native encoder enabled (BIRDNET_FLAC_ENCODER=native), detection-clip saves with loudness normalization now normalize entirely in Go with no FFmpeg dependency. The default FFmpeg path is unchanged (#3777).
  • Low-memory runtime detection (foundation). BirdNET-Go now detects a constrained memory limit at startup (including container cgroup caps) and applies conservative heap and allocator backstops, controlled by a new lowmemory.mode setting (auto, on, off). On systems with ample memory it is inactive and changes nothing (#3533).

Security

  • Anonymous clients no longer see internal source details. The public detection SSE stream was sending the raw audio-source display name (which can embed an RTSP host or credentials) to unauthenticated subscribers; they now receive only a stable source id, while authenticated clients are unchanged (#3726).
  • HLS tokens and secrets scrubbed from logs. Request and error logging in the v2 API recorded raw URL paths and query strings, which meant live HLS stream tokens were being written to logs; these are now redacted (#3727).
  • Session cookie Secure flag follows real TLS state. The session cookie's Secure flag is now derived from whether TLS is actually in effect (#3783).

Bug Fixes

Audio & Streaming

  • USB sound cards survive a reboot. Capture is now matched to a stable USB hardware id instead of the ALSA card index the kernel reassigns at boot, so a sound card no longer stops working after a reboot until you re-select it in Settings. This was the most-reported audio issue (#3688, #3697).
  • RTSP streams open on FFmpeg 4.x (Debian 12). The FFmpeg connection-timeout flag is now selected per FFmpeg version, fixing RTSP capture that failed to start on FFmpeg 4.x (#3560 by @mvanhorn, #3658).
  • Sample-rate dropdown populates when adding a new audio source (#3680).
  • Clip exports no longer collide thanks to a unique temp file per export (#3556).

Spectrograms

  • Bat spectrograms show the ultrasonic range again. The bat frequency profile was disabled by a malformed filter argument, so bat clips rendered in the 0-12 kHz bird view; it is fixed and re-enabled (#3529 by @alexbelgium).
  • Fallback spectrograms render in color. When clip generation falls back to FFmpeg (for example MP3 clips on native Windows), the default style now renders colorful instead of black and white (#3847 by @pelazas).

Detections & Review

  • "Ignore this species" on a False Positive now works. The checkbox silently did nothing because of a field-name mismatch; ticking it now actually adds the species to the exclude list (#3815 by @iamrans0m00).
  • Review saves no longer duplicate comments, and you can now unlock a detection from the review form (#3859).
  • Detection cards no longer overlap or get clipped on mobile (#3719 by @alexbelgium, #3729 by @alexbelgium).
  • Missing dashboard thumbnails fall back to an alternate image provider instead of showing nothing (#3816).
  • Banner descriptions preserve line breaks (#3814 by @iamrans0m00).
  • Top-species ordering is stable for species with equal detection counts, so the dashboard list no longer reshuffles between refreshes (#3830).
  • Species rarity uses your local calendar day, so "new species today" and rarity status are correct across time zones (#3820).

Species & Multi-Model

  • No more duplicate species when running multiple models. Detections are now collapsed to a canonical scientific name at ingestion, so BirdNET and Perch reporting the same bird under different names no longer show up twice or fire a spurious "new species" alert. Range-filter and inclusion matching are alias-aware as well (#3728, #3725).
  • Perch v2 non-bird classes are recognized by the privacy and dog-bark filters and by image lookups (#3584).
  • Settings species exclude list is canonicalized to scientific names so exclusions match reliably (#3692).

Integrations & Weather

  • MQTT accepts scheme-less broker addresses in the TLS a...
Read more

Release Manifest

Release Manifest Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 23 Jun 06:35
233498d

Auto-generated, machine-readable manifest of the latest BirdNET-Go release on each channel (stable, nightly, beta). Do not delete; consumed by the in-app update checker. Stable URL: https://github.com/tphakala/birdnet-go/releases/download/manifest/manifest.json

Nightly Build nightly-20260615

Choose a tag to compare

@tphakala tphakala released this 15 Jun 15:10
40f69c1

The headline of this release is species name localization for every model: detections from Perch v2 and BattyBirdNET used to show as raw scientific names, and now the majority of species resolve to proper common names in your configured language, thanks to an embedded OpenFauna dataset that is now the authoritative naming source across the dashboard, analytics, search, and species settings. This release also adds an opt-in Private Mode that locks the whole UI and API behind login, three new contributor features (a New & Returning Species widget, source badges on detections, and sortable species tables), and an important security fix that stops source-IP spoofing through forwarded headers on directly-exposed instances.

New Features

Localized Common Names for Every Model

Species detected by secondary models such as Perch v2 and BattyBirdNET previously displayed as raw scientific names, because those models only ship scientific-only labels. BirdNET-Go now resolves names through a vendored, embedded OpenFauna dataset (40+ locales), so the large majority of species, birds and bats alike, show proper common names in your configured species language across the dashboard, analytics charts and tables, detection detail, search, the species settings pickers, and CSV exports. Force-include and exclude lists, as well as search, now also accept localized common names for these scientific-only species (so a Finnish "mopsilepakko" resolves to Barbastella barbastellus). This is a display and search overlay only: MQTT, BirdWeather, notifications, the public API, RSS, and the stored database names continue to use the server-configured locale (#3404, #3406, #3407, #3450, #3452, #3454, #3460, #3461, #3464, #3468, #3469, #3504, #3506).

Two notes for upgraders: OpenFauna is now the naming authority, so for the default en-uk locale a handful of species names shift from IOC British forms to eBird/American forms (for example "Common Magpie" becomes "Eurasian Magpie"), and a search for the old name no longer matches. Separately, per-visitor browser-language localization (showing names in each visitor's own UI language) is wired in but ships off by default; it stays dormant behind a kill switch pending a dedicated per-visitor species-language preference that is independent of the UI chrome language (#3463, #3474).

Private Mode

A new Security.PrivateMode toggle (default off) locks the entire dashboard and v2 API behind authentication, for operators who do not want any read-only UI or API reachable from the internet. With it on, every endpoint except the small login-bootstrap allow-list requires authentication, and the SPA shows a full-screen login. It is strictly additive: with the toggle off, the existing guest-friendly behavior is unchanged, and the setting hot-reloads without a restart (#3122 by @TeTeHacko).

Re-Alert on Rising Confidence

Detection alert rules can now notify again when a species crosses a higher configured confidence step, scoped to the species and novelty episode, instead of being suppressed for the whole cooldown window. A rare bird that starts as a low-confidence detection and grows more convincing will now alert again at the higher step (#3288 by @keithkml).

New & Returning Species Widget

An optional dashboard widget surfaces species carrying a novelty indicator (new lifetime, new this year, or new this season) for the selected day, with a confidence pill, detection count, and a "last seen N days ago" gap for returning species. It renders nothing on quiet days and adds no extra network requests (#3376 by @alexbelgium).

Source Badges on Detections

Detections now show which microphone or RTSP source heard each bird, across detection cards, tables, the detail view, analytics, and the currently-hearing card. Search gains a source filter to match (#3101 by @TeTeHacko).

Sortable Species Tables

The analytics Species page columns are now click-to-sort, with the sort order persisted across refreshes and kept in sync with the filter dropdown (#3325 by @alexbelgium). The species settings Custom tab was also redesigned from a flat, header-less list into a sortable, searchable table matching the sibling Active tab (#3508).

Precipitation in Weather Data

The yr.no, OpenWeather, and Wunderground providers already collected a precipitation amount and a high-level condition category, but both were dropped before reaching the database. They are now persisted and exposed through the weather API and the detection-detail weather panel (#3495).

Detection Drops on System Health

Detections dropped because the classifier results queue was full were previously only visible in logs. The System Health page now surfaces these drops with windowed counts and trend indicators, so users on constrained hardware can see when they are losing detections, and how many (#3497).

Native FLAC Encoder (Preview, opt-in via BIRDNET_FLAC_ENCODER=native)

This release adds an experimental pure-Go FLAC encoder and EBU R128 audio-normalization path that removes the FFmpeg dependency for detection-clip exports and BirdWeather soundscape uploads. With the BIRDNET_FLAC_ENCODER=native environment variable set, FLAC clips and BirdWeather uploads are encoded in-process, which avoids the FFmpeg subprocess failures (encode timeouts, broken pipes, missing or misconfigured ffmpeg) that recur on resource-constrained and container deployments.

This is off by default and experimental. With the variable unset, the existing FFmpeg path runs unchanged and is byte-for-byte identical to before. The native path is gated so it can earn confidence in the field before becoming the default; there is no settings or UI for it yet (#3483, #3502, #3512).

Security

  • Forwarded client-IP headers now require a trusted proxy - CF-Connecting-IP, X-Forwarded-For, and X-Real-IP were honored from any peer, so a client on a directly-exposed instance could forge its source IP, which feeds login rate limiting, subnet-bypass auth, and request logs. These headers are now trusted only from loopback/private peers by default, plus a new hot-reloadable Security.TrustedProxies CIDR list (the reserved value "cloudflare" expands to Cloudflare's edge ranges). Upgrade note: a reverse proxy that connects from a public IP must be added to TrustedProxies for forwarded headers to be honored again (#3393).
  • Open-redirect hardening on login - post-login redirect targets are now validated and base-path-aware, so a crafted redirect cannot send users off-site after authentication (#3360).
  • Weather provider logs no longer leak secrets - API keys and request coordinates are now scrubbed from provider error logs and wrapped errors, and endpoint schemes are validated (#3448, #3451, #3456).

Bug Fixes

Audio & Streaming

  • Per-stream channel selector showed blank after reload - an unset channel mode came back as an empty string that the form's default did not catch, so the dropdown showed "Select..." after every reload. The control now adapts to the source (selector for multi-channel, a note for mono), surfaces the detected stream format, and no longer triggers a needless stream restart on an empty-vs-explicit downmix transition (#3357).
  • iOS/iPad Safari played clips silently - when the shared AudioContext was still suspended, the players routed audio into the suspended graph, which on iOS permanently silences the element. Clips now play through the native output while suspended and attach the Web Audio graph only once the context is running (#3511).
  • Stream test gave a generic error for audio-less streams - testing a URL with no audio stream now reports that specifically instead of a generic connection failure (#3429 by @kv1sidisi).
  • Audio exports now use dual-pass loudness normalization for more consistent clip levels (#3367).

Authentication

  • Basic auth and OAuth settings now hot-reload - changing them in Security settings takes effect immediately without a server restart (#3379).
  • Post-login redirect preserves the query string - you now land back on the exact page you requested, including its query parameters (#3359).
  • OIDC reliability and UX - per-issuer retry lifecycle for OIDC, OAuth login flow logged to the security module, and clearer allowed-users guidance in the settings UI (#3390, #3384).

Dashboard & Analytics

  • Mobile dashboard now uses a single-column layout instead of a cramped multi-column grid (#3274 by @keithkml).
  • Detection search now matches common names, not just scientific names (#3385).
  • Analytics timezone handling - charts and SQL now bucket dates, years, and hours by the configured timezone instead of UTC, and analytics queries apply a consistent timeout and return 408 on deadline (#3475, #3476, #3467).
  • Assorted UI fixes - the species image popup aligns to the row top in the above position, a permanent horizontal scrollbar was removed from the daily stats grid, and several dropdown, fetch-race, search-filter, and audio-playback edge cases were fixed (#3498, #3505, #3494).

Weather

  • Weather polling recovers after a settings change - the polling lifecycle, hot-reload recovery, and backoff state machine were hardened so weather updates resume correctly after settings are changed at runtime (#3453).

Infrastructure & Platform

  • Rootless container startup - the container no longer tries to link system timezone files (which fails under a rootless or arbitrary user); it reads the TZ env var directly and falls back to UTC with clear guidance when the timezone cannot be resolved (#3369 by @bo0tzz).
  • systemd host timezone - the systemd service generator now detects the host timezone via timedatectl and /etc/localtime (#3351).

Internationalization

Nightly Build nightly-20260601

Choose a tag to compare

@tphakala tphakala released this 01 Jun 16:21

This release fixes stereo RTSP streams that stopped detecting birds after nightly-20260524, and adds per-stream audio channel selection so you can pick which microphone channel (left, right, or both) each stream uses for detection. Support dump submission from Settings > Support works again (the previous timeout was too short for Raspberry Pi and slow connections). Alert rules can now match against species lists and trigger on new or returning species. A round of multi-model stability fixes makes running BirdNET alongside Perch much more reliable.

New Features

Per-Stream Audio Channel Mode Selection

You can now choose which audio channel each stream uses for bird detection: left, right, or downmix (both channels mixed together). This matters because many IP cameras send stereo audio where only one channel carries the actual microphone signal. Mixing both channels together can reduce detection accuracy due to phase interference between the left and right signals.

A new dropdown in stream settings (both when adding and editing streams) lets you pick the mode. An "Analyze Channels" button captures a few seconds of audio and shows a visual comparison of the energy levels on each channel, with a recommendation for which one to use. If a stereo source is still set to downmix, an orange warning banner appears on the stream card suggesting you select a single channel instead (#3286, #3287, #3300).

Alert Rule Enhancements

Alert rules now support "in list" and "not in list" matching, so you can create a single rule like "notify me only if the species is NOT in my common-bird list" instead of creating dozens of separate rules. A new species novelty system also tracks when each species was last seen, letting you create rules that trigger on genuinely new species (never detected before) or returning species (back after a period of absence) (#3267, #3275 by @keithkml).

Smarter Health Diagnostics

The System Health page is now better at distinguishing a brief glitch from a real problem. Instead of simple error counters, health checks evaluate whether issues are transient or sustained, whether they are getting worse or improving, and how many hours in the evaluation window were affected. The detail panel shows these signals visually with trend indicators and pattern badges, making it easier to decide whether something needs attention (#3289, #3290, #3293).

Lower Memory Usage from Audio Resampling

The audio resampler now reuses memory buffers instead of allocating new ones for every audio frame. In practice, this noticeably reduces BirdNET-Go's total memory consumption and garbage collection overhead, especially on low-powered devices like Raspberry Pi where memory is limited (#3285 by @anyasabo).

Bug Fixes

Audio & Streaming

  • Stereo RTSP streams stopped detecting birds - a regression in nightly-20260524 caused stereo RTSP streams to skip the mono downmix step when the source sample rate already matched the target (both 48 kHz). The audio pipeline received interleaved stereo samples but treated them as mono, effectively halving the sample rate. Visible symptoms: audio sounds slowed down, upper third of the spectrogram is black, and detection rates drop to zero. Fixes #3278, #3277 (#3283).
  • RTSP streams had no connection timeout - the FFmpeg flag for RTSP socket timeouts was incorrect (-timeout instead of -stimeout), so streams had no protection against hanging connections during the TCP connect phase (#3287).
  • HLS live stream played back at quarter speed for high sample rate sources - when capturing at 192 kHz (bat detection), the HLS pipeline skipped an internal downsampling step, causing the browser audio player to play back at roughly 4x slower than real time (#3347).

Range Filter & Multi-Model

  • Perch detections bypassed geographic range filter - with the default range filter setting, Perch species were not filtered by location, allowing out-of-range species to appear in detections and notifications (#3276 by @keithkml).
  • Active Species table empty after uninstalling a model - removing Perch v2 or BirdNET v3.0 could leave behind stale config that silently disabled the range filter entirely, causing detections to run unfiltered with no warning in the UI (#3324).
  • Species count showed ~14,800 species with multi-model - when running BirdNET alongside Perch, the Active Species / Current Species count ignored the range filter threshold for non-primary model species, displaying every species in the database instead of only those in your geographic area (#3326).
  • Stale range filter config persisted after model uninstall - even after the runtime was fixed, the saved config could still show incorrect status in the Species page and heatmap. The config now self-heals on startup (#3327).
  • Duplicate species in analytics with multi-model - insights pages (new arrivals, dawn chorus, phantom species, expected species) showed duplicate entries when both BirdNET and Perch detected the same species (#3294).

Model Reload Stability

  • Crashes and incorrect results during model reload - several race conditions could cause crashes, panics, or stale data when reloading, uninstalling, or reinstalling models while detection was running. Model metadata is now captured atomically during reload, and settings access is synchronized across all concurrent readers (#3329, #3333, #3340, #2933 by @anyasabo).

Health Diagnostics

  • Health status showed "Healthy" when no data was available - the system now correctly reports "Unknown" when diagnostic results are empty, instead of falsely reporting a healthy state (#3308).

Infrastructure & Platform

  • Container startup failed on Kubernetes/OpenShift - running under an arbitrary user ID (common in rootless containers and OpenShift) caused startup failures because the system could not look up user information. Container detection now uses a reliable fallback (#3266 by @bo0tzz).
  • Let's Encrypt certificates lost on every restart - TLS certificates were stored only in memory, so each restart requested a new certificate from Let's Encrypt. This could hit rate limits and cause temporary HTTPS outages (#3319 by @brycesub).
  • Support dump uploads timing out on slow connections - submitting a support dump from Settings > Support could fail on Raspberry Pi or slow networks because the upload exceeded the default 30-second HTTP timeout. The timeout is now 120 seconds (#3301).
  • Unnecessary image lookups wasting API calls - the background image refresh was retrying species that were already confirmed to have no image available, and included species from prediction models that had never actually been detected (#3305 by @keithkml).
  • Noisy error reports from Wikipedia rate limiting - temporary Wikipedia API throttling was generating unnecessary error reports in Sentry; these are now suppressed since they resolve on their own (#3309).
  • "Error opening /proc/self/cgroup" message on macOS - a harmless but confusing error message appeared on non-Linux platforms during container detection (#3193 by @anyasabo).
  • Build setup failed on Raspberry Pi - architecture detection in the Taskfile was incorrect for ARM platforms (#3192 by @anyasabo).

Nightly Build nightly-20260524

Choose a tag to compare

@tphakala tphakala released this 24 May 15:20

This release fixes a critical regression where RTSP streams with sample rates below 48 kHz (typical IP cameras send 8-16 kHz audio) cut in and out after the bat detection changes in nightly-20260523. All streams are now probed at startup so resampling only happens when needed. This release also adds time-windowed health evaluation with sparkline visualizations, SQLite corruption detection with auto-recovery at startup, and completes settings hot-reload coverage for the remaining 5 settings that previously required a restart.

New Features

Time-Windowed Health Evaluation with Sparkline Visualization

Health diagnostics no longer evaluate lifetime counters. A past burst of errors previously marked the system as Critical forever until restart; checks now evaluate configurable time windows (15m to 7d, default 1h). The System Health page is redesigned to match the System Overview visual language: a status metric strip replaces the old hero card, diagnostics auto-run on page mount, and counter-based checks show inline SVG sparklines (24 hourly bars, colored by status) with expandable detail panels. The window selector persists to localStorage. 22 new i18n keys fully translated across all 15 locales (#3249).

Complete Settings Hot-Reload Coverage

Five settings categories that were saved to disk but required a restart to take effect now hot-reload at runtime: Log Deduplication, RTSP Health monitoring, MQTT HomeAssistant discovery, System Monitoring, and HLS LiveStream. This brings the hot-reload TODO count from 5 to 0: every setting changed through the UI now takes effect immediately (#3254).

SQLite Corruption Detection at Startup with Auto-Recovery

A synchronous PRAGMA quick_check now runs at startup after migration. When index-level corruption is detected (common from power loss on SD cards), BirdNET-Go attempts automatic recovery via REINDEX. If recovery fails, the system continues in degraded mode so headless users keep web UI access. A corruption flag is latched to suppress duplicate Sentry event floods (prevents the 244+ duplicate events seen in production), and a persistent notification with actionable recovery guidance is sent to the user. A new DatabaseIntegrityCheck appears in the health diagnostics system (#3246).

Security

  • Temp file paths hardened against symlink attacks - Predictable temp file paths across datastore, API prerequisites, and log rotation are replaced with os.CreateTemp (random name + O_EXCL). Backup files and archives now use 0600 permissions instead of the os.Create default. Database connection pools are properly closed when post-Open() initialization fails (#3248).

Bug Fixes

Audio & Streaming

  • RTSP streams with sub-48 kHz sample rates cut in and out - The bat detection changes in nightly-20260523 removed FFmpeg's -ar/-ac output resampling flags for all protocol streams, which broke cameras that send 8-16 kHz audio since the pipeline expects 48 kHz. All streams are now probed via ffprobe at startup to discover actual sample rates. Resampling is applied only when the source rate differs from the target: sub-48 kHz sources get resampled up, 48 kHz sources skip resampling, and high-rate bat sources preserve their ultrasonic content. A new SourceSampleRate field carries the probed rate through the full pipeline. Fixes #3255 (#3256).
  • Model reload used stale settings, locale changes required restart - ReloadModel() read from a stale bn.Settings pointer, so changing the locale or thread count via the UI had no effect until a full restart. All sub-methods now see a fresh settings snapshot. Five stale settings reads in HLS streaming are also fixed (#3253).
  • Duplicate ORT notifications on range filter reload - The v3 geomodel path bypassed the early ONNX Runtime availability check, causing repeated Sentry events and bell notifications on every range filter reload when ORT was unavailable. A single check at the top of model initialization now guards both paths (#3245).

Health Diagnostics

  • Health check endpoint could hang indefinitely - runChecks spawned goroutines with 10s per-check contexts and then called wg.Wait() unconditionally. If a check ignored its context (e.g., gopsutil syscalls), the /api/v2/system/diagnostics/run endpoint blocked forever. A channel-based approach now respects an overall timeout with a 100ms grace period, returning StatusUnknown for unfinished checks. Multi-result slices are defensively copied to prevent data races (#3251).