Guide

Multiple speakers and effects, in the same block of text

The transcript understands one piece of syntax on top of plain text: a bracketed tag at the start of a line switches which character, and optionally which saved FX preset, applies to everything after it. This page covers exactly what that tag looks up, how the text around it gets split, and what happens when a tag doesn't match anything you've saved. It's the fast-typing alternative to the transcript's Characters menu, not a separate feature from it, both end up assigning the same character metadata to the same text.

01 · SyntaxTwo forms of one tag

Both forms sit at the start of a line, followed by a colon and the text that tag applies to:

Syntax
[PresetName]: Text spoken with that preset's voice and settings.

[PresetName:FXPresetName]: Same, plus that FX preset layered on top.

Everything up to the next tag (or the end of the text) belongs to that segment. Plain text with no tag at all is treated as a single segment using whatever voice and settings the Settings tab is currently set to, exactly like today.

02 · What gets looked upPresetName is a character name, not a raw voice

This is the part that trips people up: the name in brackets isn't a voice ID like af_heart. It's the name of a character (Edit > Characters..., or one of the legacy presets/<name>.json snapshots, which each become a character with that same name on load), so a tag's name is looked up as a character, case-insensitively, against whatever's saved. If you haven't saved anything under that name, the tag has nothing to find.

Same idea for the FX half: FXPresetName is the name of an FX preset saved from the FX dock's "Save FX Preset" button, stored as presets/fx/<name>.json. The FX dock's full field list is on the settings reference.

So before a script like [Narrator]: ... means anything, a preset literally named Narrator has to already exist in presets/.

The FX-only trick. Leave the preset name blank and start with a colon: [:FXPresetName]: Text. Since there's nothing before the colon, no preset gets applied, only the FX preset does, and the voice stays whatever the Settings tab is currently set to. Handy for layering an effect onto a line without also switching who's speaking.

03 · How segments splitEach tag resets to your base settings, not the last tag's

This is the second thing worth knowing before writing a long script: segments don't inherit from each other. Each one starts fresh from the Settings tab's project-scope settings, then layers on its own tag if it has one.

  1. Untagged text before the first tag, or text with no tags at all, uses the Settings tab's project-scope settings as-is.

  2. A [Preset]: tag loads that preset and overlays it on top of the base settings for everything until the next tag.

  3. A [:FXPreset]: tag keeps the base voice and settings, and only overlays the FX preset.

  4. An empty segment, one tag immediately followed by another with no text between them, is dropped rather than generating a silent clip.

  5. Each segment is independently split into smaller chunks afterward using your Split By setting, so one [Preset]: block can still turn into several audio chunks under the hood. The tags layer on top of smart splitting, they don't replace it.

04 · Worked exampleA four-line script, segment by segment

Assume two presets already exist, Narrator and VillainVoice, along with two FX presets, Reverb Heavy and Whisper. The Settings tab's currently selected voice is whatever you last picked, called out below as "the base voice."

Script
[Narrator]: The old house stood at the end of the lane.

[Narrator:Reverb Heavy]: A single door creaked open in the dark hallway.

[VillainVoice]: "Who dares enter my domain?" a voice boomed.

[:Whisper]: ...someone should not have come here.
[Narrator]:

Loads the Narrator preset. No FX preset, so whatever FX the preset itself specifies (usually none) is all that applies.

[Narrator:Reverb Heavy]:

Loads Narrator again, since presets don't carry over between segments, and layers the Reverb Heavy FX preset on top for this line only.

[VillainVoice]:

Switches to a completely different preset. No FX preset here, so no FX preset gets applied, not "whatever the last one was."

[:Whisper]:

Blank preset name, so this line uses the base voice (not VillainVoice, that only applied to the segment above), with the Whisper FX preset layered on.

05 · When a tag doesn't matchTypos don't stop the run

If a preset name in brackets doesn't match a saved file, that segment doesn't fail. It falls back to the Settings tab's project-scope settings, generation continues, and the status line shows a warning: Warning: Preset 'X' not found.

Same story for a missing FX preset: Warning: FX Preset 'X' not found. That segment just skips the FX step rather than erroring out.

The practical upshot: a typo in a long script quietly generates that block in the wrong voice instead of stopping you. Worth watching the status line while a multi-speaker script is running, especially the first time you use a new preset name.

06 · Turning tags into clipsAuto-split does the Characters-menu work for you

Writing a whole script with these tags and then manually selecting each block to assign it in the timeline works, but it's repetitive. Auto-split reads the same tags this page describes and creates one clip per tagged span automatically, landing each clip on its matching character's track, then generates them in one action.

Ask for the finer split and it also cuts each tagged span on paragraph breaks, so one [Narrator]: block spanning three paragraphs becomes three clips instead of one. Untagged narration only gets auto-clipped when your project has exactly one character, otherwise it's left alone, same as text nobody's assigned a character to today.

A span whose tag name doesn't match any saved character contributes no clip and shows up as a warning rather than failing the whole run, the same forgiving behavior described below for a missing preset.

07 · Plays well withLexicon, generation modes, and both engines

The Lexicon dock's pronunciation overrides apply to every segment's text before synthesis, regardless of which preset or FX preset is active. Lexicon rules are global, not per-speaker.

This syntax works the same way in Standard and JIT generation, both call the same parser before splitting text into chunks.

Both Kokoro and Audio8 support it today. Since the tags reference saved presets, not built-in engine voices, switching the active engine doesn't break an existing script as long as the preset names still resolve to something valid for the new engine.