Speech and prompts¶
A script can talk back and it can ask. Text-to-speech (TTS) reads text aloud through your output device, so a command can say "shields up" or read out a status. The spoken prompt goes further: it speaks a question and waits for a spoken answer, which is the confirm-or-deny pattern without touching the keyboard.
All of this lives under amri.speech. TTS is on by default and needs no setup. If
no voice content is installed, speech degrades to silence and logs one line, so a
script should not assume it was heard.
Speaking¶
amri.speech.speak(text[, opts]) queues an utterance and returns immediately. Speech
plays one utterance at a time, so back-to-back speak calls play in spoken order
rather than overlapping.
amri.speech.speak_sync(text[, opts]) speaks the same way but blocks the script until
the utterance is presented in turn. Use it when the next line depends on the words
having been said.
| Function | Effect |
|---|---|
amri.speech.speak(text[, opts]) |
Queue an utterance. Returns immediately. |
amri.speech.speak_sync(text[, opts]) |
Speak and block until the utterance plays in turn. |
amri.speech.stop() |
Stop the current utterance. |
amri.speech.speaking() |
Whether TTS is currently speaking. |
Options¶
opts is an optional table for speak and speak_sync:
| Key | Effect |
|---|---|
voice |
A voice name (not a path), as reported by amri.speech.voices() or an alias from your engine.toml [voices] table. An unknown name falls back to the default voice. |
volume |
Playback volume for this utterance. |
barge_in |
true cuts the current utterance, drops the queue, and plays now. |
Asking¶
amri.speech.ask(responses[, opts]) speaks nothing on its own: you speak first, then
call it to listen for one of a fixed set of responses. It blocks until one of them
is heard and returns that word, or returns nil when opts.timeout seconds pass with
no match. This is the confirm-or-deny primitive.
amri.speech.speak("Jettison cargo. Are you sure?")
local answer = amri.speech.ask({"confirm", "abort"}, {timeout = 8})
if answer == "confirm" then
amri.input.tap("j")
amri.speech.speak("Cargo away")
else
-- nil (timeout) or "abort" both cancel
amri.speech.speak("Cancelled")
end
The response set is constrained: only the listed words can be heard, which keeps a
confirmation reliable under game audio. A nil return means no answer arrived in
time and should be treated as a cancel.
Listening state¶
amri.speech.listen(on) does not capture free text. It mutes command listening when
on is false and resumes it when on is true. amri.speech.listening() returns
whether command listening is currently active. Use these to silence recognition during
a cutscene or a menu, then turn it back on.
amri.speech.listen(false) -- stop reacting to spoken commands
-- ... later ...
amri.speech.listen(true) -- resume
For free-form transcription (speaking arbitrary text into a document), use the
dictation window under amri.speech.dictate.*, which is a separate engine from the
command recognizer. See the listening modes page.
Voices¶
amri.speech.voices() returns a table of the installed voice names, the same names you
pass as opts.voice. The table is empty when TTS is unavailable, which is the check a
script uses before assuming it can speak.
-- Pick the first British voice if one is installed, else the default.
for _, name in ipairs(amri.speech.voices()) do
if name:find("^en_GB") then
amri.speech.speak("Ready", {voice = name})
break
end
end
TTS is configured in the [tts] table of your engine.toml. Setting enabled = false
there turns spoken output off, and a stripped-down install may ship without any voice
content. In both cases amri.speech.speak(...) becomes a silent no-op, so never rely
on audio alone to convey something the player must act on.
Speech can be silent
A profile is portable across machines that do not have your exact voice, and TTS
can be off entirely. Treat speak as best-effort output, and gate anything that
depends on being heard on amri.speech.voices() returning a non-empty list.
A runnable script¶
A confirm-before-firing command, saved beside the profile and pointed at with
script = "confirm_fire.lua":
-- confirm_fire.lua
amri.speech.speak_sync("Arming main gun")
local answer = amri.speech.ask({"fire", "hold"}, {timeout = 6})
if answer == "fire" then
amri.input.tap("space")
amri.speech.speak("Firing")
else
amri.speech.speak("Holding")
end
See also¶
- Functions: how a command calls into
amri.*. - API reference: every
amri.speech.*signature. - Listening modes: command listening and dictation.