CoolFace
Modelpublic

aufklarer/Sortformer-Diarization-CoreML

sourceHugging Facecc-by-4.0updated 2mo agoView on Hugging Face
1likes698downloads
Model Card

Sortformer Diarization (CoreML)

CoreML port of NVIDIA Sortformer for end-to-end speaker diarization on Apple Silicon. Runs on the Neural Engine. No separate embedding extraction or clustering — the model directly predicts per-frame speaker activity for up to 4 speakers, with streaming state (speaker cache + FIFO) carried across calls.

Model

ArchitectureSortformer (Sort Loss + 17-layer FastConformer + 18-layer Transformer)
Base model`nvidia/diar_streaming_sortformer_4spk-v2.1` (117M params)
PrecisionFP16 compute, FP32 I/O boundaries
Sample rate16 kHz, 128 mel bins (n_fft 400, hop 160)
Max speakers4 (arrival-order slots)
Speaker cache / FIFO188 / 40 encoder frames
Frame duration80 ms per prediction frame

Three variants ship from the same checkpoint, differing only in chunk shape:

VariantNew audio per callMel inputUse case
Sortformer (default)~27 s[1, 3048, 128]offline batch, highest throughput
Sortformer_balanced~8 s[1, 968, 128]~3× faster first-load compile
Sortformer_streaming480 ms[1, 112, 128]incremental / realtime

Files

FileSizeDescription
Sortformer.mlmodelc / .mlpackage~230 MBdefault variant (compiled / source)
Sortformer_balanced.mlmodelc / .mlpackage~230 MBbalanced variant
Sortformer_streaming.mlmodelc / .mlpackage~230 MBstreaming variant
config.json, config_balanced.json, config_streaming.json<1 KBchunk-shape hyperparameters per variant

Performance

Measured on M-series Apple Silicon (Neural Engine, warm):

VariantPer-call latencyRealtime factor
defaultone call per ~27 s of audio~125–750×
balancedone call per ~8 shundreds of ×
streaming8.1 ms median per 480 ms step~59× per step; ~39× end-to-end incremental

The streaming export is parity-gated: driven by NeMo's own streaming feature loader and cache-update algorithm, it matches NeMo's native forward_streaming loop at 100% frame-decision agreement (MAE 0.0005). On a five-file VoxConverse-dev pilot, the incremental session reaches 8.1% DER (collar 0.25) with correct speaker counts on all files.

Streaming interface

The streaming variant carries state through the CoreML interface; the speaker-cache update runs host-side between calls.

Inputs: chunk [1,112,128], chunk_lengths [1], spkcache [1,188,512], spkcache_lengths [1], fifo [1,40,512], fifo_lengths [1]

Outputs: speaker_preds_out [1,242,4], chunk_pre_encoder_embs_out [1,14,512], chunk_pre_encoder_lengths_out [1]

The pipeline contains two sub-models: PreEncoder (mel pre-encode + state concat) and Head (FastConformer + Transformer + sigmoid heads).

Usage

swift
// Whole-buffer diarization
let diarizer = try await SortformerDiarizer.fromPretrained()
let result = diarizer.diarize(audio: samples, sampleRate: 16000)

// Incremental streaming: push PCM in any size, stable speaker slots
let session = try await SortformerStreamingSession.fromPretrained()
let snapshot = try session.push(audio: samples)
let final = try session.finish()
bash
speech diarize meeting.wav --engine sortformer

Source

Links