AI Speech Reference
Use useAISpeech to convert text into natural-sounding audio. Generated speech returns a hosted URL for playback and persistence.
useAISpeech
Returns
generateSpeech(function): Generate speech from text.isLoading(boolean): Whether generation is in progress.error(Error | null): Current error.clearError(() => void): Clear the current error.
Result Shape
url(string): Hosted URL for playback and persistence.
generateSpeech Input
text(string, required): Text to convert to speech.voice(string): Platform voice ID fromlistSpeechVoices(). Omit it to use Haven. The same voices work with every speech model.instructions(string): Additional voice direction for supported OpenAI models.language(string, default"en"): ISO 639-1 language code.model(string): Model ID for the request.
generateSpeech resolves to the result shape above on success or undefined on failure. It never rejects.
Example
Import the hook from the AI hook module:
import { useAISpeech } from '@/hooks/use-ai'
import { usePersistentItem } from '@/hooks/use-persistent-item'
export default function App() {
const [text, setText] = React.useState('')
const [audioUrl, setAudioUrl] = usePersistentItem<string | null>(
'audioUrl',
null,
)
const { generateSpeech, isLoading, error } = useAISpeech()
const handleGenerate = async () => {
if (!text.trim()) return
const audio = await generateSpeech({ text: text.trim() })
if (audio?.url) {
setAudioUrl(audio.url)
}
}
return (
<div>
<textarea
value={text}
onChange={(event) => setText(event.target.value)}
placeholder="Enter text to convert to speech..."
/>
<button onClick={handleGenerate} disabled={isLoading}>
{isLoading ? 'Generating...' : 'Generate speech'}
</button>
{error ? <p className="text-destructive">{error.message}</p> : null}
{audioUrl ? (
<audio controls src={audioUrl} className="w-full">
Your browser does not support the audio element.
</audio>
) : null}
</div>
)
}
Use the returned hosted URL for playback and persistence.
Voices and Providers
Omit voice unless the app needs a voice picker. listSpeechVoices() takes no arguments and returns the platform voices: Haven, Cedar, Atlas, Lumen, Willow, and Ember. Haven is the default when voice is omitted or unrecognized. These voices are not tied to one provider. The platform maps the selected voice onto whichever speech model runs the request, so the exact sound can vary between models.
import { listSpeechVoices, useAISpeech } from '@/hooks/use-ai'
const voices = listSpeechVoices()
const [voiceId, setVoiceId] = React.useState<string | undefined>(undefined)
const { generateSpeech } = useAISpeech()
await generateSpeech({
text: 'Welcome to our application!',
voice: voiceId,
})
Model Selection
When no model is specified, the platform chooses an efficient default speech model for the user's plan. To expose model choice, pass a model ID and build selectors from listSpeechModels():
import { listSpeechModels, useAISpeech } from '@/hooks/use-ai'
const models = listSpeechModels()
const [modelId, setModelId] = React.useState<string | undefined>(undefined)
const { generateSpeech } = useAISpeech()
await generateSpeech({
text: 'Hello world',
model: modelId,
})
listSpeechModels() returns model objects with id, displayName, provider, tier, description, and capabilities. Speech model capabilities include tts.
listSpeechVoices() returns voice objects:
id: Voice ID to pass asvoice.name: Human-readable voice name.description: Guidance about the voice character.
Lite models are available on every plan. Standard models require Basic or Pro. Advanced models require Pro. More capable models cost more credits. Deprecated models automatically fall back to a recommended replacement.
Best Practices
- Omit
voiceunless the app specifically needs a voice picker or branded voice. - Use the
urlfield for playback and persistence. - Store the URL with
usePersistentItemif the audio should survive reloads. - Split long content into chunks because maximum text length varies by model.
- If you require a specific voice, pass a platform voice ID from
listSpeechVoices().