CoolFace
Modelpublic

jasonzhang76/Qwen3-ASR-0.6B-ONNX-CPU

sourceHugging Faceapache-2.0updated 5mo agoView on Hugging Face
0likes12downloads
Model Card

Qwen3-ASR-0.6B — Full ONNX CPU

Run Qwen3-ASR on any CPU. No GPU. No PyTorch.

Self-contained ONNX pipeline for Qwen3-ASR-0.6B. Encoder and decoder both run on ONNX Runtime with INT8 quantized decoder. Long audio is automatically split at silence boundaries — no manual chunking needed.

Highlights

  • —Zero GPU, Zero PyTorch — onnxruntime + librosa + tokenizers only
  • —Real-time on 8W CPU — RTF 0.71x with VAD chunking on Intel N100
  • —3x realtime on desktop — RTF 0.32x (INT8)
  • —Self-contained — all weights + tokenizer included
  • —30 languages — same multilingual coverage as the original
  • —Long audio support — automatic silence-based splitting with --chunk-sec
  • —Bit-exact encoder — cosine similarity 1.000000 vs PyTorch reference

Quick Start

bash
git clone https://huggingface.co/Daumee/Qwen3-ASR-0.6B-ONNX-CPU
cd Qwen3-ASR-0.6B-ONNX-CPU

python3 -m venv .venv && source .venv/bin/activate
pip install onnxruntime librosa soundfile tokenizers

# Short audio
python onnx_inference.py test_audio/librispeech_1_1089_1.wav

# Long audio (auto-chunked at silence)
python onnx_inference.py long_meeting.wav --chunk-sec 30

# Specify language + JSON output
python onnx_inference.py audio.wav --language Korean --json

Benchmarks

Intel N100 (4 cores, 8W TDP)

Short audio — 13 LibriSpeech test-clean samples, INT8 decoder:

AudioRTFEncoderPrefillDecodeTokens
12.4s0.97x3.8s3.2s5.1s49
11.6s0.84x2.4s3.0s4.3s39
10.6s0.86x2.3s2.9s3.8s32
10.4s0.92x1.6s2.5s4.5s41
6.6s1.08x1.5s2.3s3.4s27
3.3s1.36x1.3s1.4s1.7s15
Audio > 10s achieves realtime or faster. Decoder: ~100ms/token (INT8).

Long audio — production deployment with VAD chunking (Docker, 2 threads):

InputChunksAvg RTFPeak Memory
600s (10 min)190.71x5.7 GB
Without chunking, 10-min audio consumes 15GB+ and gets OOM-killed. With 30s chunks, prefill cost is amortized → RTF drops well below 1.0x.

Desktop x86_64:

ModeRTFNotes
ONNX FP320.63xNo quantization
ONNX INT80.32x3x realtime

Architecture

StageRuntimeComponentDetails
1librosaMel Spectrogram16kHz → 128-bin log-mel
2ONNX Runtimeencoder_conv.onnx3x Conv2D, 8x downsample
3ONNX Runtimeencoder_transformer.onnx18 Transformer layers + Projector (896→1024)
4NumPyembed_tokens.binFuse audio features into prompt
5ONNX Runtimedecoder_init.int8.onnxPrefill → logits + KV cache
6ONNX Runtimedecoder_step.int8.onnxAutoregressive decode until EOS
EncoderDecoder
QuantizationFP32Dynamic INT8
Format2 models (conv + transformer)2 models (init + step)
KV Cache—ONNX I/O

Long Audio

Audio longer than 45s is automatically split at silence boundaries using RMS energy detection. No external VAD model needed.

bash
python onnx_inference.py meeting.wav                  # 30s chunks (default)
python onnx_inference.py meeting.wav --chunk-sec 20   # 20s chunks, less memory

Split range scales with target: min = target/2, max = target×1.5. The split point is the silence frame nearest to the target length.

Files

FileSizeDescription
onnx_inference.py—Inference CLI (single file, no deps beyond pip)
tokenizer.json11 MBSelf-contained tokenizer
onnx_models/encoder_conv.onnx48 MBConv block
onnx_models/encoder_transformer.onnx669 MBTransformer + Projector
onnx_models/decoder_init.int8.onnx571 MBPrefill (INT8)
onnx_models/decoder_step.int8.onnx571 MBDecode step (INT8)
onnx_models/embed_tokens.bin622 MBToken embeddings

Total: ~2.5 GB

Model

ComponentParamsDetails
Audio Encoder~310Md=896, 18 layers, 14 heads
Projector~1.7MLinear 896→1024
LLM Decoder~470Md=1024, 28 layers, GQA 16Q/8KV
Total~782M

30 languages: Chinese, English, Cantonese, Japanese, Korean, Arabic, German, French, Spanish, Portuguese, Indonesian, Italian, Russian, Thai, Vietnamese, Turkish, Hindi, Malay, Dutch, Swedish, Danish, Finnish, Polish, Czech, Filipino, Persian, Greek, Romanian, Hungarian, Macedonian

Technical Notes

  • —Attention: Original cu_seqlens windowed attention only works with flash_attention_2. CPU uses eager mode (all-to-all). ONNX export matches this.
  • —Weight tying: embed_tokens = lm_head in original. In ONNX, separated — embed_tokens.bin for input, lm_head baked into decoder.
  • —KV Cache: [num_layers, batch, kv_heads, seq_len, head_dim] — init outputs, step extends.
  • —MRoPE: Layout [24,20,20]. For ASR (no vision), all 3 dims share the same position IDs.

Dependencies

onnxruntime
librosa
soundfile
tokenizers

No PyTorch. No transformers. No CUDA.

Acknowledgements

Decoder ONNX export architecture inspired by andrewleech/qwen3-asr-onnx.

References

License

Code: Apache 2.0. Model weights: original license.