Skip to content

BirdBox in your browser

BirdBox finds bird vocalizations as time-frequency boxes. The model runs on your device; audio is never uploaded.

Drop a recording here

WAV, FLAC, MP3, OGG or M4A, up to 10 minutes. Recordings are resampled to 32 kHz mono, like the CLI does.

# Time Frequency Confidence Verify or remove

About this demo

The demo runs a self-contained BirdBox graph with ONNX Runtime Web 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 with the same model. The model menu at the top picks the graph:

  • 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.
  • All-In-One (docs/models/All-In-One_fp16.onnx): the All-in-One 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: 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.

Browser limits

  • 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.
  • Use the CLI for long files and batch jobs.

The sample soundscape is the example recording of BirdNET-Analyzer (birdnet_analyzer/example/soundscape.wav, MIT License), resampled to 32 kHz. The BirdNET website demo uses the same file. Recordings loaded by number come from Xeno-canto under the license of each recording.

Adding 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.

    python src/inference/onnx_export.py \
        --output-path docs/models/Just-Bird_fp16.onnx \
        --precision fp16
    
    python src/inference/onnx_export.py `
        --output-path docs/models/Just-Bird_fp16.onnx `
        --precision fp16
    
    python src/inference/onnx_export.py ^
        --output-path docs/models/Just-Bird_fp16.onnx ^
        --precision fp16
    

    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 start with it.

    {
      "models": [
        {
          "file": "Just-Bird_fp16.onnx",
          "label": "Just-Bird_fp16.onnx",
          "merge_method": "fusion",
          "conf": 0.15,
          "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", "…": "…" }
        }
      ]
    }
    
    Field Meaning
    file The ONNX file, relative to docs/models/
    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 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 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 merge still matches the graph:

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

    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.