useSpeechSynthesis
Reactive wrapper around the SpeechSynthesis API. Provides speak/stop/toggle controls with real-time status tracking.
Text-to-speech via the SpeechSynthesis API. Click Speak to hear the text.
import { const useSpeechSynthesis: (text: MaybeObservable<string>, options?: DeepMaybeObservable<UseSpeechSynthesisOptions>) => UseSpeechSynthesisReturn
useSpeechSynthesis } from "@usels/web";
function function TextToSpeech(): JSX.Element
TextToSpeech() { const { const isSupported$: ReadonlyObservable<boolean>
isSupported$, const isPlaying$: ReadonlyObservable<boolean>
Whether speech is currently playing
isPlaying$, const status$: ReadonlyObservable<UseSpeechSynthesisStatus>
Current status
status$, const speak: () => void
Start speaking the text
speak, const stop: () => void
Stop speaking
stop } = function useSpeechSynthesis(text: MaybeObservable<string>, options?: DeepMaybeObservable<UseSpeechSynthesisOptions>): UseSpeechSynthesisReturn
Framework-agnostic reactive wrapper around the
SpeechSynthesis API.
Each speak() call constructs a fresh SpeechSynthesisUtterance using the
latest text and option values. Cleanup (speechSynthesis.cancel()) is
registered via onUnmount.
useSpeechSynthesis("Hello world");
return ( <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Supported: {const isSupported$: ReadonlyObservable<boolean>
isSupported$.ImmutableObservableBase<boolean>.get(trackingType?: TrackingType | GetOptions): {}
get() ? "Yes" : "No"}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Status: {const status$: ReadonlyObservable<UseSpeechSynthesisStatus>
Current status
status$.ImmutableObservableBase<UseSpeechSynthesisStatus>.get(trackingType?: TrackingType | GetOptions): {}
get()}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> <JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick={() => const speak: () => void
Start speaking the text
speak()}>Speak</JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button> <JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick={() => const stop: () => void
Stop speaking
stop()}>Stop</JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button> </JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> );}import { createSpeechSynthesis } from "@usels/web";
function TextToSpeech() { "use scope"; const { isSupported$, isPlaying$, status$, speak, stop } = createSpeechSynthesis("Hello world");
return ( <div> <p>Supported: {isSupported$.get() ? "Yes" : "No"}</p> <p>Status: {status$.get()}</p> <button onClick={() => speak()}>Speak</button> <button onClick={() => stop()}>Stop</button> </div> );}With voice options
Section titled “With voice options”// @noErrorsimport { useSpeechSynthesis } from "@usels/web";
function CustomVoice() { const { speak, stop, isPlaying$ } = useSpeechSynthesis("안녕하세요", { lang: "ko-KR", pitch: 1.2, rate: 0.9, });
return ( <button onClick={() => (isPlaying$.get() ? stop() : speak())}> {isPlaying$.get() ? "Stop" : "Speak"} </button> );}Reactive text and options
Section titled “Reactive text and options”The text parameter accepts MaybeObservable<string>, and options accept DeepMaybeObservable. Changes take effect on the next speak() call.
// @noErrorsimport { observable, useObservable } from "@usels/core";import { useSpeechSynthesis } from "@usels/web";
function DynamicSpeech() { const text$ = useObservable("Hello world"); const rate$ = observable(1);
const { speak } = useSpeechSynthesis(text$, { rate: rate$ });
return ( <div> <input value={text$.get()} onChange={(e) => text$.set(e.target.value)} /> <button onClick={() => speak()}>Speak</button> </div> );}text is MaybeObservable<string>. Pass a plain string or an Observable<string>. The latest value is read at each speak() call.
options is DeepMaybeObservable. Each option field can be a plain value or an Observable. All options are read at each speak() call time. The voice option uses opaque wrapping to prevent Legend-State from deep-proxying the DOM object.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
text | MaybeObservable<string> | - |
options | UseSpeechSynthesisOptions (optional) | - |
UseSpeechSynthesisOptions
Section titled “UseSpeechSynthesisOptions”Returns
Section titled “Returns”UseSpeechSynthesisReturn
| Name | Type | Description |
|---|---|---|
isPlaying$ | ReadonlyObservable<boolean> | Whether speech is currently playing |
status$ | ReadonlyObservable<UseSpeechSynthesisStatus> | Current status |
error$ | ReadonlyObservable<UseSpeechSynthesisErrorData | undefined> | Speech error |
speak | () => void | Start speaking the text |
stop | () => void | Stop speaking |
toggle | (value?: boolean | undefined) => void | Toggle speaking |
isSupported$ | ReadonlyObservable<boolean> | - |