Klang Pianissimo ONNX
ONNX versions of Klang Pianissimo, our Swedish speech recognition model. They run on an ordinary CPU with onnxruntime, without PyTorch or NeMo.
Versions
| Version | Download | CV test | FLEURS test | Klang Dialects | Speed, Intel | Speed, ARM | Speed, Mac | Memory, 30 s clip |
|---|---|---|---|---|---|---|---|---|
| Original fp32 | 2.51 GB | 4.46 | 6.51 | 4.85 | ||||
| int8 | 660 MB | 4.65 | 6.62 | 4.93 | 35ร | 63ร | 74ร | 1.5 GB |
| int4 | 515 MB | 4.63 | 6.58 | 5.06 | 12ร | 23ร | 37ร | 1.1 GB |
| fp16 | 1.28 GB | 4.47 | 6.48 | 4.89 | 18ร | 30ร | 55ร | 4.0 GB |
| fp32 | 2.56 GB | 4.46 | 6.48 | 4.89 | 18ร | 30ร | 55ร | 3.0 GB |
Word error rate (WER, %); lower is better. Speed is Real Time Factor (RTFx) measured on a 30-second clip. Benchmarked on the CPU with 4 threads on an Intel Xeon Platinum 8481C, 8 threads on a Google Axion (ARM) and 6 threads on an Apple M5 Pro. Memory was measured on the Intel Xeon.
On a Mac, the MLX versions run on the GPU and are about twice as fast.
Usage
Install onnx-asr:
pip install onnx-asr[cpu,hub]
Transcribe a 16 kHz mono WAV file:
import onnx_asr
model = onnx_asr.load_model("KlangAI/pianissimo-sv-onnx", quantization="int8")
print(model.recognize("audio.wav"))
Only the files for the chosen version are downloaded. Use quantization="int4" or "fp16", or leave it out for fp32.
With timestamps:
result = model.with_timestamps().recognize("audio.wav")
print(result.text)
for token, start in zip(result.tokens, result.timestamps):
print(f"{start:6.2f} {token}")
Long recordings
onnx-asr can split long recordings at pauses with voice activity detection:
vad = onnx_asr.load_vad("silero")
for segment in model.with_vad(vad).recognize("long.wav"):
print(f"[{segment.start:7.1f}s] {segment.text}")
Vocabulary
Supports custom vocabulary using our custom implementation of NeMo's phrase boosting. The implementation matches NeMo's results on the original model. Listing names and terms increases the chance that the model spells them correctly. Needs pip install sentencepiece.
import sys
from huggingface_hub import snapshot_download
path = snapshot_download(
"KlangAI/pianissimo-sv-onnx",
allow_patterns=["*.py", "tokenizer.model"],
)
sys.path.append(path)
import pianissimo_onnx
vocabulary = ["Klang AI", "Pianissimo", "RixVox", "Common Voice"]
pianissimo_onnx.boost(model, vocabulary)
print(model.recognize("audio.wav"))
Test results are on the main model card.
Files
| File | Contents |
|---|---|
encoder-model{.int8,.int4,.fp16,}.onnx |
Encoder. The fp32 weights are in encoder-model.onnx.data. |
decoder_joint-model{.int8,.int4,.fp16,}.onnx |
Decoder |
vocab.txt |
The 8,192 tokens, plus the blank token |
nemo128.onnx |
Converts audio to the 128-band spectrogram the encoder expects |
config.json |
Settings for onnx-asr |
How they were made
All versions are exported from the released checkpoint and keep its local attention (256 frames on each side).
- int8: weights and calculations in 8 bits. Before quantizing, part of the scale of each layer's input is moved into its weights (SmoothQuant), which makes the 8-bit version more accurate. The decoder's LSTM is stored in fp16.
- int4: weights in 4 bits, in groups of 32 with a scale and offset per group chosen with HQQ. Calculations are done in fp32. Plain rounding to 4 bits was 0.2 to 0.6 percentage points worse on every test set.
- fp16: weights stored in fp16.
The test sets and scoring are the same as on the main model card: 5,516 Common Voice v26 test clips, 758 FLEURS test clips, and the 1,804-recording clean set of Klang Dialects. WER is calculated over each whole set after lowercasing, replacing punctuation with spaces, and collapsing whitespace. All results come from onnxruntime 1.24.1 on the CPU.
License and citation
Released under CC BY 4.0, like the original model.
@misc{klang2026pianissimo,
title = {Klang Pianissimo},
author = {{Klang}},
year = {2026},
howpublished = {Hugging Face model repository},
url = {https://huggingface.co/KlangAI/pianissimo-sv}
}
- Downloads last month
- 615