LAION-AI/univeral-audio-annotation-pipeline

25

stars

19

commits

Python

primary language

Jul 3, 2026

updated

README

Universal Audio Annotation Pipeline

Produces structured JSON annotations from any audio file, covering speech transcription, speaker diarization, emotions, vocal bursts, sound effects, and music.

Best configuration: Gemma-12B + DiCoW — Nemotron 3.5 words + VibeVoice/Sortformer diarization + DiCoW overlap-aware ASR, fused by a text-only Gemma-4-12B LLM (no audio in the final step). It is the highest-Reward pipeline on SoundScape-Bench (0.253) — rank 3 of all systems, nearly matching Gemini 3.5 Flash (0.256) and ahead of every other pipeline. (It trades precision for that recall: see the tradeoff note.)

A turnkey, end-to-end implementation lives in default_pipeline/ — the default, suggested configuration. It uses Nemotron 3.5 for the words, VibeVoice + Sortformer for diarization/timing, pyannote + DiCoW to transcribe overlapping speakers separately, the Whisper experts and the SFX LoRA sound-event detector — all fused by a text-only Gemma-4-12B model (it reads only the experts' outputs, not the audio). It produces expressive emotion & speaking-style captions, detailed sound-effect captions and a dedicated music segment type, strict diarization-only speaker identity, overlapping-speech segments, and explicit singing detection, plus per-clip JSON and a self-contained HTML report. The legacy audio MOSS-Audio-8B annotator (higher precision/F1) remains available via --fusion moss, as does the triple-ASR ensemble. See docs/default_pipeline.md for models, setup and run instructions.

cd default_pipeline && bash setup_environments.sh ./envs
export HF_TOKEN=...        # token with gated pyannote + SFX-LoRA access accepted
bash run_all.sh --audio /path/to/clips --workdir ./uaap_work --envs ./envs      # --fusion gemma (default)

⚡ With ≥2 GPUs the heavy stages (Gemma fusion, SFX, ASR…) are auto-sharded across GPUs over disjoint clips (≈N× faster, identical output; --gpus 0,1). Optional quality-neutral lower-VRAM fuser: export GEMMA_FILE=gemma-4-12b-it-UD-Q6_K_XL.gguf. See efficiency notes.

🎧 Live demo (20 samples — audio + predictions vs ground truth): demo · 📊 Full model comparison: comparison

Pipeline Architecture

The default configuration combines Nemotron 3.5 (words), VibeVoice + Sortformer (diarization/timing), pyannote + DiCoW (overlap-aware per-speaker ASR), the Whisper voice experts and the specialist sound-event pre-passes — all fused by a text-only Gemma-4-12B stage that reads the experts' outputs (not the audio):

┌───────────────────────────────────────────────────────────────────────┐
│                    INPUT: Audio File (any length)                      │
└───────────────────────────────────┬───────────────────────────────────┘
        ┌──────────────┬─────────────┴───────────┬───────────────────┐
        ▼              ▼                          ▼                   ▼
  ┌──────────┐  ┌────────────────┐     ┌──────────────┐   ┌────────────────────┐
  │ VibeVoice│  │ Nemotron 3.5 + │     │ pyannote     │   │ DiCoW              │
  │ ASR      │  │ Sortformer     │     │ diarization  │──▶│ diarization-cond.  │
  │ (diar/   │  │ (words)        │     │ + overlap    │   │ Whisper (per-spk,  │
  │  timing) │  │                │     │ detection    │   │ overlap-aware ASR) │
  └────┬─────┘  └───────┬────────┘     └──────┬───────┘   └─────────┬──────────┘
       │ timing/spk     │ words               │ overlaps            │ overlapped speech
       └────────┬───────┴─────────────┬───────┴──────────┬─────────┘
            ▼                      ▼                  ▼
  ┌──────────────────────┐  ┌──────────────────────────────┐
  │ Whisper experts (x3) │  │ Specialist sound-event prepass│
  │ emotion · timbre ·   │  │ • SFX LoRA (MOSS-8B-Instruct  │
  │ speaking-style        │  │   + laion sfx-lora r=128)     │
  │ (per utterance)      │  │ • Vocal-burst locator @0.88   │
  └──────────┬───────────┘  └───────────────┬──────────────┘
             └───────────────┬──────────────┘
                             ▼
        ┌──────────────────────────────────────────────┐
        │     Gemma-4-12B — TEXT-ONLY fusion (no audio) │
        │  fuses all expert text → final annotation     │
        │  Nemotron words on VibeVoice timeline         │
        │  DiCoW recovers overlapping/simultaneous spk  │
        │  detailed sound-event + dedicated music caps  │
        │  (legacy: MOSS-Audio-8B, audio, --fusion moss)│
        └───────────────────────┬──────────────────────┘
                                │  + deterministic gap-fill
                                ▼
        ┌──────────────────────────────────────────────┐
        │   OUTPUT: Structured JSON (covers full clip)  │
        │   [speech · vocal_burst · sound_event · music]│
        └──────────────────────────────────────────────┘

Output Format

The pipeline produces a JSON array of segment dictionaries. Four segment types:

Speech segment

{
  "type": "speech",
  "start_time": 2.31,
  "end_time": 5.87,
  "transcription": "I can't believe you actually did that",
  "speaker_id": "speaker_1",
  "emotion": "anger_3",
  "age": "adult_30s",
  "gender": "female",
  "voice_timbre": "alto, warm, slightly raspy",
  "speaking_style": "confrontational, accusatory, raised voice",
  "language": "en",
  "accent": "American Midwest",
  "speaking_rate": "fast"
}

Vocal burst segment

{
  "type": "vocal_burst",
  "start_time": 5.87,
  "end_time": 6.14,
  "speaker_id": "speaker_1",
  "vocal_burst": "scoff",
  "emotion": "contempt_2"
}

Sound event segment

{
  "type": "sound_event",
  "start_time": 3.10,
  "end_time": 5.20,
  "description": "Medium-sized dog barking aggressively in the background",
  "loudness": "moderate"
}

Music segment

{
  "type": "music",
  "start_time": 9.80,
  "end_time": 15.10,
  "description": "Upbeat acoustic folk-pop: brightly strummed steel-string guitar and light tambourine, mid-tempo ~110 BPM, major key, warm and nostalgic mood, no vocals",
  "loudness": "moderate"
}

Field Reference

FieldValues
emotionEmoNet taxonomy + intensity 1-4 (e.g. anger_3, joy_2, sadness_4)
agebaby, toddler, child, teenager, young_adult_20s, adult_30s, adult_40s, middle_aged_50s, senior_60s, elderly_70s_plus
gendermale, female, nonbinary, unclear
speaking_ratevery_slow, slow, normal, fast, very_fast
vocal_burstchuckle, belly_laugh, gentle_sob, gasp, sigh, scoff, scream, etc.
loudnessquiet, moderate, loud, very_loud
languageISO 639-1 code

Quick Start

Installation

pip install -r requirements.txt

Run the pipeline

# DEFAULT pipeline (Gemma-12B + DiCoW, text-only fusion): use the staged runner
cd default_pipeline
bash run_all.sh --audio input.wav --workdir ./uaap_work --envs ./envs       # --fusion gemma (default)

The default Gemma-12B + DiCoW configuration runs as the staged default_pipeline/ (each stage in its own venv — llama.cpp, pyannote, DiCoW and the ASR toolkits pin incompatible deps, so they can't share one process). The single-process pipeline/run_pipeline.py below is a legacy reference for the MOSS-Audio configurations only.

Configurations

ConfigFinal fusion · ASRSoundScape-Bench RewardNotes
Gemma-12B + DiCoWdefaultGemma-4-12B text-only · Nemotron+VibeVoice/Sortformer + DiCoW overlap ASR0.253Best Reward of any pipeline; overlap-aware; trades precision (see eval)
nemotron_vibevoice (MOSS, --fusion moss)MOSS-Audio-8B audio · Nemotron+VibeVoice/Sortformer0.236Most precise (best F1/lowest hallucination); audio-grounded
triple_greedy (legacy ensemble)MOSS-Audio-8B · VibeVoice+Parakeet+Qwen30.196Top on the older 60-scene LLM-judged eval (4.13)
ensemble_greedy / vibevoiceMOSS-Audio-8B · dual / single ASRReduced ASR variants

Gemma-12B + DiCoW is the default (bash run_all.sh ... --fusion gemma). It adds pyannote diarization + DiCoW overlap-aware ASR, then fuses every expert's text output with Gemma-4-12B (no audio in the final step) — plus the SFX LoRA detector, vocal-burst locator (0.7) + captioner, emotion/ style captions, dedicated music segments, overlapping-speech segments and full-timeline coverage. Use --fusion moss for the audio MOSS-Audio-8B annotator (higher precision). See docs/default_pipeline.md.

Model Requirements

ModelHuggingFace IDGPU VRAMRole
VibeVoice-ASRmicrosoft/VibeVoice-ASR~16 GBdiarization/timing (default)
Nemotron 3.5 ASRnvidia/nemotron-3.5-asr-streaming-0.6b~3 GBwords (default)
Sortformernvidia/diar_sortformer_4spk-v1~2 GBdiarization (default)
pyannotepyannote/speaker-diarization-3.1 (+ segmentation-3.0, gated)~2 GBoverlap detection (default)
DiCoWBUT-FIT/DiCoW_v3_3~3 GBoverlap-aware per-speaker ASR (default)
Gemma fuserunsloth/gemma-4-12b-it-GGUF (Q8, llama.cpp)~14 GBTEXT-only final fusion (default)
Whisper experts (x3)laion/BUD-E-Whisper, laion/timbre-whisper, laion/voice-tagging-whisper~2 GBemotion/timbre/style
SFX LoRAOpenMOSS-Team/MOSS-Audio-8B-Instruct + laion/moss-audio-sfx-lora-v4 (gated)~18 GBsound events
Vocal-burst locator + captionerlaion/vocalburst-locator (@0.88) + laion/vocalburst-captioning-whisper~2 GBvocal bursts
Parakeet / Qwen3nvidia/parakeet-tdt-0.6b-v3, Qwen/Qwen3-ASR-1.7B (+aligner)~12 GBlegacy ensemble only
MOSS AnnotatorOpenMOSS-Team/MOSS-Audio-8B-Thinking~18 GBlegacy final stage (--fusion moss)

Models load/unload sequentially (each stage in its own venv), so peak VRAM ≈ the largest single stage (~16–18 GB); the default runs comfortably on one 24 GB GPU, faster on two.

Gated models (request access, then export HF_TOKEN=...): pyannote/segmentation-3.0, pyannote/speaker-diarization-3.1, and laion/moss-audio-sfx-lora-v4 (or run --no-sfx). The Gemma GGUF downloads automatically. Full model table with links: docs/default_pipeline.md.

Evaluation Results

SoundScape-Bench (200 multilingual soundscapes, automatic answer-key scoring)

The current default was selected on SoundScape-Bench — 200 held-out soundscapes (EN/ZH/FR/DE/ES/NL, ~25 % overlapping speech) built from understood pieces so every event has an exact answer key. The headline Reward = IoU(timing) × content, where content is a weighted mix of caption cosine and (1 − WER) for speech, averaged over all answer-key events.

#SystemRewardIoUF1WERsndhalluc
1Gemini 3.1 Pro (omni)0.2970.6150.27072 %0.38523 %
2Gemini 3.5 Flash (omni)0.2560.5560.23367 %0.31023 %
3UAAP Gemma-12B + DiCoW ⭐ (this default, text-only fusion)0.2530.5150.14959 %0.27343 %
4UAAP Gemma-12B (text-only, no DiCoW)0.2480.5120.14456 %0.27844 %
5UAAP Gemma-4B + DiCoW (text-only)0.2440.4900.15159 %0.26944 %
6UAAP nemotron_vibevoice (MOSS-Audio-8B, --fusion moss)0.2360.4570.19165 %0.28727 %
7Gemini 3 Flash (omni)0.2120.4500.17266 %0.26233 %
8UAAP triple-ASR ensemble (legacy)0.1960.3880.14566 %0.22632 %
9GPT-Audio 1.5 (omni)0.0970.2230.09761 %0.15236 %

The default Gemma-12B + DiCoW is the highest-Reward pipeline of all (rank 3 overall, nearly matching Gemini 3.5 Flash and well above the audio MOSS configs). A text-only LLM that faithfully fuses strong experts wins on timing (IoU) and transcription (WER), and DiCoW recovers overlapping/simultaneous speakers (cleanly separating e.g. an English and a Mandarin speaker talking at once).

⚖️ Precision tradeoff (read before deploying): because the Gemma fuser has no audio, it cannot reject candidate events it can't hear, so it over-generates — hallucination ~43 % and F1 ~0.15, versus the audio MOSS-Audio-8B config's 27 % / 0.191. If you need maximum precision / fewest spurious events, run --fusion moss. The default optimizes the recall-oriented Reward at lower cost (a ~12B text model, no audio in the final step).

📊 Interactive comparison: soundscape_comparison.html · 🎧 20-sample audio demo (predictions vs ground truth): gemma12_dicow_demo.html

Vocal-burst detection threshold (how we chose 0.88)

The vocal-burst pre-pass is a two-model ensemble: the detector laion/vocalburst-locator finds where bursts occur, and the captioner laion/vocalburst-captioning-whisper (a Whisper-small fine-tune of laion/sound-effect-captioning-whisper on laion/improved_synthetic_vocal_burts; val clap_sim 0.251 vs 0.190 untuned) describes what each one is.

To pick the detector's confidence threshold we swept 0.85 → 0.92 (1% steps) over 150 audio clips (merge_gap=0.3 s, min_dur=0.5 s). For every (clip × threshold) the detected segments were captioned, and the audio + (start, end, caption) list was sent to Gemini 3.1 Pro, which rated three axes 0–5 (5 = perfect): caption quality, timestamp accuracy, and completeness (cover ALL real bursts, penalizing misses and false positives) — 1,200 independent judgments. overall = mean of the three.

rankthresholdoverallcompletenesscaption qualitytimestamp accuracy
🥇0.883.4753.113.244.07
🥈0.893.4693.153.184.08
🥉0.853.4663.113.224.07
40.903.4453.103.244.00
50.863.4113.053.144.04
60.873.3903.073.104.00
70.913.3643.053.143.91
80.923.3633.023.153.92

Scores cluster tightly across the band; threshold 0.88 is the best overall and is now the pipeline default (UAAP_VB_THRESHOLD, VocalBurstLocator.detect(threshold=0.88)). Timestamp accuracy is consistently strong (~4.0); completeness is the weakest axis and drops at 0.91–0.92 as real bursts get missed. Full interactive report (audio + predictions + per-clip Gemini scores for the top-3 thresholds): on the locator model card.

Legacy LLM-judged eval (60 scenes, Gemini 3.1 Pro, 0–5 scale)

Earlier configuration sweep that selected the previous triple-ASR default:

#ASRDecodingSyntheticYouTubeCombined
1Triplegreedy3.704.564.13
2Tripletemp=0.53.744.233.99
3Ensemblegreedy3.434.393.91
4VibeVoicegreedy3.534.083.80
5VibeVoicetemp=0.53.703.653.67
6Ensembletemp=0.53.503.813.66

Combined = equal-weight average of Synthetic and YouTube scores.

For detailed evaluation results, see docs/evaluation_results.md.

Interactive evaluation grid: GitHub Pages

Repository Structure

default_pipeline/        # ⭐ Default recommended configuration (turnkey scripts)
  setup_environments.sh  # Build the per-component virtual-envs
  run_all.sh             # Run all stages end-to-end
  prepare_audio.py       # Stage 0: decode + index
  workers/               # One script per stage:
    stage1a_vibevoice.py #   VibeVoice-ASR (diarization / timing authority)
    stage1_nemotron_sortformer.py #  Nemotron 3.5 + Sortformer (default word source)
    stage_pyannote_diar.py #  ⭐ pyannote diarization + overlap detection (default)
    stage_dicow.py       #   ⭐ DiCoW diarization-conditioned overlap ASR (default)
    stage5_gemma_fusion.py #  ⭐ Gemma-12B TEXT-only fusion — DEFAULT final stage
    stage1b_parakeet.py  #   Parakeet TDT v3 + Sortformer (legacy ensemble option)
    stage1c_qwen3.py     #   Qwen3-ASR + ForcedAligner (legacy ensemble option)
    stage2_whisper_experts.py  # emotion/timbre/style
    stage3_sfx_lora.py   #   SFX LoRA sound events
    stage3b_vocalburst.py#   Vocal-burst locator + captioner
    stage4_moss_annotator.py   # MOSS-Audio final annotation (legacy, --fusion moss)
  build_report.py        # Self-contained HTML report

pipeline/
  run_pipeline.py        # Single-process reference runner (MOSS configs only)
  asr_vibevoice.py       # VibeVoice-ASR component
  asr_nemotron.py        # Nemotron 3.5 + Sortformer (default word source)
  diarize_pyannote.py    # ⭐ pyannote diarization + overlap detection
  asr_dicow.py           # ⭐ DiCoW diarization-conditioned overlap ASR
  gemma_fusion.py        # ⭐ Gemma text-only LLM fusion (default final stage)
  asr_parakeet.py        # Parakeet TDT v3 + Sortformer (legacy ensemble option)
  asr_qwen3.py           # Qwen3-ASR-1.7B + ForcedAligner (legacy ensemble option)
  whisper_experts.py     # Emotion/timbre/style Whisper models
  sfx_lora.py            # LoRA SFX sound event detection
  vocalburst_locator.py  # Vocal-burst locator + sound-effect captioner
  moss_annotator.py      # MOSS-Audio-8B-Thinking annotation (legacy final stage)
  utils.py               # Shared utilities (incl. full-timeline gap-fill)

evaluation/
  eval_triple_asr.py     # Full evaluation script
  gemini_judge.py        # Gemini evaluation scorer
  build_html_report.py   # HTML report generator

docs/
  default_pipeline.md    # ⭐ Default configuration: models, links, setup, run guide
  pipeline_details.md    # Per-component details
  evaluation_results.md  # Full evaluation results
  training_lora.md       # LoRA training details
  eval_grid/index.html   # Interactive evaluation grid

examples/
  sample_output.json     # Example pipeline output
  sample_predictions/    # Sample prediction JSONs

ASR

Voice experts

Sound events

Annotator & MOSS-Audio

License

Apache 2.0

Contributors

LAION-AI/univeral-audio-annotation-pipeline

25

stars

19

commits

Python

primary language

Jul 3, 2026

updated

README

Universal Audio Annotation Pipeline

Produces structured JSON annotations from any audio file, covering speech transcription, speaker diarization, emotions, vocal bursts, sound effects, and music.

Best configuration: Gemma-12B + DiCoW — Nemotron 3.5 words + VibeVoice/Sortformer diarization + DiCoW overlap-aware ASR, fused by a text-only Gemma-4-12B LLM (no audio in the final step). It is the highest-Reward pipeline on SoundScape-Bench (0.253) — rank 3 of all systems, nearly matching Gemini 3.5 Flash (0.256) and ahead of every other pipeline. (It trades precision for that recall: see the tradeoff note.)

A turnkey, end-to-end implementation lives in default_pipeline/ — the default, suggested configuration. It uses Nemotron 3.5 for the words, VibeVoice + Sortformer for diarization/timing, pyannote + DiCoW to transcribe overlapping speakers separately, the Whisper experts and the SFX LoRA sound-event detector — all fused by a text-only Gemma-4-12B model (it reads only the experts' outputs, not the audio). It produces expressive emotion & speaking-style captions, detailed sound-effect captions and a dedicated music segment type, strict diarization-only speaker identity, overlapping-speech segments, and explicit singing detection, plus per-clip JSON and a self-contained HTML report. The legacy audio MOSS-Audio-8B annotator (higher precision/F1) remains available via --fusion moss, as does the triple-ASR ensemble. See docs/default_pipeline.md for models, setup and run instructions.

cd default_pipeline && bash setup_environments.sh ./envs
export HF_TOKEN=...        # token with gated pyannote + SFX-LoRA access accepted
bash run_all.sh --audio /path/to/clips --workdir ./uaap_work --envs ./envs      # --fusion gemma (default)

⚡ With ≥2 GPUs the heavy stages (Gemma fusion, SFX, ASR…) are auto-sharded across GPUs over disjoint clips (≈N× faster, identical output; --gpus 0,1). Optional quality-neutral lower-VRAM fuser: export GEMMA_FILE=gemma-4-12b-it-UD-Q6_K_XL.gguf. See efficiency notes.

🎧 Live demo (20 samples — audio + predictions vs ground truth): demo · 📊 Full model comparison: comparison

Pipeline Architecture

The default configuration combines Nemotron 3.5 (words), VibeVoice + Sortformer (diarization/timing), pyannote + DiCoW (overlap-aware per-speaker ASR), the Whisper voice experts and the specialist sound-event pre-passes — all fused by a text-only Gemma-4-12B stage that reads the experts' outputs (not the audio):

┌───────────────────────────────────────────────────────────────────────┐
│                    INPUT: Audio File (any length)                      │
└───────────────────────────────────┬───────────────────────────────────┘
        ┌──────────────┬─────────────┴───────────┬───────────────────┐
        ▼              ▼                          ▼                   ▼
  ┌──────────┐  ┌────────────────┐     ┌──────────────┐   ┌────────────────────┐
  │ VibeVoice│  │ Nemotron 3.5 + │     │ pyannote     │   │ DiCoW              │
  │ ASR      │  │ Sortformer     │     │ diarization  │──▶│ diarization-cond.  │
  │ (diar/   │  │ (words)        │     │ + overlap    │   │ Whisper (per-spk,  │
  │  timing) │  │                │     │ detection    │   │ overlap-aware ASR) │
  └────┬─────┘  └───────┬────────┘     └──────┬───────┘   └─────────┬──────────┘
       │ timing/spk     │ words               │ overlaps            │ overlapped speech
       └────────┬───────┴─────────────┬───────┴──────────┬─────────┘
            ▼                      ▼                  ▼
  ┌──────────────────────┐  ┌──────────────────────────────┐
  │ Whisper experts (x3) │  │ Specialist sound-event prepass│
  │ emotion · timbre ·   │  │ • SFX LoRA (MOSS-8B-Instruct  │
  │ speaking-style        │  │   + laion sfx-lora r=128)     │
  │ (per utterance)      │  │ • Vocal-burst locator @0.88   │
  └──────────┬───────────┘  └───────────────┬──────────────┘
             └───────────────┬──────────────┘
                             ▼
        ┌──────────────────────────────────────────────┐
        │     Gemma-4-12B — TEXT-ONLY fusion (no audio) │
        │  fuses all expert text → final annotation     │
        │  Nemotron words on VibeVoice timeline         │
        │  DiCoW recovers overlapping/simultaneous spk  │
        │  detailed sound-event + dedicated music caps  │
        │  (legacy: MOSS-Audio-8B, audio, --fusion moss)│
        └───────────────────────┬──────────────────────┘
                                │  + deterministic gap-fill
                                ▼
        ┌──────────────────────────────────────────────┐
        │   OUTPUT: Structured JSON (covers full clip)  │
        │   [speech · vocal_burst · sound_event · music]│
        └──────────────────────────────────────────────┘

Output Format

The pipeline produces a JSON array of segment dictionaries. Four segment types:

Speech segment

{
  "type": "speech",
  "start_time": 2.31,
  "end_time": 5.87,
  "transcription": "I can't believe you actually did that",
  "speaker_id": "speaker_1",
  "emotion": "anger_3",
  "age": "adult_30s",
  "gender": "female",
  "voice_timbre": "alto, warm, slightly raspy",
  "speaking_style": "confrontational, accusatory, raised voice",
  "language": "en",
  "accent": "American Midwest",
  "speaking_rate": "fast"
}

Vocal burst segment

{
  "type": "vocal_burst",
  "start_time": 5.87,
  "end_time": 6.14,
  "speaker_id": "speaker_1",
  "vocal_burst": "scoff",
  "emotion": "contempt_2"
}

Sound event segment

{
  "type": "sound_event",
  "start_time": 3.10,
  "end_time": 5.20,
  "description": "Medium-sized dog barking aggressively in the background",
  "loudness": "moderate"
}

Music segment

{
  "type": "music",
  "start_time": 9.80,
  "end_time": 15.10,
  "description": "Upbeat acoustic folk-pop: brightly strummed steel-string guitar and light tambourine, mid-tempo ~110 BPM, major key, warm and nostalgic mood, no vocals",
  "loudness": "moderate"
}

Field Reference

FieldValues
emotionEmoNet taxonomy + intensity 1-4 (e.g. anger_3, joy_2, sadness_4)
agebaby, toddler, child, teenager, young_adult_20s, adult_30s, adult_40s, middle_aged_50s, senior_60s, elderly_70s_plus
gendermale, female, nonbinary, unclear
speaking_ratevery_slow, slow, normal, fast, very_fast
vocal_burstchuckle, belly_laugh, gentle_sob, gasp, sigh, scoff, scream, etc.
loudnessquiet, moderate, loud, very_loud
languageISO 639-1 code

Quick Start

Installation

pip install -r requirements.txt

Run the pipeline

# DEFAULT pipeline (Gemma-12B + DiCoW, text-only fusion): use the staged runner
cd default_pipeline
bash run_all.sh --audio input.wav --workdir ./uaap_work --envs ./envs       # --fusion gemma (default)

The default Gemma-12B + DiCoW configuration runs as the staged default_pipeline/ (each stage in its own venv — llama.cpp, pyannote, DiCoW and the ASR toolkits pin incompatible deps, so they can't share one process). The single-process pipeline/run_pipeline.py below is a legacy reference for the MOSS-Audio configurations only.

Configurations

ConfigFinal fusion · ASRSoundScape-Bench RewardNotes
Gemma-12B + DiCoWdefaultGemma-4-12B text-only · Nemotron+VibeVoice/Sortformer + DiCoW overlap ASR0.253Best Reward of any pipeline; overlap-aware; trades precision (see eval)
nemotron_vibevoice (MOSS, --fusion moss)MOSS-Audio-8B audio · Nemotron+VibeVoice/Sortformer0.236Most precise (best F1/lowest hallucination); audio-grounded
triple_greedy (legacy ensemble)MOSS-Audio-8B · VibeVoice+Parakeet+Qwen30.196Top on the older 60-scene LLM-judged eval (4.13)
ensemble_greedy / vibevoiceMOSS-Audio-8B · dual / single ASRReduced ASR variants

Gemma-12B + DiCoW is the default (bash run_all.sh ... --fusion gemma). It adds pyannote diarization + DiCoW overlap-aware ASR, then fuses every expert's text output with Gemma-4-12B (no audio in the final step) — plus the SFX LoRA detector, vocal-burst locator (0.7) + captioner, emotion/ style captions, dedicated music segments, overlapping-speech segments and full-timeline coverage. Use --fusion moss for the audio MOSS-Audio-8B annotator (higher precision). See docs/default_pipeline.md.

Model Requirements

ModelHuggingFace IDGPU VRAMRole
VibeVoice-ASRmicrosoft/VibeVoice-ASR~16 GBdiarization/timing (default)
Nemotron 3.5 ASRnvidia/nemotron-3.5-asr-streaming-0.6b~3 GBwords (default)
Sortformernvidia/diar_sortformer_4spk-v1~2 GBdiarization (default)
pyannotepyannote/speaker-diarization-3.1 (+ segmentation-3.0, gated)~2 GBoverlap detection (default)
DiCoWBUT-FIT/DiCoW_v3_3~3 GBoverlap-aware per-speaker ASR (default)
Gemma fuserunsloth/gemma-4-12b-it-GGUF (Q8, llama.cpp)~14 GBTEXT-only final fusion (default)
Whisper experts (x3)laion/BUD-E-Whisper, laion/timbre-whisper, laion/voice-tagging-whisper~2 GBemotion/timbre/style
SFX LoRAOpenMOSS-Team/MOSS-Audio-8B-Instruct + laion/moss-audio-sfx-lora-v4 (gated)~18 GBsound events
Vocal-burst locator + captionerlaion/vocalburst-locator (@0.88) + laion/vocalburst-captioning-whisper~2 GBvocal bursts
Parakeet / Qwen3nvidia/parakeet-tdt-0.6b-v3, Qwen/Qwen3-ASR-1.7B (+aligner)~12 GBlegacy ensemble only
MOSS AnnotatorOpenMOSS-Team/MOSS-Audio-8B-Thinking~18 GBlegacy final stage (--fusion moss)

Models load/unload sequentially (each stage in its own venv), so peak VRAM ≈ the largest single stage (~16–18 GB); the default runs comfortably on one 24 GB GPU, faster on two.

Gated models (request access, then export HF_TOKEN=...): pyannote/segmentation-3.0, pyannote/speaker-diarization-3.1, and laion/moss-audio-sfx-lora-v4 (or run --no-sfx). The Gemma GGUF downloads automatically. Full model table with links: docs/default_pipeline.md.

Evaluation Results

SoundScape-Bench (200 multilingual soundscapes, automatic answer-key scoring)

The current default was selected on SoundScape-Bench — 200 held-out soundscapes (EN/ZH/FR/DE/ES/NL, ~25 % overlapping speech) built from understood pieces so every event has an exact answer key. The headline Reward = IoU(timing) × content, where content is a weighted mix of caption cosine and (1 − WER) for speech, averaged over all answer-key events.

#SystemRewardIoUF1WERsndhalluc
1Gemini 3.1 Pro (omni)0.2970.6150.27072 %0.38523 %
2Gemini 3.5 Flash (omni)0.2560.5560.23367 %0.31023 %
3UAAP Gemma-12B + DiCoW ⭐ (this default, text-only fusion)0.2530.5150.14959 %0.27343 %
4UAAP Gemma-12B (text-only, no DiCoW)0.2480.5120.14456 %0.27844 %
5UAAP Gemma-4B + DiCoW (text-only)0.2440.4900.15159 %0.26944 %
6UAAP nemotron_vibevoice (MOSS-Audio-8B, --fusion moss)0.2360.4570.19165 %0.28727 %
7Gemini 3 Flash (omni)0.2120.4500.17266 %0.26233 %
8UAAP triple-ASR ensemble (legacy)0.1960.3880.14566 %0.22632 %
9GPT-Audio 1.5 (omni)0.0970.2230.09761 %0.15236 %

The default Gemma-12B + DiCoW is the highest-Reward pipeline of all (rank 3 overall, nearly matching Gemini 3.5 Flash and well above the audio MOSS configs). A text-only LLM that faithfully fuses strong experts wins on timing (IoU) and transcription (WER), and DiCoW recovers overlapping/simultaneous speakers (cleanly separating e.g. an English and a Mandarin speaker talking at once).

⚖️ Precision tradeoff (read before deploying): because the Gemma fuser has no audio, it cannot reject candidate events it can't hear, so it over-generates — hallucination ~43 % and F1 ~0.15, versus the audio MOSS-Audio-8B config's 27 % / 0.191. If you need maximum precision / fewest spurious events, run --fusion moss. The default optimizes the recall-oriented Reward at lower cost (a ~12B text model, no audio in the final step).

📊 Interactive comparison: soundscape_comparison.html · 🎧 20-sample audio demo (predictions vs ground truth): gemma12_dicow_demo.html

Vocal-burst detection threshold (how we chose 0.88)

The vocal-burst pre-pass is a two-model ensemble: the detector laion/vocalburst-locator finds where bursts occur, and the captioner laion/vocalburst-captioning-whisper (a Whisper-small fine-tune of laion/sound-effect-captioning-whisper on laion/improved_synthetic_vocal_burts; val clap_sim 0.251 vs 0.190 untuned) describes what each one is.

To pick the detector's confidence threshold we swept 0.85 → 0.92 (1% steps) over 150 audio clips (merge_gap=0.3 s, min_dur=0.5 s). For every (clip × threshold) the detected segments were captioned, and the audio + (start, end, caption) list was sent to Gemini 3.1 Pro, which rated three axes 0–5 (5 = perfect): caption quality, timestamp accuracy, and completeness (cover ALL real bursts, penalizing misses and false positives) — 1,200 independent judgments. overall = mean of the three.

rankthresholdoverallcompletenesscaption qualitytimestamp accuracy
🥇0.883.4753.113.244.07
🥈0.893.4693.153.184.08
🥉0.853.4663.113.224.07
40.903.4453.103.244.00
50.863.4113.053.144.04
60.873.3903.073.104.00
70.913.3643.053.143.91
80.923.3633.023.153.92

Scores cluster tightly across the band; threshold 0.88 is the best overall and is now the pipeline default (UAAP_VB_THRESHOLD, VocalBurstLocator.detect(threshold=0.88)). Timestamp accuracy is consistently strong (~4.0); completeness is the weakest axis and drops at 0.91–0.92 as real bursts get missed. Full interactive report (audio + predictions + per-clip Gemini scores for the top-3 thresholds): on the locator model card.

Legacy LLM-judged eval (60 scenes, Gemini 3.1 Pro, 0–5 scale)

Earlier configuration sweep that selected the previous triple-ASR default:

#ASRDecodingSyntheticYouTubeCombined
1Triplegreedy3.704.564.13
2Tripletemp=0.53.744.233.99
3Ensemblegreedy3.434.393.91
4VibeVoicegreedy3.534.083.80
5VibeVoicetemp=0.53.703.653.67
6Ensembletemp=0.53.503.813.66

Combined = equal-weight average of Synthetic and YouTube scores.

For detailed evaluation results, see docs/evaluation_results.md.

Interactive evaluation grid: GitHub Pages

Repository Structure

default_pipeline/        # ⭐ Default recommended configuration (turnkey scripts)
  setup_environments.sh  # Build the per-component virtual-envs
  run_all.sh             # Run all stages end-to-end
  prepare_audio.py       # Stage 0: decode + index
  workers/               # One script per stage:
    stage1a_vibevoice.py #   VibeVoice-ASR (diarization / timing authority)
    stage1_nemotron_sortformer.py #  Nemotron 3.5 + Sortformer (default word source)
    stage_pyannote_diar.py #  ⭐ pyannote diarization + overlap detection (default)
    stage_dicow.py       #   ⭐ DiCoW diarization-conditioned overlap ASR (default)
    stage5_gemma_fusion.py #  ⭐ Gemma-12B TEXT-only fusion — DEFAULT final stage
    stage1b_parakeet.py  #   Parakeet TDT v3 + Sortformer (legacy ensemble option)
    stage1c_qwen3.py     #   Qwen3-ASR + ForcedAligner (legacy ensemble option)
    stage2_whisper_experts.py  # emotion/timbre/style
    stage3_sfx_lora.py   #   SFX LoRA sound events
    stage3b_vocalburst.py#   Vocal-burst locator + captioner
    stage4_moss_annotator.py   # MOSS-Audio final annotation (legacy, --fusion moss)
  build_report.py        # Self-contained HTML report

pipeline/
  run_pipeline.py        # Single-process reference runner (MOSS configs only)
  asr_vibevoice.py       # VibeVoice-ASR component
  asr_nemotron.py        # Nemotron 3.5 + Sortformer (default word source)
  diarize_pyannote.py    # ⭐ pyannote diarization + overlap detection
  asr_dicow.py           # ⭐ DiCoW diarization-conditioned overlap ASR
  gemma_fusion.py        # ⭐ Gemma text-only LLM fusion (default final stage)
  asr_parakeet.py        # Parakeet TDT v3 + Sortformer (legacy ensemble option)
  asr_qwen3.py           # Qwen3-ASR-1.7B + ForcedAligner (legacy ensemble option)
  whisper_experts.py     # Emotion/timbre/style Whisper models
  sfx_lora.py            # LoRA SFX sound event detection
  vocalburst_locator.py  # Vocal-burst locator + sound-effect captioner
  moss_annotator.py      # MOSS-Audio-8B-Thinking annotation (legacy final stage)
  utils.py               # Shared utilities (incl. full-timeline gap-fill)

evaluation/
  eval_triple_asr.py     # Full evaluation script
  gemini_judge.py        # Gemini evaluation scorer
  build_html_report.py   # HTML report generator

docs/
  default_pipeline.md    # ⭐ Default configuration: models, links, setup, run guide
  pipeline_details.md    # Per-component details
  evaluation_results.md  # Full evaluation results
  training_lora.md       # LoRA training details
  eval_grid/index.html   # Interactive evaluation grid

examples/
  sample_output.json     # Example pipeline output
  sample_predictions/    # Sample prediction JSONs

ASR

Voice experts

Sound events

Annotator & MOSS-Audio

License

Apache 2.0

Contributors

Languages

Python

96.3%

Shell

3.7%