voice_audio_multi/docs/models/nemotron_3_diar.md
Fabio c36510c21e
Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
Initial import: audio.cpp with Orange Pi documentation
2026-11-04 19:05:22 +01:00

8 KiB
Raw Permalink Blame History

Nemotron 3 Diarization

nemotron_3_diar provides native audio.cpp inference for NVIDIA Nemotron 3 Diarization. It identifies up to eight speakers by arrival order and supports offline, native-batch, and continuous streaming inference.

Model

Field Value
Family nemotron_3_diar
Task diar
Modes offline, streaming
Input 16 kHz WAV audio
Output Speaker turns through --turns-out
Weights BF16 GGUF (default), Q8_0 GGUF

The checkpoint is distributed under OpenMDW-1.1. GGUF weights are packaged in Nemotron-3-Diarization-GGUF.

Convert

Build audiocpp_gguf, then convert the original .nemo archive:

python tests/nemotron_3_diar/convert_gguf.py \
  --checkpoint /path/to/Nemotron-3-Diarization.nemo \
  --output-dir /path/to/staging \
  --converter /path/to/audiocpp_gguf \
  --gguf-output /path/to/Nemotron-3-Diarization-GGUF/nemotron-3-diarization-bf16.gguf \
  --type orig

The converter reads the original NeMo archive, writes canonical Safetensors staging files, and packages a self-contained GGUF with the v1 model spec.

Run

Offline:

audiocpp_cli --task diar \
  --family nemotron_3_diar \
  --model /path/to/nemotron-3-diarization-bf16.gguf \
  --backend cuda --audio meeting.wav --turns-out turns.json

The server exposes native batch inference through repeated multipart files:

curl -N http://127.0.0.1:8080/v1/batches/transcriptions \
  -F model=nemotron-3-diar \
  -F file=@/path/to/meeting-a.wav \
  -F file=@/path/to/meeting-b.wav

The SSE response emits each file's speaker_turns as soon as that result is ready. Use its index field to map results back to upload order.

Streaming with an official latency profile:

audiocpp_cli --task diar --mode streaming \
  --family nemotron_3_diar \
  --model /path/to/nemotron-3-diarization-bf16.gguf \
  --backend cuda --audio meeting.wav --turns-out turns.json \
  --session-option nemotron_3_diar.latency_profile=low

Latency Profiles

In server streaming mode, use /v1/audio/transcriptions/live for live PCM or /v1/audio/transcriptions with stream=true for a WAV upload. Configure the model with task: "diar", mode: "streaming", and the desired latency profile in session_options. See the server streaming API for request and response formats.

Streaming emits completed speaker turns. An ongoing turn appears when it ends or when the input stream closes, so time to the first turn also depends on the speech itself. The final response contains all turns, including the last open turn. The buffer latencies below describe model input buffering, not time to a completed speaker turn.

All geometry values use 80 ms encoder frames. Input-buffer latency is chunk_len + chunk_right_context.

Profile Buffer latency Speaker cache FIFO Chunk Right context Cache update
very_high 30.4 s 264 40 340 40 300
low 1.04 s 264 264 9 4 222
very_low 0.64 s 264 264 6 2 222
ultra_low 0.32 s 264 264 3 1 222
asr_la13 1.12 s 264 264 14 0 222
asr_la6 0.56 s 264 264 7 0 222
asr_la3 0.32 s 264 264 4 0 222
asr_la0 0.08 s 264 264 1 0 222

The asr_laN profiles match nemotron_asr speaker masking at ASR lookahead N: one ASR chunk of N + 1 frames per step and no right context, as in NeMo's multitalker pipeline. See speaker-tagged transcription. asr_la0 processes one 80 ms frame per step and is slow.

Use custom to set the five geometry controls directly.

Common Options

Option Value Default Description
--audio WAV path required Input audio for one request.
--turns-out JSON path not set Save decoded speaker turns.
--mode offline, streaming offline Select bounded offline or incremental streaming execution.
--batch-audio-dir directory not set Submit all WAV files through native offline batching.

Request Options

Use these with --request-option.

Option Value Default Description
speaker_threshold 0.0 to 1.0 0.5 Speaker activity threshold.
speaker_min_frames integer >= 0 0 Minimum turn duration in 10 ms output frames.
speaker_pad_frames integer >= 0 0 Padding around turns in 10 ms output frames.
return_frame_probabilities true, false false Attach the raw 10 ms speaker-activity timeline as the speaker_probabilities artifact. With --out-dir, the CLI writes speaker_probabilities.safetensors. It holds one F32 tensor speaker_probabilities [frames, 8] and string metadata: format_version, source_family, frames, speakers, frame_hop_samples, sample_rate, latency_profile, and the five geometry values. nemotron_asr reads this file for speaker-tagged transcription.

Session Options

Use these with --session-option nemotron_3_diar.<name>=<value>.

Option Value Default Description
latency_profile very_high, low, very_low, ultra_low, asr_la0, asr_la3, asr_la6, asr_la13, custom very_high Streaming geometry preset.
spkcache_len integer >= 16 checkpoint value Speaker-cache length for custom.
fifo_len integer >= 0 checkpoint value FIFO length for custom.
chunk_len integer >= 1 checkpoint value Processing chunk length for custom.
chunk_right_context integer >= 0 checkpoint value Future context for custom.
spkcache_update_period integer >= 1 checkpoint value FIFO-to-cache update period for custom.
graph_arena_mb integer >= 1 1024 GGML graph metadata arena size.
weight_context_mb integer >= 1 1024 GGML weight metadata arena size.
weight_type storage type native Runtime weight storage type.
attention auto, flash, eager auto Encoder attention lowering. auto uses flash attention on GPUs that support it and eager attention on others, such as Volta and Turing.

Validation

The output was compared with NeMo Python (SortformerEncLabelModel.forward_streaming, FP32, CPU, NVIDIA-NeMo/Speech cf724ac) and with NVIDIA's C++ port (NeMo-Speech.cpp 8c15060), using the same .nemo checkpoint (SHA-256 867c53f5...). All numbers use the native 10 ms speaker probabilities.

Case Build Max |Δ| vs NeMo Mean |Δ| Frame flips at 0.5
AMI EN2002d 20 s (319,990 samples), very_high CPU, F32 weights 8.7e-4 2.1e-5 0
AMI EN2002d 20 s (319,990 samples), low CPU, F32 weights 1.6e-3 2.6e-5 1
Same clip, NVIDIA C++ port, very_high CPU, F32 1.1e-1 9.4e-4 2

The model is sensitive to tiny input changes in long streams. On a 120 s meeting with the low profile, adding inaudible noise (σ = 1e-5) to the input changes the NeMo output by 1.1% DER-equivalent and this port's output by 3.2%. This port and NeMo differ by 3.6–4.2% on the same file, which is the same order. NVIDIA's C++ port shows the same difference. Against NeMo on that file, every build falls in one band: CPU F32 4.2%, CUDA F32 4.4%, CUDA BF16 5.1%, and CUDA Q8_0 4.3%. Q8_0 therefore shows no quality cliff.

On CUDA, flash attention converts K and V to F16. Compared with the CPU F32 output, eager attention reduces the difference from 74 to 2 flipped frames on the 120 s stream and costs about 35% more time (900 s of audio in 16.8 s instead of 12.5 s on an RTX 4070 Ti SUPER). The default stays auto.

Known deviation: NeMo pads mel features to a multiple of 16 frames, and its subpixel convolution reads those padded rows at the last real 80 ms frame. This port uses zero padding there, so the final 70 ms of a file can differ by up to 0.02.