Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

<a href="#license"><img src="https://img.shields.io/badge/license-MIT%20code%20%7C%20AGPL--3.0%20project-brightgreen.svg" alt="License: MIT code, AGPL-3.0 project"></a>
<a href="https://www.python.org/downloads/release/python-31213/" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/python-3.12-blue.svg" alt="Python 3.12"></a>
<img src="https://img.shields.io/badge/species-282-brightgreen" alt="Species 282">

</div>

Expand All @@ -29,7 +28,7 @@ Everything you need, including installation instructions, an interactive demo, m

## Demo

Try the [Demo](https://birdnet-team.github.io/BirdBox/demo/) in your browser: it runs the Just-Bird model on your device, with no installation and no upload. Load a recording, tune the confidence and phrase gap, review and edit the boxes, and export them in the BirdBox output formats.
Try the [Demo](https://birdnet-team.github.io/BirdBox/demo/) in your browser: it runs the Just-Bird model (or All-In-One, from the model menu) on your device, with no installation and no upload. Load a recording, tune the confidence and phrase gap, review and edit the boxes, and export them in the BirdBox output formats.

<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/img/demo_screenshot_dark.png">
Expand Down
45 changes: 32 additions & 13 deletions docs/demo.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@ hide:

## About this demo

The demo runs the self-contained Just-Bird graph `docs/models/Just-Bird_fp16.onnx` with [ONNX Runtime Web](https://onnxruntime.ai/docs/tutorials/web/){ target="_blank" rel="noopener noreferrer" } in your browser. The graph computes the PCEN spectrogram, runs the YOLO detector on 3 s windows every 1.5 s and applies NMS, just like [`detect_birds.py`](cli/detect-birds.md) with the Just-Bird model. There are no species labels: every box is a bird vocalization (`bird`).
The demo runs a self-contained BirdBox graph with [ONNX Runtime Web](https://onnxruntime.ai/docs/tutorials/web/){ target="_blank" rel="noopener noreferrer" } in your browser. The graph computes the PCEN spectrogram, runs the YOLO detector on 3 s windows every 1.5 s and applies NMS, just like [`detect_birds.py`](cli/detect-birds.md) with the same model. The model menu at the top picks the graph:

**Instant sliders.** The model runs once per recording, at the lowest confidence of the slider (0.05). The demo asks the graph for its per-window boxes (`raw_all`) and repeats the graph's window fusion in JavaScript: window ownership and weighted box fusion, joining calls into phrases, removing nested boxes. NMS only lets higher-scoring boxes suppress lower ones, so the boxes for any confidence and phrase gap are the same as a graph run with those values.
- **Just-Bird** (`docs/models/Just-Bird_fp16.onnx`, the default): every box is a bird vocalization (`bird`), without species labels. For species, combine the boxes with [BirdNET](https://github.com/birdnet-team/BirdNET-Analyzer){ target="_blank" rel="noopener noreferrer" }.
- **All-In-One** (`docs/models/All-In-One_fp16.onnx`): the [All-in-One](models-and-metrics/all-in-one.md) model with its 282 classes. The table names the species of each box.

**Instant sliders.** The model runs once per recording, at the lowest confidence of the slider (0.05). The demo asks the graph for its per-window boxes (`raw_all`) and repeats the graph's merge in JavaScript. For Just-Bird that is window fusion: window ownership and weighted box fusion, joining calls into phrases, removing nested boxes. For All-In-One it is song reconstruction: boxes of one species closer than the song gap become one box. NMS only lets higher-scoring boxes suppress lower ones, so the boxes for any confidence and gap are the same as a graph run with those values.

**Spectrogram.** The viewer shows an STFT spectrogram by default. In its display settings, *PCEN* switches to the PCEN mel spectrogram BirdBox detects on.

**Review.** Boxes can be verified, moved, resized, removed and drawn. The exports use the BirdBox [output formats](data/outputs.md): the JSON of `--output-format json-with-algorithm-metadata`, the simplified CSV and the Raven selection table, plus a CSV with every column of the table.

!!! warning "Browser limits"
- The model is downloaded once (about 35 MB) and then comes from the browser cache.
- The model is downloaded once (about 20 MB for Just-Bird, 51 MB for All-In-One) and then comes from the browser cache.
- Audio is decoded locally, resampled to 32 kHz mono and truncated to **10 minutes**.
- The browser's resampler is not librosa's, so files that are not recorded at 32 kHz can give slightly different boxes than the CLI.
- ONNX Runtime runs single-threaded here: about 10 s for 2 minutes of audio on a laptop. Safari can be slower than Chromium or Firefox.
Expand All @@ -28,7 +31,7 @@ The sample soundscape is the example recording of [BirdNET-Analyzer](https://git

## Adding models

The demo runs the first model in `docs/models/manifest.json` with `"merge_method": "fusion"`. Only window-fusion exports work: the instant sliders need the graph's per-window boxes (`raw_all`) and the JavaScript port of its window fusion (`docs/javascripts/demo/fusion.js`). The export uses window fusion for Just-Bird, Hawaii and Southern-Sierra-Nevada (`--merge auto`); `--merge fusion` forces it for the other models.
The model menu lists the models in `docs/models/manifest.json`; the first one is the default. The instant sliders need the graph's per-window boxes (`raw_all`) and a JavaScript port of its merge: `docs/javascripts/demo/fusion.js` for window fusion (`fusion`, the export's default for Just-Bird, Hawaii and Southern-Sierra-Nevada) and `docs/javascripts/demo/songs.js` for song reconstruction (`reconstruct`, the default for the other models). The Just-Bird frequency gate (`--merge reconstruct` with Just-Bird) has no port; such entries are skipped.

1. Export the model.

Expand All @@ -53,11 +56,13 @@ The demo runs the first model in `docs/models/manifest.json` with `"merge_method
--precision fp16
```

`--precision fp16` stores the network weights in fp16, which makes the file about a third smaller (35 MB instead of 53 MB for Just-Bird). Feature extraction and merging stay in fp32. On 13 test recordings, 99.4% of the fp32 graph's boxes were reproduced (mean IoU 0.996). The export prints the merge it baked in (`Merge (baked in)`) and the suggested defaults (`Default conf`, `Default song_gap`), which it also stores in the ONNX metadata.
For another model, add `--pt-model`, for example `--pt-model models/All-In-One.pt --output-path docs/models/All-In-One_fp16.onnx`.

`--precision fp16` stores the network weights in fp16, which halves the file (20 MB instead of 38 MB for Just-Bird, 51 MB instead of 99 MB for All-In-One). Feature extraction and merging stay in fp32. On 13 test recordings (`tests/onnx_graph_parity.py`), the fp16 graphs reproduced the boxes of `detect_birds.py` with the `.pt` model: 99.8% for Just-Bird (mean IoU 0.995) and 99.7% for All-In-One, with the same species (mean IoU 0.997). The export prints the merge it baked in (`Merge (baked in)`) and the suggested defaults (`Default conf`, `Default song_gap`), which it also stores in the ONNX metadata.

2. Place the `.onnx` file under `docs/models/` if the export path was elsewhere.

3. Add an entry to `docs/models/manifest.json`, first in the list if the demo should run it.
3. Add an entry to `docs/models/manifest.json`, first in the list if the demo should start with it.

```json
{
Expand All @@ -70,6 +75,16 @@ The demo runs the first model in `docs/models/manifest.json` with `"merge_method
"phrase_gap": 0.05,
"species_mapping": "Just-Bird",
"names": { "0": "bird" }
},
{
"file": "All-In-One_fp16.onnx",
"label": "All-In-One_fp16.onnx",
"merge_method": "reconstruct",
"conf": 0.2,
"song_gap": 0.1,
"species_mapping": "All-In-One",
"names": { "0": "????", "1": "amabaw1", "…": "…" },
"common_names": { "0": "Unknown", "1": "Amazonian Barred-Woodcreeper", "…": "…" }
}
]
}
Expand All @@ -78,19 +93,23 @@ The demo runs the first model in `docs/models/manifest.json` with `"merge_method
| Field | Meaning |
| :--- | :--- |
| `file` | The ONNX file, relative to `docs/models/` |
| `label` | Name shown at the top of the demo |
| `merge_method` | `fusion`, as printed by the export. Other entries are skipped. |
| `label` | Name in the model menu |
| `merge_method` | `fusion` or `reconstruct`, as printed by the export. Other entries are skipped. |
| `conf` | Where the confidence slider starts: the printed `Default conf` (0.15 for Just-Bird, 0.2 for the other models) |
| `phrase_gap` | Where the phrase gap slider starts: the printed `Default song_gap` (0.05 for Just-Bird, 0 for Hawaii and Southern-Sierra-Nevada) |
| `phrase_gap` | `fusion` only: where the phrase gap slider starts, the printed `Default song_gap` (0.05 for Just-Bird, 0 for Hawaii and Southern-Sierra-Nevada) |
| `song_gap` | `reconstruct` only: where the song gap slider starts, the printed `Default song_gap` (0.1) |
| `species_mapping` | Written to `model_config` of the exported JSON |
| `names` | Class labels for the exports, by class index (ONNX Runtime Web does not expose ONNX metadata) |
| `names` | eBird codes by class index, for the table and the exports (ONNX Runtime Web does not expose ONNX metadata) |
| `common_names` | Optional: common names by class index, shown in the table instead of the codes |

For a species model, `names` and `common_names` come from `id_to_ebird` and `ebird_to_name` of its mapping in `src/config.py`. With more than one class, the table gets a species column.

4. Check that the demo's fusion still matches the graph:
4. Check that the demo's merge still matches the graph:

```bash
cd tests/js && npm install
node demo_fusion_parity.mjs ../../docs/models/Just-Bird_fp16.onnx
node demo_merge_parity.mjs ../../docs/models/Just-Bird_fp16.onnx
```

The script compares `fusion.js` with the graph's own detections for 16 slider settings on `tests/test.wav` and fails on any difference. Run it after exporting a new model or changing the fusion in `src/inference/onnx_export.py`.
The script compares `fusion.js` or `songs.js`, whichever the manifest entry's `merge_method` names, with the graph's own detections for 16 slider settings on `tests/test.wav` and fails on any difference. Run it after exporting a new model or changing a merge in `src/inference/onnx_export.py`.

5 changes: 2 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
<p><strong>Deep Learning Bird Call Detection & Evaluation System</strong></p>

<a href="#license"><img src="https://img.shields.io/badge/license-MIT%20code%20%7C%20AGPL--3.0%20project-brightgreen.svg" alt="License: MIT code, AGPL-3.0 project"></a>
<a href="https://www.python.org/downloads/release/python-3120/" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/python-3.12-blue.svg" alt="Python 3.12"></a>
<img src="https://img.shields.io/badge/species-282-brightgreen" alt="Species 282">
<a href="https://www.python.org/downloads/release/python-31213/" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/python-3.12-blue.svg" alt="Python 3.12"></a>

</div>

Expand Down Expand Up @@ -58,7 +57,7 @@ The inference software found 4 different species vocalizations and was able to l
## Quick Links

- [Installation](installation.md) - set up the environment
- [Demo](demo.md) - Just-Bird in your browser
- [Demo](demo.md) - BirdBox in your browser
- [How it works](how-it-works/overview.md) - pipeline description
- [Data In/Out](data/fileflows.md) - datasets and output-format descriptions
- [Models and Metrics](models-and-metrics/overview.md) - list of models with corresponding metrics
Expand Down
Loading
Loading