loading

Support and voices

IsSupported / GetVoices

IsSupported reports whether window.speechSynthesis exists. GetVoices returns every SpeechVoice the platform offers - name, BCP-47 language tag, whether it is the default for its language and whether synthesis runs locally or via a network service.

C#
@inject Bit.Butil.SpeechSynthesis speechSynthesis

var isSupported = await speechSynthesis.IsSupported();

SpeechVoice[] voices = await speechSynthesis.GetVoices();

foreach (var voice in voices)
{
    // voice.Name, voice.Lang, voice.Default, voice.LocalService, voice.VoiceUri
}
Live sample
voices output
Results will appear here when you interact with the samples.

Speak an utterance

Speak

Configure a SpeechUtterance - text, an optional voice from GetVoices, rate (0.1–10; the slider below covers a practical 0.1–4), pitch (0–2) and volume (0–1) - and hand it to Speak. The call resolves once the engine accepts the utterance, not when speech finishes; utterances queue if you call Speak repeatedly. A string-only overload speaks with all defaults.

C#
await speechSynthesis.Speak(new SpeechUtterance
{
    Text = "Hello from Bit.Butil!",
    VoiceName = "Microsoft Aria Online (Natural) - English (United States)",
    Rate = 1.0,
    Pitch = 1.0,
    Volume = 1.0,
});

// or with defaults for everything:
await speechSynthesis.Speak("Hello from Bit.Butil!");
Live sample
Text
Voice
Rate (1.0)
Pitch (1.0)
Volume (1.0)
speak output
Results will appear here when you interact with the samples.

Pause, resume, cancel

Pause / Resume / Cancel

Pause freezes the current utterance mid-word and Resume picks it back up. Cancel flushes the whole queue and stops any current speech - the right call when the user navigates away or starts a new narration.

C#
await speechSynthesis.Pause();

await speechSynthesis.Resume();

await speechSynthesis.Cancel(); // flush the queue and stop
Live sample
playback output
Results will appear here when you interact with the samples.

Engine state

IsSpeaking / IsPending

IsSpeaking is true while an utterance is being spoken (including while paused); IsPending is true while at least one utterance is still waiting in the queue. Useful for toggling a speaking indicator or debouncing repeated Speak calls.

C#
var speaking = await speechSynthesis.IsSpeaking();
var pending = await speechSynthesis.IsPending();
Live sample
engine state output
Results will appear here when you interact with the samples.
Note:
Voices load lazily in Chromium Chromium populates the voice list asynchronously, so the very first GetVoices call after a page load can return an empty array. Click GetVoices again (or re-query after the engine warms up) and the full list appears. Voice availability also differs per OS - cloud voices on Windows, high-quality local voices on macOS.
Note:
Autoplay policies apply Some browsers require a user gesture before audio output is allowed, so trigger the first Speak from a click or key handler. If nothing is audible, also check the OS output device and the Volume slider above.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes window.speechSynthesis.
GetVoices
ValueTask<SpeechVoice[]> GetVoices()
Returns the list of voices the platform makes available.
Speak
ValueTask Speak(SpeechUtterance utterance)
Speaks the configured utterance. Resolves once the engine has accepted it (not when speech finishes).
Speak
ValueTask Speak(string text)
Quick-shorthand: speak the text with default voice and rate.
Cancel
ValueTask Cancel()
Cancels all pending utterances and stops any current speech.
Pause
ValueTask Pause()
Pauses the current utterance.
Resume
ValueTask Resume()
Resumes a paused utterance.
IsSpeaking
ValueTask<bool> IsSpeaking()
True when the engine is currently speaking (or paused).
IsPending
ValueTask<bool> IsPending()
True when an utterance is queued.
IsPaused
ValueTask<bool> IsPaused()
True when speech is paused. Independent of IsSpeaking, which stays true while paused mid-utterance - check this before rendering a pause/resume toggle.
An unhandled error has occurred. Reload 🗙