VieGem-ASR 🇻🇳💎

VieGem-ASR

Fast Vietnamese and Vietnamese–English speech recognition: a 359M-parameter streaming CTC model on Google's EmbeddingGemma 2 audio encoder. Inspired by Quan Nguyen's QUAN-Transcribe-1.0.

  • Fast: about 3,500× real time on one H100 (batched, greedy); streams in 0.48 s chunks with no look-ahead.
  • Vietnamese: mean WER 6.34 over 8 common test sets (5.29 with the included n-gram LM).
  • Code-switching: ViMedCSS WER 14.3; 66% of English terms written exactly.

Demo

Results

Vietnamese test sets

WER %, lower is better, greedy unless marked "+ LM". VieGem-ASR, QUAN-Transcribe-1.0 and Qwen3-ASR-0.6B were run by us with one normalizer; † = reported in the QUAN-Transcribe-1.0 model card (our scorer matches its numbers within 0.1).

Test set What it contains VieGem-ASR VieGem-ASR + LM QUAN-Transcribe-1.0 Qwen3-ASR-0.6B Gemini-Flash-3.8 † ElevenLabs Scribe v2 † PhoWhisper-large † Whisper large-v3 †
VIVOS read speech, quiet room 6.63 4.78 7.52 10.22 9.36 9.14 4.52 9.18
FLEURS vi read Wikipedia sentences 7.33 5.85 7.88 8.40 5.90 5.60 5.31 7.09
Common Voice 17 read, crowd-sourced microphones 8.61 6.21 9.69 16.07 10.30 10.50 9.12 18.43
PhoAudiobook audiobooks 1.39 1.04 1.39 3.23 1.60 1.45 0.87 1.85
LSVSC large mixed-domain corpus 5.16 4.71 5.35 7.78 5.70 6.25 6.81 13.96
Bud500 mixed domains, tightly cut clips 3.08 2.75 1.82 6.79 1.80 3.15 9.51 64.03
GigaSpeech2 vi YouTube, spontaneous 9.50 8.52 11.60 11.37 10.70 10.50 10.14 14.19
ViMD dialects of 63 provinces 9.05 8.46 9.84 13.98 10.00 10.05 11.38 15.56
Mean of the 8 6.34 5.29 6.89 9.73 6.92 7.08 7.21 18.04

Bold = best greedy result per row. Text is lowercased, without punctuation, numbers as words.

Vietnamese–English code-switching (ViMedCSS)

System Test WER Hard WER
Whisper-large-v3 (paper) 34.47 39.35
PhoWhisper-large (paper) 31.24 37.37
PhoWhisper-small + AG, fine-tuned (paper) 23.67 33.73
QUAN-Transcribe-1.0 22.26 26.56
VieGem-ASR 14.30 21.08
VieGem-ASR + LM 13.00 19.84

"Paper" = numbers from the ViMedCSS paper (its own normalization, so approximate).

Streaming and speed

  • Streaming (0.48 s chunks): VIVOS 8.73, CV17 10.84, FLEURS 9.02, LSVSC 5.84, ViMD 10.00, ViMedCSS 15.99.
  • A 10-minute video is transcribed in 0.49 s on one H100 (median of 20 runs, ~1,220× real time).

Usage

import torch, soundfile as sf
from transformers import AutoTokenizer
from asr.model import CTCModel, ModelConfig, greedy_decode     # asr/ folder of this repo
from asr.text import Units

ck = torch.load("viegem_asr.pt", map_location="cpu")
cfg = ModelConfig.from_dict(ck["model_config"])
units = Units(ck["gemma_ids"])
tok = AutoTokenizer.from_pretrained(cfg.encoder_id)               # google/embeddinggemma-2 (accept its terms)
model = CTCModel(cfg, units.gemma_ids)
model.load_state_dict(ck["model"], strict=False)
model = model.cuda().eval()

wav, sr = sf.read("audio.wav", dtype="float32")                  # 16 kHz mono, ≤ 30 s
x = torch.from_numpy(wav)[None].cuda()
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
    logits, lens = model(x, torch.tensor([x.shape[1]], device="cuda"), streaming=False)  # streaming=True: 0.48 s chunks
print(units.decode(tok, greedy_decode(logits, lens)[0]))

With the LM (pip install kenlm):

from asr.lm_decode import LMDecoder

words = open("lm/viegem_lm.unigrams.txt", encoding="utf-8").read().split()
dec = LMDecoder("lm/viegem_lm.bin", unigrams=words, alpha=0.35, beta=1.5)
pieces = ["", ""] + tok.convert_ids_to_tokens(units.gemma_ids)
lp = torch.log_softmax(logits[0, : lens[0]].float(), -1).cpu().numpy()
print(units.decode(tok, dec.decode(lp, pieces, beam_width=32)))

Model

  • Encoder: EmbeddingGemma 2 audio tower (12 conformer layers, 25 frames/s); top 4 layers fine-tuned.
  • Reader: layer mix + 6 transformer blocks (d=768) with chunked attention, so one model serves offline and streaming.
  • Head: 21,031 Gemma tokens (Vietnamese, English, single characters), initialized from Gemma's text embeddings.
  • Files: viegem_asr.pt (fp16 weights, 311 MB), asr/ (code), lm/ (4-gram KenLM from our training transcripts, 71 MB), demo/.

Training data

About 5,800 hours, every set filtered against all test and dev sentences.

Type Sources Hours
Audiobooks PhoAudiobook, InfoRe2 ~1,900
Social media and YouTube VietSpeech, viVoice, GigaSpeech2 (subset), VietSuperSpeech ~2,820
Mixed domains Bud500, VLSP2020, LSVSC, ViMD, FPT FOSD, InfoRe1, FLEURS, Common Voice 17 ~780
English LibriSpeech-100 ~100
Vietnamese–English (medical) ViMedCSS ~23

Limitations

  • Output is lowercase, without punctuation; numbers are written as words.
  • Clips cut in the middle of a word (as in Bud500) lose the last word more often.
  • English is meant for terms mixed into Vietnamese; plain English is weak (LibriSpeech test-clean 10.7).

License

Non-commercial research use (CC-BY-NC-SA-4.0), because the training data includes Bud500, viVoice and PhoAudiobook. Use must also follow the Gemma Terms of Use and Prohibited Use Policy.

Credits

Google DeepMind (EmbeddingGemma 2); Quan Nguyen (QUAN-Transcribe-1.0, the inspiration for this work); the authors of VIVOS, Common Voice, FLEURS, LSVSC, ViMD, Bud500, PhoAudiobook, VietSpeech, viVoice, GigaSpeech2, VietSuperSpeech, VLSP2020, FPT FOSD, InfoRe, ViMedCSS and LibriSpeech. ViMedCSS baselines: Nguyen et al., LREC 2026.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for 5CD-AI/VieGem-ASR

Finetuned
(124)
this model

Space using 5CD-AI/VieGem-ASR 1