One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Speech Synthesis

Speak text aloud through the platform synthesizer

One.SpeechSynthesis speaks text aloud through the platform voice. Reach for it for read-aloud articles, navigation prompts, and accessibility announcements. It is separate from One.Speech, which is microphone dictation going the other way.

On iOS utterances queue on AVSpeechSynthesizer. On Android they queue on the system text-to-speech engine. On web the browser’s speech synthesis speaks.

Usage

import { One } from 'one'
One.SpeechSynthesis.speak('Hello', {
language: 'en-US',
rate: 1,
onDone: () => console.log('finished'),
})
await One.SpeechSynthesis.stop()

speak queues while another utterance speaks. Each call carries its own start, done, stopped, and error callbacks, and every utterance ends with exactly one of done, stopped, or error.

How it works

Options default to the natural voice: pitch 1, rate 1, volume 1, and a system voice matching the language, which itself defaults to the current voice’s language. Volume runs 0 (muted) to 1. The text must fit maxInputLength, read once from the engine; iOS reports no limit. stop clears the queue and the interrupted utterance reports stopped. pause and resume hold and continue synthesis on iOS and resolve quietly on Android. isSpeaking covers this app’s queue, so it turns false once the queue finishes or stop resolves, and stays true while paused. getAvailableVoices resolves identifier, language, name, and quality entries, where quality is default or enhanced.

On iOS physical devices speech stays silent when the silent switch is on. On web cancellation maps to onStopped and every voice reports default quality. Without a synthesizer, speak does nothing, reads report empty, and callbacks never fire.

API reference

MethodsTypeDescription
speak(text: string, options?: SpeechSynthesisOptions) => voidQueue an utterance with its own callbacks.
(text: string, options?: SpeechSynthesisOptions) => voidQueue an utterance with its own callbacks.
stop() => Promise<void>Clear the queue. The cut utterance reports stopped.
() => Promise<void>Clear the queue. The cut utterance reports stopped.
pause() => Promise<void>Hold synthesis. iOS only; quiet on Android.
() => Promise<void>Hold synthesis. iOS only; quiet on Android.
resume() => Promise<void>Continue synthesis. iOS only; quiet on Android.
() => Promise<void>Continue synthesis. iOS only; quiet on Android.
isSpeaking() => Promise<boolean>Whether this app speaks, queues or holds speech.
() => Promise<boolean>Whether this app speaks, queues or holds speech.
getAvailableVoices() => Promise<SpeechSynthesisVoice[]>The installed voices.
() => Promise<SpeechSynthesisVoice[]>The installed voices.
maxInputLengthnumberThe longest text one speak accepts.
numberThe longest text one speak accepts.
OptionsTypeDescription
languagestringBCP-47 tag. Defaults to the voice language.
stringBCP-47 tag. Defaults to the voice language.
pitchnumberPitch multiplier. Default 1.
numberPitch multiplier. Default 1.
ratenumberRate multiplier. Default 1.
numberRate multiplier. Default 1.
voicestringA voice id. Defaults to the system voice.
stringA voice id. Defaults to the system voice.
volumenumber0 muted to 1 max. Default 1.
number0 muted to 1 max. Default 1.
onStart() => voidThe utterance started speaking.
() => voidThe utterance started speaking.
onDone() => voidThe utterance finished speaking.
() => voidThe utterance finished speaking.
onStopped() => voidThe utterance was stopped.
() => voidThe utterance was stopped.
onError(error: Error) => voidThe utterance failed.
(error: Error) => voidThe utterance failed.
VoiceTypeDescription
identifierstringThe id to pass as voice.
stringThe id to pass as voice.
languagestringThe BCP-47 tag it speaks.
stringThe BCP-47 tag it speaks.
namestringThe display name.
stringThe display name.
qualitySpeechSynthesisVoiceQualityDefault or enhanced.
SpeechSynthesisVoiceQualityDefault or enhanced.

Platform differences

iOSAndroidWeb
EngineSystem voiceSystem TTSBrowser API
QueueQueuesQueuesQueues
PauseHoldsQuiet no-opBrowser decides
Silent switchMutesNo switchNo switch
Voice qualityDefault, plusDefault, plusDefault only

Limits and gotchas

Examples

Read an article aloud

import { useEffect } from 'react'
import { Button } from 'react-native'
import { One } from 'one'
function ReadAloud({ paragraphs }: { paragraphs: string[] }) {
useEffect(() => {
return () => {
void One.SpeechSynthesis.stop()
}
}, [])
function read() {
for (const text of paragraphs) {
One.SpeechSynthesis.speak(text, { rate: 1.1 })
}
}
return <Button title="Read aloud" onPress={read} />
}

Queueing every paragraph at once speaks the article in order without manual chaining. Unmounting stops the queue so speech never outlives the screen.

Announce with a chosen voice

import { useEffect, useState } from 'react'
import { Button } from 'react-native'
import { One } from 'one'
function Announcer({ message }: { message: string }) {
const [voice, setVoice] = useState<string | undefined>(undefined)
useEffect(() => {
One.SpeechSynthesis.getAvailableVoices().then((voices) => {
const enhanced = voices.find((entry) => entry.quality === 'enhanced')
setVoice(enhanced?.identifier)
})
}, [])
function announce() {
One.SpeechSynthesis.speak(message, {
voice,
onError: () => {},
})
}
return <Button title="Announce" onPress={announce} />
}

An enhanced voice reads announcements more naturally where one is installed; elsewhere the identifier stays undefined and the system voice speaks. The empty error callback keeps a failed announcement quiet.

Edit this page on GitHub.