Generate speech audio from subtitle text using various TTS engines.

When the subtitle carries speaker names — the Actor field in ASSA/SSA, or <v Name> voices in WebVTT — a Set up cast button appears (with the speaker count). It opens a dialog where each actor is assigned an engine, voice, and optionally a model and voice instruction of their own. Lines without an actor use the globally selected voice. The cast is remembered between sessions, so the same actors open already assigned next time.
If the speaker names are written into the text instead (an SDH subtitle), see the speaker prompt below — and for a video where nobody labeled the speakers at all, Find Voices in Video and Clone works out the cast by listening.
Clicking Generate runs up to three quick checks on the subtitle before any audio is made. Each one only appears when it has something to show, each opens a review dialog where every proposed change is a checkbox, and each can be turned off in Options → Settings (search for “Text to speech: prompt”).
An SDH subtitle writes its speakers into the text — MIKE: text, [NARRATOR] text, (Speaker 1) text, or a name alone on its line with the speech below. Sent to a TTS engine as-is, the names are read aloud. When no cast exists yet and at least two speakers are found, Subtitle Edit offers to move the names into the actor field: the tags leave the spoken text, the Set up cast dialog opens so each speaker gets a voice, and generation continues with the cast.
Speaker 1) are checked by default; mixed-case candidates like Warning: are listed for you to judge, but unchecked.Sentences split across several subtitles are offered for merging, so the engine speaks each thought as one breath group. These merges are applied to the subtitle in the main window when the window is closed with OK.
Lines that contain only sounds or music — ♪, [door slams], (sighs), or nothing once formatting tags are stripped — get read aloud or hallucinated into made-up words by TTS engines. Subtitle Edit offers to leave the checked lines silent: no audio is generated for them, and they are not counted as failures. A sound annotation followed by real speech ([gunshot] Get down!) is kept.
Local downloadable engines are installed into the Subtitle Edit data folder when you accept the download prompt.
Several of the local engines above are different models on the same CrispASR runtime, sharing one CrispASR/models folder with the speech-to-text backends. What separates them is voice output quality rather than features, so they are collected here.
Output rate is the engine’s native render rate - 48 kHz carries noticeably more high end than 24 kHz on headphones, though for speech mixed under a video the difference is small. Reference WAV is the format a cloning reference is converted to on import; Subtitle Edit resamples with ffmpeg for you, but a clean 3-10 second recording at or above that rate clones best.
| Engine | Output rate | Languages | Voice cloning | Reference WAV | Download |
|---|---|---|---|---|---|
| OmniVoice TTS (CrispASR) | 24 kHz | 646 | Built-in voice + zero-shot | 24 kHz mono | ~1 - 1.6 GB |
| Qwen3 TTS (CrispASR) | 24 kHz | 10 | VoiceDesign, CustomVoice or Voice clone | 24 kHz mono (strictly enforced) | ~2.3 GB |
| Chatterbox TTS (CrispASR) | 24 kHz | 23 on Base; Turbo is English-only | Zero-shot | 24 kHz mono | ~700 MB - 1.8 GB Base, ~1 GB Turbo |
| IndexTTS (CrispASR) | 24 kHz | Follows the text | Zero-shot | 24 kHz mono | ~600 MB - 2.4 GB |
| CosyVoice3 (CrispASR) | 24 kHz | 9, plus 18 Mandarin dialects as voices | 8 baked-in presets + zero-shot | 16 kHz mono + a transcript sidecar | ~1.6 - 2.5 GB |
| MOSS-TTS (CrispASR) | 24 kHz | 20 | Zero-shot | 24 kHz mono | ~10.5 - 20.5 GB incl. codec |
| Zonos TTS (CrispASR) | 44.1 kHz | Follows the text | From a reference recording | 24 kHz mono | ~1.8 GB |
| VoxCPM2 (CrispASR) | 48 kHz | ~30 | Zero-shot | 24 kHz mono (upsampled internally) | ~1.7 - 5 GB |
| dots.tts (CrispASR) | 48 kHz | Follows the text | Zero-shot | 24 kHz mono | ~2.4 - 5 GB |
“Follows the text” means the engine has no language picker - it speaks whatever script it is given, taking its accent from the reference voice.
Notes on picking one:
Q4_K is the small fast default, Q8_0 is close to full precision, and F16 is rarely worth the extra gigabytes.Some engines require additional configuration:
Several local engines can clone a voice from a reference recording. The first time you do this — when you import a reference recording, or generate speech with a cloned voice — Subtitle Edit shows a one-time dialog with the terms you are accepting. You have to tick the checkbox before you can continue.
The points that matter:
Declining just means “not now” — nothing is changed, the clone is refused, and you are asked again the next time. The answer is remembered per terms version, so you are asked again if the terms change.
You do not have to prepare a reference recording by hand. In the main window, right-click a subtitle line in the waveform and choose Clone voice to → engine name. Subtitle Edit cuts the audio for that line out of the video’s current audio track, asks what to call the new voice (pre-filled with the line’s actor, or the video name and line number), and imports it as a cloned voice for the chosen engine. The line’s own text is used as the transcript the cloning engines want, so you are not asked to type it.
The menu item appears when exactly one subtitle line is selected and the right-click was on that line, and a video is open. Only engines that can clone are listed. The new voice is then in the voice list for that engine the next time you open Video → Text to speech….
Pick a line with clean speech: a couple of seconds or more, one speaker, and as little music and effects as possible. The clip is used exactly as it sounds in the video.
Video → More → Find voices in video and clone… does the whole cast in one go: it works out who speaks in the video, clones each of them, and leaves the cast assigned so the dubbing is ready to generate.
What happens, in order:
(Speaker 1) …) are moved into the subtitle’s Actor field, where they belong.If a subtitle is already open, its lines and text are kept — the speakers are matched to your existing lines by time overlap, so a translation is not replaced by the transcription. With nothing open, the transcription becomes the subtitle.
Lines that overlap no detected speech (music, on-screen text) are left without an actor and fall back to the globally selected voice.
For dubbing a video with several speakers there is a faster way than cloning each of them by hand. With a video open, pick Clone from video (voice of each line) at the top of the voice list. Every subtitle line is then spoken in the voice heard in the video at that line — whoever speaks line 12 in the original speaks line 12 in the dub. No reference recordings, no imports, no cast to assign.
Before generating, Subtitle Edit cuts one short reference clip per line out of the video’s audio. Lines shorter than about three seconds are grown into the silence around them, but never into the neighbouring line — a reference with two speakers in it would clone the wrong person.
Qwen3 TTS runs through the CrispASR runtime and shares the CrispASR/models directory with the speech-to-text Crisp ASR engines.
Chatterbox TTS runs through the CrispASR runtime (shared with the speech-to-text feature) and supports voice cloning.
Kokoro TTS runs a local server with downloadable models.
OmniVoice TTS runs the omnivoice-tts CLI on CPU. It supports a large set of languages and voice cloning from reference WAV files (with an accompanying transcript). Because each line is a separate run that takes its own reference, it is also the engine behind Clone from video (voice of each line).
MistralSpeech is configured with an API key and model selection. The selected model is remembered in settings.
You can control pausing and pacing in ElevenLabs output directly from the subtitle text.
<break time="1.5s" /> for an explicit pause (up to about 3 seconds). Keep them sparse: too many break tags in one line can make ElevenLabs speed up or add audio artifacts....) add a hesitant pause, and dashes (---) add a short break. These are less precise than break tags but useful for a natural feel.Subtitle Edit sends your text to ElevenLabs with text normalization turned off, so these pause cues are preserved instead of being collapsed or rewritten.
Behavior depends on the selected model:
eleven_turbo_v2_5, eleven_multilingual_v2, …) honor SSML <break> tags and punctuation pauses.<break> tags. Subtitle Edit automatically converts each <break time="Xs" /> into the nearest v3 audio pause tag — [short pause] (under 0.75 s), [pause] (up to 1.5 s), or [long pause] (longer) — so the same subtitle text keeps working when you switch to v3.When Review audio clips is enabled, a dedicated review window opens after generation. This window lets you inspect, play, and regenerate audio for every subtitle line before the result is used. A 120px waveform of the original video audio is shown above the grid as a reference. The session (clips, per-line voice and engine, includes, text edits) can be written to SubtitleEditTts.json and imported again later — see Continuing a Session Later. Regeneration history is kept for the current session only and is not part of the export.
Each subtitle line is shown as a row with the following columns:
| Column | Description |
|---|---|
| Include | Checkbox to include or exclude the line from the final output |
| # | Subtitle line number |
| Text | The subtitle text (editable — double-click to modify before regenerating). Text edits are applied to the subtitle in the main window when the Text to speech window is closed with OK |
| Voice | The voice used for that line |
| Speed | The speed factor applied to fit the audio into the subtitle’s duration |
| CPS | Characters per second for the subtitle line |
You can regenerate the audio for any individual line:
The new clip is trimmed for silence and automatically speed-adjusted to fit the subtitle timing. After regeneration the new clip plays back immediately for review.
For ElevenLabs, extra fine-tuning parameters are available when that engine is selected: Stability, Similarity, Speaker Boost, Speed, and Style Exaggeration. A Reset button restores all ElevenLabs parameters to their defaults.
Every time a clip is regenerated, the previous version is saved. To review the history for a line, click the History button on that row. The history dialog shows all generated versions with their voice name and speed, and lets you play each one. Selecting a version and clicking OK restores it as the active clip for that line.
Uncheck the Include checkbox on any row to exclude that line’s audio from the final output. Excluded lines are skipped when the video file is assembled.
Click Export to save all audio clips and a SubtitleEditTts.json metadata file to a folder of your choice. The JSON file records the audio file names, subtitle timings, voice names, engine names, speed factors, and text for each line, making it easy to re-import or post-process the clips externally.
A long video does not have to be dubbed in one sitting. Export the session when you stop, and import it when you come back:
SubtitleEditTts.json there, plus a wav subfolder with every generated clip.SubtitleEditTts.json.What comes back with the session:
From there you can play, edit text, regenerate single lines, and finish the session normally. Keep the wav folder next to the JSON file: the clip paths are stored relative to it, so the whole folder can be moved or copied to another machine.
| Key | Action |
|---|---|
| Ctrl+R | Regenerate selected line |
| Escape | Close / Cancel |
| F1 | Open help |