Offline continuous speech recognition with wake word support, custom phrases, and real-time transcription using sherpa-onnx models on ARC Windows.
How to add the Sherpa-ONNX Speech To Text robot skill
- Load the most recent release of ARC (Get ARC).
- Press the Project tab from the top menu bar in ARC.
- Press Add Robot Skill from the button ribbon bar in ARC.
- Choose the Audio category tab.
- Press the Sherpa-ONNX Speech To Text icon to add the robot skill to your project.
Don't have a robot yet?
Follow the Getting Started Guide to build a robot and use the Sherpa-ONNX Speech To Text robot skill.
How to use the Sherpa-ONNX Speech To Text robot skill
Offline speech recognition with the open source sherpa-onnx toolkit from the Next-gen Kaldi team. It runs a neural network model on the computer ARC is running on, with no account, no cost per phrase and no internet connection once the model has been downloaded.
Unlike the cloud engines, which record a few seconds and send them away, this robot skill holds the microphone open and recognizes continuously. It answers in a fraction of a second and costs nothing to leave running all day - but it also hears every word said anywhere near the robot, which is why it has a wake word.
Unlike ARC's own Speech Recognition robot skill, it is not limited to a list of phrases. It can recognize anything that is said and put it in a variable, which is what a conversational robot skill downstream wants, and it will still run scripts from a phrase list if you give it one.
It does not do text to speech. Pair it with a speech synthesis robot skill if the robot should also talk.
Requirements
- ARC on Windows.
- An internet connection the first time a model is used, to download it. After that, none.
- Disk space for the model: 30MB to 640MB depending on the one chosen.
- A microphone on this computer. Choose which one in the configuration.
- Only one instance per project.
Getting started
- Add the robot skill to the project. It starts with a small streaming English model selected and begins downloading it (57MB) straight away, and it is listening within a minute.
- Say one of the example phrases - "robot turn left". It appears in the log with how closely it matched.
- Open the configuration to change the phrases, choose a different model, or turn on the wake word.
Models are shared by every project on the computer and are only ever downloaded once. They are kept
in Documents\ARC\Speech Models\Sherpa-Onnx - or in ProgramData\ARC\Speech Models\Sherpa-Onnx
when the Windows user name has accented or non-Latin characters, which the model loader cannot open.
The configuration shows the exact folder and has a button to open it. Delete a model's folder to
remove it.
Choosing a model
There are two kinds, and the difference is the one you will notice:
- Streaming models recognize while you speak. The text appears in the window word by word, and the answer is there the moment you stop. Best for commands and for a robot that should feel responsive.
- The others wait until you stop speaking, then recognize the whole utterance at once. They are usually more accurate, and add punctuation and capitals (which are removed by default). A small voice activity detector (Silero, 2MB) decides where each utterance starts and ends; it is downloaded with the model.
| Model | Kind | Download | Good for |
|---|---|---|---|
| English - Kroko streaming | Streaming | 57MB | The default. Commands and conversation |
| English - Zipformer streaming | Streaming | 310MB | More accurate streaming English on long sentences |
| German / French / Spanish - Kroko streaming | Streaming | 57-124MB | The same, in those languages |
| Chinese + English - Zipformer streaming | Streaming | 511MB | Mandarin and English, even mixed in one sentence |
| English - Moonshine tiny / base | Whole utterance | 30MB / 111MB | Short commands on small computers |
| English - Parakeet TDT 110M | Whole utterance | 108MB | Very accurate for its size |
| English - Parakeet TDT 0.6B v2 | Whole utterance | 482MB | The most accurate English here. Wants a desktop processor |
| European - Parakeet TDT 0.6B v3 | Whole utterance | 487MB | 25 European languages, detected automatically |
| Whisper tiny.en / base.en / small.en | Whole utterance | 118-636MB | OpenAI Whisper, English |
| Multilingual Whisper tiny / base / small | Whole utterance | 116-639MB | 99 languages. Set Language, or leave it empty to detect it |
| Asian + English - SenseVoice | Whole utterance | 166MB | Mandarin, Cantonese, English, Japanese, Korean |
Any other sherpa-onnx speech recognition model can be used too: download and extract one from https://github.com/k2-fsa/sherpa-onnx/releases/tag/asr-models, choose Custom model folder, enter the folder and pick its kind. The files are found by name (encoder, decoder, joiner, tokens.txt and so on), and int8 copies are preferred when a model ships both.
The window
- The status says what the robot skill is doing: Downloading or Unpacking with a percentage, Loading model, Listening, Hearing speech, Robot is talking, Paused or Error.
- Under it is the model that is loaded, or the reason it could not be.
- The words being spoken appear in italics as they are recognized, with streaming models.
- The level bar is the microphone. It turns red while the robot skill is paused or while the robot's own voice is being ignored. If it never moves while you speak, the problem is the microphone, not the model.
- Pause stops the robot skill acting on what it hears. The model stays loaded, so unpausing is instant.
- With a wake word configured, Wake and Sleep do by hand what the wake word does by voice, and the label between them counts down how long the robot stays awake.
- The log holds the last 200 lines: model loading and how long it took, every phrase with how closely it matched, wake words, and anything that went wrong.
Wake word
Because the engine hears everything, all the time, a wake word is what stops every stray sentence in the room from being a command.
There is no second recognizer and no extra processor cost. The wake word is matched against the text that was already recognized, which means:
- it can be any phrase, in any language the model knows, not a keyword from a fixed list;
- it still counts when the model mishears a letter or two;
- several alternatives can be given, one per line, so people have more than one way to get the robot's attention;
- the wake word and a command can arrive in the same breath. "Robot, turn left" wakes the robot and turns left, with the wake word taken off the front. Turn Accept the wake word and a command inone breath off to require a pause instead.
After the wake word the robot stays awake for Stay awake for (seconds), so a conversation does not need the wake word in front of every sentence. Set it to 0 for one command per wake word. With Every command starts the timer again on, the robot keeps listening as long as somebody keeps talking to it.
Match threshold is the one to tune. A short wake word wants a high threshold, because short words resemble each other - if "robot" keeps waking on "rowboat", either raise the threshold or use a longer wake word such as "hey robot".
Phrases and scripts
| When | What runs |
|---|---|
| A phrase in the list is heard | That phrase's script, then anything recognized |
| Something is heard that is not in the list | nothing in the list matched, then anything recognized |
| The phrase list is empty | anything recognized, for everything that is heard |
| Somebody starts talking | somebody starts talking, before anything has been recognized |
| The wake word is heard | the wake word is heard |
| The wake word timeout runs out | it goes back to sleep |
Phrases are matched loosely rather than compiled into a grammar, because none of these models can be
restricted to one. Everything is recognized and then compared with the list: the phrase may be at the
start of a longer sentence ("turn left please" matches turn left), and small mistakes are forgiven
according to Phrase match threshold. How close the match was becomes the confidence.
Leave the phrase list empty to have everything that is heard go into the variables and run the anything recognized script - that is the setup for feeding a conversational robot skill.
Global variables
| Variable | Holds |
|---|---|
$SherpaPhrase |
The recognized text. When a phrase in the list matched, this is the phrase as it is written in the list, so a script can compare against it reliably. Otherwise it is what was actually heard. |
$SherpaConfidence |
How closely it matched, 0 to 1. Always 1 when there is no phrase list, because free text cannot be wrong. |
$SherpaPartial |
The sentence being spoken, while it is being spoken. Streaming models only. |
$SherpaAwake |
True while the robot is acting on what it hears. |
Any of them can be renamed, or emptied to not set it at all.
Configuration
Model
| Setting | Meaning |
|---|---|
| Model | From the list above, or Custom model folder. Default English - Kroko streaming. |
| Download / Stop | Fetch the selected model now, or stop a download. |
| Open models folder | Where the models are kept, shared by every project. |
| Folder / Model kind | Only for a custom model: where its files are, and what kind it is. |
| Language | Only for Whisper and SenseVoice. Whisper takes a code such as en, de or fr, or empty to detect it. SenseVoice takes auto, zh, en, ja, ko or yue. |
| Threads | Processor threads the recognizer may use. Default 2. More makes the large models answer faster on a desktop with cores to spare. |
| Use the int8 files | Use a model's int8 quantized files when it ships both. A quarter of the size, faster, nearly as accurate. Default on. |
| Download the model by itself | Off means nothing is downloaded until you press Download. Turn it off on a metered connection. Default on. |
Recognition
| Setting | Meaning |
|---|---|
| End of speech silence (ms) | The pause that counts as "they have finished". 800 suits commands. Raise it to about 1200 if long sentences keep being cut in half; lower it to about 500 if the robot feels slow. |
| Longest utterance (seconds) | Anything longer is cut into pieces. Whisper cannot take more than 30. Default 15. |
| Voice detection threshold | Only for the models that are not streaming. Raise it in a noisy room, lower it for a quiet voice or a distant microphone. Default 0.5. |
| Phrase match threshold | How close what was heard has to be to something in the phrase list. 1.00 is word for word. Default 0.75. |
| Remove punctuation | Phrase lists are written without it, and Whisper and Parakeet add it. Default on. |
| Make the text lower case | What ARC's own speech recognition does. Default on. |
| Device | Which microphone to listen to. |
| Ignore the microphone while the robot is talking | So the robot does not answer its own text to speech. Default on. |
| Keep ignoring it for (ms) after | The tail after the robot stops talking. Audio is handed to the speaker before it has actually been heard - a connected EZB has most of a second of its own buffering behind it - so without a tail the end of every sentence is still heard. Default 750. |
Pausing
A pause phrase and a resume phrase let the robot be told out loud to stop and start listening. Setting a resume phrase keeps the engine recognizing while the robot skill is paused, so that it can hear it - which costs processor time. With no resume phrase, pausing stops the decoding altogether.
Control commands
| Command | What it does |
|---|---|
PauseListening |
Stop acting on what is heard. The model stays loaded. |
UnpauseListening |
Start again. |
TogglePause |
Pause if listening, listen if paused. |
GetPause |
Returns true when paused. |
Wake |
Wake the robot without the wake word, and keep it awake until Sleep. |
Sleep |
Stop acting on what is heard until the wake word is said again. |
GetAwake |
Returns true when the robot is acting on what it hears. |
GetLastHeard |
The last thing recognized, whether or not it matched a phrase or the robot was awake. |
GetText |
Waits for the next thing said and returns it. No scripts run and no variables are set for that utterance, and the wake word is not needed - for a script that asked a question and wants the answer. |
DownloadModel |
Download the selected model now. Returns straight away; watch the window. |
ReloadModel |
Unload and load the model again, after changing the model files on disk. |
Troubleshooting
| Symptom | Cause |
|---|---|
| Status stays Idle and the model line says not loaded yet | Automatic downloading is off. Press Download in the configuration. |
| Download fails | No internet connection, or github.com is blocked. The model can also be downloaded by hand from the sherpa-onnx releases page and used as a custom model. |
| Error: "sherpa-onnx could not load the model" | A custom model whose kind does not match its files. |
| Error: "onnxruntime.dll could not be loaded" | The robot skill folder is incomplete, or the Visual C++ runtime is missing. Re-install the robot skill. |
| The level bar never moves | The wrong recording device, or no microphone. Try Windows sound settings. |
| Level bar moves but nothing is recognized | For a model that is not streaming, lower Voice detection threshold. Check the model's language is the one being spoken. |
| Sentences are cut off in the middle | Raise End of speech silence (ms). |
| Answers feel slow | Choose a streaming model, lower End of speech silence (ms), or raise Threads. |
| The robot answers itself | Turn on Ignore the microphone while the robot is talking, and raise Keep ignoring it for (ms) after. |
| Phrases are heard but ignored | What was said is not close enough to a phrase. Lower Phrase match threshold, or add the wording you actually use to the list. |
| The robot acts on conversation that was not aimed at it | Turn on the wake word. |
| The wake word fires when nobody said it | Raise Match threshold, or use a longer wake word. |
See also
- sherpa-onnx - https://github.com/k2-fsa/sherpa-onnx
- The models - https://github.com/k2-fsa/sherpa-onnx/releases/tag/asr-models
