TTS studioPro
A long form script editor for speech: a voice per paragraph, expressive tags inside the text, stale marks after edits, regenerate one sentence at the caret, and a timeline of takes with play all and take switching.
On this page
Installation
Usage
import { TtsStudio } from "@/components/ui/chatcn/pro/tts-studio"
<TtsStudio
voices={voices}
paragraphs={paragraphs}
onParagraphsChange={setParagraphs}
onGenerate={({ paragraphId, text, voiceId, sentence }) => synthesize(paragraphId, text, voiceId, sentence)}
onExport={exportMix}
/>A paragraph is { id, voiceId, text, takes, activeTake, status, generatedText }. Set status: "generating" when a request starts and append the take when it lands, with generatedText set to the text it was made from: when the text changes after that, the paragraph says it is out of date and Generate all picks it up. A take with sentence set redid that sentence only.
The examples play a demo synthesizer built on the Web Audio API (renderBabble and renderSfx in @/lib/chatcn-pro-speech): it sounds like a voice behind a wall, so nothing pretends to be a real model. Pass your API's audio as URLs or buffers instead.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
paragraphs, defaultParagraphs, onParagraphsChange | StudioParagraph[] | |
voices | SpeechVoice[] | Required. Each paragraph picks one with the free voice-picker |
onGenerate | (request) => void | Paragraph id, text, voice, and sentence for one sentence |
onExport | () => void | Enabled once every paragraph has a current take |
title | ReactNode | Default Script |
tags | AudioTagInfo[] | The tags your model reads, for the autocomplete |
labels | Partial<TtsStudioLabels> | Every string the studio shows or announces, for translation |
disabled, locale |
Keyboard
| Key | Action |
|---|---|
Alt + Enter | Regenerate the sentence at the caret |
⌘ or Ctrl + Enter | Regenerate the paragraph |
[ | Open the tag menu inside the text |
Tab | Voice, text, play, regenerate, then the timeline clips and takes |
Accessibility
- Each paragraph's text is named with its number and voice and described by its status: not generated, out of date, generating, or which take plays.
- Timeline clips are buttons that say the paragraph, the voice, the length and whether it is stale.
- Status has a word as well as a color; the stale mark is amber with its sentence.
Motion
- Typing never animates. A generating paragraph shows the text shimmer after 300 ms, and its clip keeps its width, so nothing reflows.
- A new take fades into its clip over 200 ms; the playhead moves with the audio.