Runs entirely in the browser using WebGPU — no audio is uploaded to a server.
Português brasileiro, 100% no navegador. Encoder INT4 (MatMulNBits, block 32, simétrico) + decoder/joint FP, exportados do checkpoint ottema/nemotron-3.5-asr-ptbr e compatíveis com o contrato ONNX do runtime nemotron-asr-webgpu (onnxruntime-web + WebGPU). O áudio nunca sai do dispositivo.
Brazilian Portuguese ASR running entirely in the browser via ONNX Runtime Web + WebGPU. INT4 weight-only quantized encoder (block-wise MatMulNBits), FP decoder/joint, cache-aware streaming at 560 ms chunks. No audio leaves the device.
Artefatos
Arquivo
Tamanho
Execução
encoder.onnx + encoder.onnx.data
650 MiB
WebGPU (INT4 b32 sym, 219 MatMulNBits)
decoder.onnx + decoder.onnx.data
57 MiB
WASM/CPU (LSTM 2×640)
joint.onnx + joint.onnx.data
36 MiB
WASM/CPU
vocab.txt, tokenizer.json
—
13088 tokens (blank = 13087)
Contrato do encoder (chunk 560 ms): inputs audio_signal [1,65,128], length, cache_last_channel [1,24,56,1024], cache_last_time [1,24,1024,8], cache_last_channel_len, lang_id (pt-BR = 12) → outputs outputs [1,7,1024], encoded_lengths, cache_*_next. Idêntico ao de onnx-community/nemotron-3.5-asr-streaming-0.6b-onnx-int4.
Resultados (FLEURS pt-BR test, 100 amostras, WER normalizado)
Modelo
WER
Δ vs NeMo
NeMo FP32 offline (referência)
11.18%
—
ONNX FP32 streaming
~11.2%
≈ 0
ONNX INT4 b32 sym streaming (este repo)
11.85%
+0.67pp
NVIDIA base multilíngue zero-shot FP (card Ottema)
13.86%
—
O INT4 PT-BR preserva praticamente todo o ganho do fine-tuning e continua ~2pp melhor que o modelo base multilíngue em FP.
Estudo de quantização (mesma avaliação)
Config
WER
Δ
Tamanho encoder
INT4 block 128, assimétrico
12.91%
+1.72pp
577 MiB
INT4 block 32, assimétrico
11.98%
+0.80pp
628 MiB
INT4 block 32, simétrico
11.85%
+0.67pp
621 MiB
A ablação por camadas (manter layers 0–1 e/ou 22–23 em FP32) mostrou degradação distribuída pelo encoder — excluir 4 layers + prompt kernel recuperava apenas 0,63pp por +260 MiB. A escolha de esquema (block size + simetria) foi responsável por ~1pp de WER sem custo de tamanho.
Uso no navegador
Runtime de referência: nemotron-asr-webgpu — basta apontar CONFIG.BASE (em src/shared.js) para este repo:
e usar lang_id = 12 (pt-BR). Modos File / Record / Live (streaming com VAD). Requer browser com WebGPU (Chrome/Edge desktop, Chrome Android, Safari 18+); fallback WASM/CPU funciona, mais lento. Os pesos são baixados uma vez e persistidos via Cache API.
Validado em: desktop (WebGPU e WASM) e Redmi Note 14 Pro (Chrome Android, WebGPU) com streaming de voz em tempo real.
Exportação e validação
Pipeline .nemo → ONNX → INT4 com gates numéricos em cada etapa:
Exportação: wrapper sobre cache_aware_stream_step() do NeMo 2.8.0rc0 + prompt de idioma pós-encoder (one-hot 128 → prompt_kernel MLP 1152→2048→1024)
Gate FP32: cosine > 0.9999 entre PyTorch e ONNX em todos os tensores (encoder, decoder, joint)
Gate streaming: chunks de 560 ms encadeados vs offline — ΔWER ≈ 0 (11.99% vs 11.18% em 20 amostras)
Quantização: MatMulNBitsQuantizer (RTN), block 32, simétrico, apenas MatMuls do encoder