Last active 3 weeks ago

birdnet-pi.md Raw

BirdNET-Pi capture, classification, and storage design

BirdNET-Pi continuously consumes audio while the add-on and its recording service are running. However, it does not normally retain one continuous recording. It creates short temporary WAV segments, analyzes them, extracts clips for qualifying detections, and deletes the temporary segments.

Capture, classify, and store loop

1. Capture continuously

The recording service runs persistently and is configured to restart if it exits.

  • With a local microphone, arecord continuously writes sequential WAV files.
  • With RTSP or another stream, ffmpeg continuously segments the stream.
  • The default segment length is 15 seconds, configurable as RECORDING_LENGTH between 3 and 60 seconds.
  • In the Home Assistant add-on, these working files are placed in /tmp/StreamData, which is normally RAM-backed tmpfs, reducing disk writes.

See birdnet_recording.sh and the add-on's temporary-storage setup.

2. Analyze each completed segment

The analysis service watches StreamData for a completed-file event. It does not analyze a file while the recorder still has it open.

When a WAV closes, the analyzer:

  • Reads and resamples it to the model's required sample rate.
  • Converts it to mono.
  • Splits it into 3-second inference windows.
  • Optionally overlaps those windows according to OVERLAP.
  • Runs every window through the selected BirdNET model.

Capture and analysis therefore operate as a pipeline: the recorder can be creating the next segment while the previous one is being classified. Files that accumulated while analysis was stopped are processed as a backlog when it restarts.

See birdnet_analysis.py and utils/analysis.py.

3. Apply the classification filters

For each 3-second window, the model returns ranked species candidates. BirdNET-Pi considers up to the top ten candidates, not solely the highest-ranked one.

A candidate becomes a detection only if:

  • Its score is at least CONFIDENCE—default 0.70.
  • It passes the optional include and exclude lists.
  • It passes the location/week species-occurrence filter, unless explicitly whitelisted.
  • The window was not suppressed by the human-speech privacy filter.

Multiple species from the same 3-second window can therefore be accepted if each exceeds the threshold.

What happens above the confidence threshold?

For every accepted detection, BirdNET-Pi:

  • Extracts a short audio clip around the relevant 3-second window. The default extraction includes some surrounding context.
  • Names it with the species, confidence percentage, date, source, and time.
  • Stores it persistently under a structure similar to BirdSongs/By_Date/YYYY-MM-DD/Species Name/...audio-file.
  • Generates a spectrogram PNG beside the extracted audio.
  • Adds a row to the SQLite detections database.
  • Appends a corresponding record to BirdDB.txt.
  • Includes it in the current-segment JSON output used by the live interface.
  • Potentially sends an Apprise notification, subject to notification settings.
  • If BirdWeather is configured, uploads the segment as a soundscape and reports each accepted detection.
  • If the add-on's MQTT feature is enabled, publishes detection details—including species, confidence, and clip name—to the birdnet topic.

The extraction and database behavior is implemented in utils/reporting.py. The add-on-specific MQTT hook is in 33-mqtt.sh.

What happens below the threshold, or when nothing is detected?

Nothing permanent is stored for that candidate:

  • No extracted audio clip.
  • No spectrogram.
  • No database detection row.
  • No notification or detection publication.

Once reporting is complete, the analyzer deletes the original temporary WAV, even when the segment produced zero qualifying detections. It writes an empty live-results JSON object for that segment, but that JSON is replaced by a later segment.

In short:

BirdNET-Pi listens and temporarily records continuously, but normally retains audio only around classifications that pass all thresholds and filters. It is not intended to preserve a continuous 24/7 audio archive.

One caveat: if analysis fails, falls behind, or the container is stopped mid-analysis, temporary WAV files can remain as backlog. The add-on attempts to preserve unfinished files during shutdown and restore them on the next start.