Skip to content

Python / Gradio / Streamlit Integration Guide

SignaVis kann in Python-Anwendungen über seinen IIFE-Bundle eingebettet werden. Alle relevanten Typen sind in types/index.d.ts exportiert.


Bundle-Format

dist/birdnet-player.iife.js   ← für <script>-Tags in Gradio/Streamlit HTML
dist/birdnet-player.esm.js    ← für ES-Module-Umgebungen
dist/birdnet-player.css       ← Stylesheet (immer einbinden)

Das IIFE-Bundle exportiert window.BirdNETPlayerModule mit allen Klassen.


Minimal-Beispiel (Gradio Custom Component)

import gradio as gr

with gr.Blocks() as demo:
    gr.HTML("""
    <link rel="stylesheet" href="/static/birdnet-player.css">
    <script src="/static/birdnet-player.iife.js"></script>
    <div id="player-root"></div>
    <script>
      const { BirdNETPlayer, MockAudioEngine, InMemoryStorageAdapter } = window.BirdNETPlayerModule;

      // Headless-Modus: kein echtes WaveSurfer nötig
      // const engine = new MockAudioEngine();

      // Normaler Modus mit echtem Audio:
      const player = new BirdNETPlayer(
        document.getElementById('player-root'),
        { showFileOpen: false, viewMode: 'spectrogram' }
      );

      // Warte auf Initialisierung
      player.ready.then(() => {
        // Audiodaten von Python-Server laden
        player.loadUrl('/audio/recording.wav');
      });
    </script>
    """)

Events für Python → JavaScript

// Alle Events die BirdNETPlayer emittiert:
player.on('annotationcreate', (e) => {
  const ann = e.detail.annotation;
  // { id, start, end, species, color, tags, ... }
  // → via postMessage, Gradio component update oder fetch() an Python-Server senden
  fetch('/api/annotation', {
    method: 'POST',
    body: JSON.stringify(ann),
    headers: { 'Content-Type': 'application/json' },
  });
});

player.on('labelsync', () => {
  // Alle Labels haben sich geändert
});

player.on('undochange', (e) => {
  // e.detail.canUndo, e.detail.canRedo
});

JavaScript → Python Events

// Annotationen aus Python-Backend laden:
const response = await fetch('/api/annotations/recording-123');
const labels = await response.json();
player.setSpectrogramLabels(labels);

// Vorberechnetes Spektrogramm injizieren (kein DSP im Browser nötig):
const spectroResponse = await fetch('/api/spectrogram/recording-123');
const spectroData = await spectroResponse.arrayBuffer();
await player.setSpectrogramData(
  new Float32Array(spectroData),
  nFrames,
  nMels,
  { mode: 'mel', sampleRate: 32000 }
);

Headless-Modus (kein Audio, nur UI)

Für Fälle wo Python die DSP-Verarbeitung übernimmt und nur das UI-Overlay benötigt wird:

import { MockAudioEngine, InMemoryStorageAdapter } from './dist/birdnet-player.esm.js';

const engine  = new MockAudioEngine();
const storage = new InMemoryStorageAdapter({ 'aw-favourite-preset': 'perch' });

const player = new BirdNETPlayer(container, {
  engine,   // kein WaveSurfer, kein AudioContext
  storage,  // kein localStorage
});

await player.ready;

// Fake-Audio laden (kein echter ArrayBuffer nötig für UI-Tests)
await engine.loadFromUrl('placeholder://');

// Spektrogramm direkt injizieren (von Python berechnet)
await player.setSpectrogramData(floatArray, 6000, 160, { mode: 'mel' });

Wichtige Public-API-Methoden

Methode Beschreibung
loadUrl(url) Audio-URL laden (http, blob:, data:)
setSpectrogramData(data, nFrames, nMels, opts) Float32Array-Spektrogramm injizieren
setSpectrogramImage(image, opts) Fertig gerendertes Bild injizieren
setAnnotations(annotations) Waveform-Annotationen setzen
setSpectrogramLabels(labels) Spektrogramm-Labels setzen
setLabelTaxonomy(taxonomy) Label-Kategorien definieren
setLabelSuggestionProvider(fn) Suggestion-Callback registrieren
setSpeciesBar(name, opts) Artenleiste setzen
setBackgroundSpecies(species) Hintergrundarten für Suche
player.on(event, callback) Event-Listener registrieren
player.undo() / player.redo() Undo/Redo
destroy() Player aufräumen

Bekannte Einschränkungen

  • Bandpass-Segment-Playback erfordert AudioContext — nicht im Headless-Modus verfügbar.
  • WaveSurfer kann via options.WaveSurfer injiziert oder über CDN geladen werden.
  • CORS: Audio-URLs müssen CORS-Header senden oder über einen Proxy geladen werden.