Edge-friendly speech recognition from IMBE vocoder parameters. Runs at 15x real-time on a Raspberry Pi 5.
Evaluated on LibriSpeech-IMBE speaker-split validation. The included 3-gram KenLM halves WER with minimal overhead.
Conformer-CTC, trained on ~1,220 hours of IMBE-encoded speech, 25 epochs.
1import onnxruntime as ort, numpy as np
2
3session = ort.InferenceSession("model_int8.onnx")
4stats = np.load("stats.npz")
5features = ((raw_params - stats["mean"]) / stats["std"]).astype(np.float32)
6log_probs, out_lengths = session.run(None, {
7 "features": features.reshape(1, -1, 170),
8 "lengths": np.array([features.shape[0]], dtype=np.int64),
9})
1import onnxruntime as ort, numpy as np
2from pyctcdecode import build_ctcdecoder
3
4session = ort.InferenceSession("model_int8.onnx")
5stats = np.load("stats.npz")
6
7VOCAB = list(" ABCDEFGHIJKLMNOPQRSTUVWXYZ'")
8labels = [""] + VOCAB
9decoder = build_ctcdecoder(
10 labels=labels,
11 kenlm_model_path="lm/3gram.bin",
12 unigrams=open("lm/unigrams.txt").read().splitlines(),
13 alpha=0.7, # LM weight — tuned on LibriSpeech-IMBE
14 beta=2.0, # word insertion bonus
15)
16
17features = ((raw_params - stats["mean"]) / stats["std"]).astype(np.float32)
18log_probs, out_lengths = session.run(None, {
19 "features": features.reshape(1, -1, 170),
20 "lengths": np.array([features.shape[0]], dtype=np.int64),
21})
22text = decoder.decode(log_probs[0, :out_lengths[0]], beam_width=100)