Oído: Open-Vocabulary Speech Recognition on a $5 Microcontroller without a Neural Accelerator
Organizations: Lokutor (Hashing Works, S.L.L.), Madrid, Spain
Abstract
Speech recognition on low-cost microcontrollers is, in practice, limited to keyword spotting or a fixed list of commands. We present Oído, an inference engine that runs open-vocabulary English speech recognition entirely on an ESP32-S3 (240 MHz dual-core Xtensa LX7, 512 KB of SRAM, 8 MB of PSRAM, 16 MB of flash, no neural accelerator). Oído executes a 13M-parameter Conformer-CTC model with int8 weights, per-frame dynamic int8 activations and int8 attention on the chip's SIMD instructions, with a schedule designed around flash and PSRAM bandwidth. On LibriSpeech test-clean/test-other the on-device arithmetic reaches 3.70%/8.23% word error rate (WER), within 0.12 points of full precision, and 3.33%/7.15% with an on-chip 1.3M-parameter language model; a transducer head gives 2.99%/6.67% and an int4 variant fits in 8.3 MB. This is 2.3-2.8x fewer errors than the vendor's recognizer on the same chip, and fewer than Whisper tiny.en and Moonshine tiny in full precision on a laptop, including in real noise and reverberation. Measured on a physical board, the firmware runs at 1.97x the duration of the audio on one core, with transcripts identical to an instruction-exact emulator: accurate, but not yet real time (a 4 s command is transcribed about 8.7 s after it ends). The two-core schedule gives wrong results on silicon and is disabled. A streaming variant shows partial text while the speaker talks and delivers the final text 4.1-11.1 s after clips of 3.6-10.6 s (7.2-22.4 s in utterance mode) at 4.86%/11.03% WER; a Spanish model makes 34-60% fewer errors than multilingual Whisper tiny. Code and models are released.
Figures & tables
| Features | 80 log-mel, 25 ms window, 10 ms hop |
| Subsampling | 2 conv , stride 2, 176 ch 25 Hz |
| Encoder | 16 Conformer blocks, , FF 704 |
| Attention | 4 heads, relative position [ 9 ] |
| Convolution | depthwise, kernel 31, BatchNorm |
| Output | CTC [ 19 ] , 1024 SentencePiece [ 27 ] + blank |
| Parameters | 13 M (int8: 14.0 MB; int4: 8.3 MB) |
| System | Size | clean | other |
|---|---|---|---|
| Conformer-CTC S, fp32 (reference) | 52 MB | 3.68 | 8.11 |
| Oído int8, greedy | 14.0 MB | 3.70 | 8.23 |
| Oído int8 + GRU LM | 15.3 MB | 3.33 | 7.15 |
| Oído int4 (QAT), greedy | 8.3 MB | 4.61 | 9.98 |
| Oído int4 + GRU LM | 9.6 MB | 3.78 | 8.43 |
| Oído Transducer int8, greedy | 15.5 MB | 2.99 | 6.67 |
| System | CV | Vox | AMI | PS | E22 |
|---|---|---|---|---|---|
| Oído, host build of the on-chip engine | |||||
| int8, greedy | 11.4 | 9.3 | 20.2 | 11.6 | 22.4 |
| int8 + LM (books) | 10.4 | 9.2 | 20.4 | 12.2 | 21.6 |
| int8 + LM (books + transcripts) | 10.1 | 9.0 | 19.0 | 11.0 | 20.8 |
| int4 + LM (books) | 11.8 | 11.1 | 20.2 | 10.7 | 21.1 |
| Transducer int8 | 9.6 | 8.2 | 19.2 | 11.6 | 21.0 |
| Condition | T | C | C+LM | M | W | V |
|---|---|---|---|---|---|---|
| Clean | 2.5 | 3.5 | 3.3 | 4.3 | 5.6 | 9.1 |
| Car, 10 dB | 2.6 | 3.6 | 3.3 | 4.3 | 5.8 | 9.1 |
| Car, 5 dB | 2.7 | 3.6 | 3.2 | 4.4 | 5.9 | 9.3 |
| Kitchen, 10 dB | 3.0 | 4.0 | 3.6 | 5.1 | 6.6 | 10.7 |
| Kitchen, 5 dB | 3.3 | 4.7 | 4.2 | 6.1 | 7.5 | 12.4 |
| Living room, 10 dB | 3.2 | 4.4 | 4.0 | 5.8 | 6.7 | 11.5 |
| Mode | clean | other | robust. | final text ‡ |
|---|---|---|---|---|
| Utterance mode (original) | 3.33 | 7.15 | 7.5 | 6.9–21.3 s |
| Streaming, , greedy | 6.27 | 13.06 | – | – |
| Streaming, | 4.86 | 11.03 | 9.0 | 4.1–11.1 s |
| Streaming, | 6.14 | 13.23 | – | – |
| Same model, full context | 3.43 | 7.78 | 6.2 | 7.2–22.4 s |
| System | CV | MLS | Vox | FLEURS |
|---|---|---|---|---|
| Oído + LM (host build) | 13.3 | 10.6 | 15.5 | 11.3 |
| Oído greedy | 20.3 | 14.2 | 20.0 | 16.9 |
| Oído streaming + LM | 15.2 | 12.1 | 16.3 | 12.8 |
| Whisper tiny (laptop) | 33.0 | 21.5 | 28.7 | 17.1 |
| Model | clips | RTF | range | = host |
|---|---|---|---|---|
| CTC int8 (released) | 27 | 1.97 | 1.91–2.02 | 22/27 |
| CTC int4 | 10 | 1.76 | 1.73–1.83 | 8/10 |
| Transducer int8, no LM | 10 | 1.89 | 1.88–1.91 | 10/10 |
| Stream. model, utterance | 12 | 2.04 | 1.98–2.11 | 12/12 |
| Stream. model, | 12 | 1.96 | – | 10/12 |
| Spanish, utterance | 12 | 2.06 | 1.98–2.13 | 9/12 |
| Stage | Minstr/s | Mcyc/s | cyc/instr |
|---|---|---|---|
| log-mel | 10 | 14 | 1.48 |
| conv0 | 14 | 20 | 1.45 |
| im2col | 6 | 20 | 3.66 |
| matrix products | 103 | 216 | 2.09 |
| layernorm | 7 | 15 | 2.07 |
| activation quant | 15 | 32 | 2.16 |
| Step | G instr. | |
|---|---|---|
| Baseline int8 engine | 9.82 | – |
| + merged attention score pass | 9.63 | 1.9% |
| + x-stationary GEMM for | 9.39 | 2.5% |
| + K-split, batched front end † | 9.66 | +2.9% |
| + int8 positional table, buffer aliasing | 9.58 | 0.8% |
| + fused im2col quantization | 9.29 | 3.0% |
| Profile | RTF | text after clip |
|---|---|---|
| CTC int8 + LM, utterance mode | 1.97 | 6.9–7.4 s |
| CTC int4 + LM, utterance mode | 1.76 | 6.2–6.7 s |
| Transducer int8, utterance mode | 1.89 | 7.0 s † |
| Streaming model, utterance mode | 2.04 | 7.2–7.6 s |
| Streaming model, streaming | 1.96 | 4.1–4.2 s |
Automatic Speech Recognition
Automatic speech recognition converts spoken language into text across speakers, languages, domains, and recording conditions.
See all 480 papers