TTS studio appPro
A complete text to speech studio on scripted fixtures: a long form script with a voice and takes per paragraph, a panel for voice, delivery, take compare and stretch fixes, the voice library with design and clone, characters spent per take, and an export that renders real WAV files.
On this page
Installation
The template installs as a folder under components/chatcn/pro/tts-studio-app/: the app, the rail, the paragraph panel, the voice library, the export and the scripted engine, each a file you own and edit.
Usage
import { TtsStudioApp } from "@/components/chatcn/pro/tts-studio-app/tts-studio-app"
<TtsStudioApp
projects={scripts}
voices={library}
characters={account.characters}
renewal={{ amount: 100_000, at: account.renewsAt }}
/>Give it a height: it fills its parent. Everything runs on the scripted engine in tts-engine.ts: takes are synthesized in each voice's timbre with Web Audio, voice design turns the words of a description into three timbres, and export renders every take, resamples it, evens the loudness and encodes WAV in the tab. To go live, replace renderTake, designPreviews and exportAudio with your API and keep their shapes; the editor, the panel and the export follow on their own.
Examples
Design a voice
The library has three tabs: every voice with samples and filters, Design a voice from a description, and Clone a voice from recorded or uploaded samples. A saved voice joins the library and every paragraph's voice picker at once. Voices on a higher plan offer the upgrade.
Low on characters
Every take spends the characters it says, tags excluded. At the low line the balance and a banner say so; a take that needs more than is left is not made, and the banner says how many it needs with Buy characters and the upgrade. A paragraph with a tag the model does not read fails free of charge, with the fix in words.
On a phone
Below 768 px the rail moves into a drawer, the paragraph panel opens as a sheet from the sliders button, the voice sits above each paragraph and every control keeps a 44 px target. Pass layout="mobile" to force it inside a device frame.
What is inside
- The shell is the free
ChatLayout: the rail collapses to icons withCmd+Band becomes a drawer under 768 px; the paragraph panel is its side panel. TtsStudioas the editor: a voice per paragraph, inline audio tags that autocomplete on[, out of date marks after edits, one sentence redone at the caret, and a timeline of the takes in use with Play all.- The panel follows the caret: the paragraph's voice with a sample and Change voice into the library,
SpeechSettingsfor its next take, the last two takes in sync onAudioAbSwitch, and a stretch of the take said again onWaveformRegionEditor, spliced into a new take. VoiceLibrary,VoiceDesignandVoiceCloneFlowin the Voices view. Picking a voice for a paragraph applies it and goes back to the script.- Characters on
CreditBalancewith spend by action and the renewal,RateLimitBannerwhen low or short,CreditTopUpin a dialog and a plan upgrade that unlocks every voice. - Export with sample rate, bit depth, loudness and a file per paragraph, the size before you start, progress as each paragraph renders, and WAV files to download.
Props
| Prop | Type | Notes |
|---|---|---|
projects | { id, name, detail?, paragraphs }[] | Scripts. Paragraphs are TtsStudio paragraphs with their takes |
voices | SpeechVoice[] | The library. A voice with plan is locked until the upgrade |
characters | number | Characters left. A take that needs more is not made |
renewal | { amount, at } | The monthly allowance and when it renews |
spend, lowAt | CreditSpend[], number | Recent spend, and the low line. Default 1,000 |
upgrade | { name, price, period?, features, characters } | The plan the upgrade offers |
packs | CreditPack[] | Character packs for the top up dialog |
account | { name, plan } | The account menu at the foot of the rail |
defaultProjectId, defaultView, defaultVoicesTab | string, "script" | "voices", "library" | "design" | "clone" | Where it opens |
defaultDesign, cloneSamples, defaultExporting | Open into a design, a clone with samples, or a running export | |
defaultPanelOpen | boolean | The paragraph panel. Default open on desktop |
layout | "auto" | "desktop" | "mobile" | Force the phone layout inside a device frame |
Keyboard
| Key | Action |
|---|---|
Cmd+Enter or Ctrl+Enter | Generate the paragraph |
Alt+Enter | Regenerate the sentence at the caret |
[ | Insert an audio tag |
Cmd+. or Ctrl+. | Show or hide the paragraph panel |
X | Switch between take A and B |
Arrows, Enter, Space | Move between voices, pick one, play its sample |
Cmd+B or Ctrl+B | Collapse or expand the rail |
Cmd+/ or Ctrl+/ | Every shortcut, grouped by area |
Accessibility
- Landmarks from the layout, a skip link to the script, a named navigation for scripts and the library with
aria-current, and the paragraph panel as a named complementary region. - Each paragraph field is named by its number and voice and described by its status, so a screen reader hears Edited since the last take or Did not generate with the text.
- Voice changes, kept takes, new voices, purchases and finished exports are announced politely, once. Generation progress is never announced per tick.
- Every composed part keeps its own semantics: the library is a listbox, the Voices view uses tabs, the export progress is a progressbar and its options are radio groups and a switch.
Motion
- Each composed component keeps its own motion: a generating paragraph shimmers its status after 300 ms, a new take fades into its clip, the panel slides in on the panel curve, characters roll their digits.
- Export progress fills from the start edge as each paragraph renders and never runs backwards. Moving between scripts and the library is instant.
- Under reduced motion only short fades remain and the progress fill jumps.