Skip to content
Shiny Controls v1.0 - The Ultra Control Suite for .NET MAUI & BlazorO...M...G!

Wake Word

Wake word detection enables a hands-free “Hey Siri” style experience. The service listens continuously for a keyword phrase, captures the user’s utterance that follows, and sends it to the AI automatically.

await aiService.StartWakeWord("Hey Copilot");

Once started, the service:

  1. Continuously listens for the wake word phrase
  2. When detected, captures the user’s utterance via speech-to-text
  3. Sends the utterance to the AI via TalkTo()
  4. If the turn carries questions, skips wake word detection and listens directly for the user’s reply (conversation continuation)
  5. Otherwise, loops back to listening for the wake word
aiService.StopWakeWord();

This cancels the background listening loop and returns the service to an idle state. The WakeWord property is cleared and IsWakeWordEnabled returns to false.

if (aiService.IsWakeWordEnabled)
{
Console.WriteLine($"Listening for: {aiService.WakeWord}");
}

When the AI asks a question, the wake word loop skips keyword detection and immediately listens for the user’s reply. This creates a natural back-and-forth without requiring the wake word after every response.

“Is that a question” is a typed signal, not a guess at the wording: the AI answers with a structured turn whose Questions collection drives the decision. When the model can’t produce one, the service falls back to checking whether the reply ends in ?.

The conversation continues as long as the AI keeps asking. Once a turn carries no questions, the loop returns to wake word detection.

An open microphone with nobody answering is a problem — the next unrelated thing said in the room becomes the answer. FollowUpTimeout bounds the wait:

aiService.FollowUpTimeout = TimeSpan.FromSeconds(30); // default is 20 seconds
aiService.FollowUpTimeout = null; // wait indefinitely

When it expires, PendingQuestions is cleared and the loop goes back to requiring the wake word.

If voice interruption is enabled and the user says a quiet word during TTS playback, the conversation breaks immediately and returns to wake word detection. See Voice Interruption below.

During text-to-speech playback, the service can listen for voice interruptions. This is controlled by the QuietWords property:

// Default quiet words: cancel, quiet, shut up, stop, nevermind, never mind, hush
// Customize:
aiService.QuietWords = ["stop", "cancel", "quiet"];
// Disable voice interruption entirely:
aiService.QuietWords = null;

Two interruption behaviors:

  • Quiet words — If the user says only a quiet word (e.g., “stop”), TTS is silenced and the conversation loop breaks, returning to wake word detection
  • Other speech — If the user says anything else during TTS (e.g., “actually, tell me about…”), TTS is silenced and the new utterance is sent to the AI as the next message, continuing the conversation
  • Only one wake word at a time — calling StartWakeWord() while already active throws InvalidOperationException
  • Exclusive with ListenAndTalkListenAndTalk() throws InvalidOperationException if wake word is active (they both use the microphone)
  • Waits for in-progress workStartWakeWord() waits for any active TalkTo() call to complete before starting the listener
async Task ToggleWakeWord()
{
if (aiService.IsWakeWordEnabled)
{
aiService.StopWakeWord();
}
else
{
await aiService.StartWakeWord("Hey Copilot");
}
}

Wake word detection is powered by Shiny.Speech’s ISpeechToTextService. The service calls ListenForKeyword() to detect the wake phrase, then ListenUntilSilence() to capture the user’s command. Both are platform-native implementations — no cloud API is needed for the wake word detection itself.