Task: Build a managed TTS pipeline for educational syllables and words
Build a managed TTS pipeline for educational syllables and words
Set up a custom controlled TTS process to pre-generate audio for letters, syllables, and words instead of relying on unpredictable browser SpeechSynthesis.
Context
Related task to browser text-to-speech cmu326hnm0bbpqw0qh5fgsv2f.
Experiments have shown that SpeechSynthesisUtterance pronounces many whole words adequately, but performs poorly and unpredictably with individual letters, short syllables, and artificially cropped parts of words.
Observed examples:
Собака(Dog) — normal;Со(So) — sounds roughly likeС;Р(R) — closer toЭ;Ры(Ry) — normal;Свинь(Svin') — may break down into spelling out letter names;Пель(Pel') — normal;Ковь(Kov'),Солн(Soln) — may be spelled out letter by letter;Ко(Ko) → roughlyКа;Ар(Ar) → roughlyА;Ре(Re) → roughlyЭ;Де(De) →Дэ.
Conclusion: browser TTS cannot be considered a reliable source of pedagogically correct pronunciation for the letter → syllable → word mechanic.
Objective
Build a custom managed TTS pipeline to pre-generate and verify educational audio.
Main idea:
card content
↓
letters / syllables / words
↓
controlled TTS
↓
manual/automated review
↓
ready audio files
↓
app only plays pre-prepared sound
Do not rely on the user's system voice for critical pronunciation at runtime in the educational app.
What needs to be generated
Minimum:
- individual letters where pedagogically appropriate;
- educational syllables;
- individual words for picture cards;
- short character instructions/lines if necessary.
It is especially important to pre-generate all syllables and words actually used in static educational content.
A universal generator for all possible Russian language combinations is not needed. We only generate the vocabulary actually included in the app.
TTS Requirements
We need an engine/service where pronunciation can be controlled better than in browser SpeechSynthesis.
Desired capabilities:
- stable voice across generations;
ru-RUlanguage control;ratecontrol;pitchcontrol if supported;- SSML or similar pronunciation control mechanism;
- ability to set pauses;
- ability to influence the reading of individual letters/syllables;
- export results to WAV/MP3/OGG;
- reproducible results during batch generation.
If a specific TTS reads a particular syllable poorly, it should be possible to specify a special TTS string separately from the displayed text.
For example:
type PronunciationAsset = {
text: string
ttsText?: string
audioSrc: string
}
where:
{
text: 'КО',
ttsText: '<special string/SSML for correct pronunciation>',
audioSrc: '/audio/syllables/ko.mp3',
}
Content Pipeline
Provide a registry of generated units:
type TtsSourceItem = {
id: string
text: string
kind: 'letter' | 'syllable' | 'word'
ttsText?: string
voiceId?: string
rate?: number
pitch?: number
}
Example:
const items: TtsSourceItem[] = [
{
id: 'word-dog',
text: 'СОБАКА',
kind: 'word',
},
{
id: 'syllable-so',
text: 'СО',
kind: 'syllable',
ttsText: '...',
},
{
id: 'letter-r',
text: 'Р',
kind: 'letter',
ttsText: '...',
},
]
Then a separate script/build-step:
items
→ TTS API
→ audio files
→ manifest
Ready Audio Manifest
After generation, the app should work with ready assets rather than TTS.
For example:
type AudioAsset = {
id: string
text: string
kind: 'letter' | 'syllable' | 'word'
src: string
}
export const audioAssets: AudioAsset[] = [
{
id: 'word-dog',
text: 'СОБАКА',
kind: 'word',
src: '/audio/words/sobaka.mp3',
},
{
id: 'syllable-so',
text: 'СО',
kind: 'syllable',
src: '/audio/syllables/so.mp3',
},
]
In UI:
const audio = new Audio(asset.src)
audio.play()
Important Architectural Idea
Separate three layers:
Display text
≠
TTS input
≠
Generated audio asset
This will allow showing СО to the child, but sending a different technical string/SSML to the TTS if that is the only way to get the correct pronunciation.
That is, do not assume:
what is written on the screen
=
what needs to be literally passed to TTS
Quality Assurance
Each unit needs a simple review status:
type AudioReviewStatus =
| 'generated'
| 'approved'
| 'rejected'
Minimum workflow:
- generate a batch;
- listen;
- mark bad variants;
- adjust
ttsText/ voice / parameters; - re-generate only rejected ones;
- use the asset in the app after
approved.
Check especially carefully:
- individual consonants;
- two-letter syllables;
- syllables with
ь/ъ(soft/hard signs); - cropped word parts;
- combinations that TTS might mistake for abbreviations.
Character Integration
The voice character system can use the same pipeline.
If characters need to differ in voice/tempo/pitch, for each character you can either:
- generate a separate set of assets;
- or use characters only for non-critical lines, and keep educational letters/syllables in a single reference voice.
This needs to be decided separately after estimating the volume of generated assets.
First Practical Stage
Do not choose the final TTS immediately.
First, compare several candidates on a short test set of problematic strings:
Р
СО
РЫ
РЕ
ДЕ
КО
АР
СВИНЬ
ПЕЛЬ
КОВЬ
СОЛН
СОБАКА
СВИНЬЯ
Evaluate for each candidate:
- pronunciation correctness;
- stability;
- presence of SSML/phoneme hints;
- Russian voice quality;
- batch generation capability;
- cost;
- licensing restrictions;
- convenience of saving results to audio files.
After that, select the main TTS and build the production pipeline.
Definition of Done
There is a reproducible process that takes a static list of educational letters/syllables/words, generates verified audio files, saves them as application assets, and allows separately overriding the technical TTS string for edge cases.