Nemotron-3 Diarization + X-ASR, merged into one GGUF
A single GGUF file carrying both models used by nemo-x-asr-diarizer for on-device streaming transcription and speaker attribution: text from X-ASR, speaker turns from Nemotron-3 Diarization, one audio timeline, CPU only.
This file is a packaging merge. No weight was retrained, requantised, reordered within a tensor, or otherwise altered. Every tensor payload is byte-identical to its source, and that is verified rather than asserted — see Provenance and verification below.
Provenance and licensing
The bundle combines two independently licensed models. Both licences permit redistribution; the obligations they attach are discharged by the files in this repository and the attribution below.
| half | weights | base model | licence |
|---|---|---|---|
| Nemotron-3 Diarization | audio-cpp/Nemotron-3-Diarization-GGUF (nemotron-3-diarization-q8_0.gguf) | nvidia/Nemotron-3-Diarization | OpenMDW-1.1 — copy at LICENSE-OpenMDW-1.1.txt |
| X-ASR zh-en | cstr/x-asr-zh-en-GGUF (x-asr-zh-en-q8_0.gguf) | GilgameshWind/X-ASR-zh-en | Apache-2.0 — copy at LICENSE-Apache-2.0.txt |
OpenMDW-1.1 requires that a distribution retain a copy of the agreement and all applicable notices of
origin; the full text is included above and the origin of every component is listed here. Apache-2.0 requires
the licence and attribution, likewise included. The license metadata field is other because a single
artefact carries two licences rather than one.
Layout
The diarizer's tensors keep the native namespace, so its loader reads this file unchanged. The ASR half is
namespaced under asr., and the loader is taught to try the prefixed name first:
362 tensors native namespace (encoder.*, preprocessor.*, sortformer_modules.*) Nemotron-3 Diarization
966 tensors asr.* (z.*, emb.*, dec.*, join.*) X-ASR
40 metadata entries
X-ASR is a streaming Zipformer2 transducer (chunk sizes 160/480/960/1920 ms, selected by
CRISPASR_XASR_CHUNK_MS); Nemotron-3 Diarization is a Sortformer-style AOS model with up to eight speakers,
returning speaker turns and timestamps rather than words.
Usage
nemo-x-asr-diarizer \
--models-bundle nemotron3-diar-plus-x-asr.gguf \
--audio input.wav --threads 2 --windows
--models-bundle is shorthand for pointing both --xasr-model and --diar-model at this file and looking the
ASR up under the asr. prefix. The two-file layout remains supported and is what the upstream tools default
to. On the phone, the bundle measured neutral against two files: one mmap and one artefact to ship, no
throughput difference.
The host project builds this file with
tools/merge_gguf.py:
python3 tools/merge_gguf.py out.gguf \
--model =nemotron-3-diarization-q8_0.gguf \
--model asr.=x-asr-zh-en-q8_0.gguf
Provenance and verification
- 1328 / 1328 tensor payloads are byte-identical to the two source files, checked by an independent
re-parse of source and bundle (
tools/gguf_inventory.pyplus a per-tensor byte comparison). - Byte identity of behaviour: running the four gate clips from this bundle reproduces the reference
transcript hash
192184ebcd54977eexactly, with unchanged WER (gate_ms_v2 0.1765, holdout_en 0.2364, holdout_zh 0.0791), attribution (0.0779 of 77) and DER-lite (23.28%). - Types are self-checked by density, because a GGUF type id is easy to misread and the density cannot lie: Q8_0 at 8.50 bits/element, F32 at 32.00, BF16 and F16 at 16.00.
What the composite is for
Phone CPU, streaming, one process and one audio timeline: 16 kHz in, windowed text with speaker labels out.
Measured on a Dimensity 1300 with taskset C0 (two A78 cores) at 0.47 → 0.269 RTF against the
pre-optimisation baseline, byte-identical transcripts throughout, with first-partial latency improved from
0.32 s to 0.25 s. The gains came from removing work that was never model work — a mel filterbank that was
multiplying 98.5% zeros in software quad precision, a 4,000-node graph rebuilt every decode step, and a 10.2 MB
matvec streamed once per encoder frame. See the project's docs/ for the measurements behind each.