Documentation
¶
Overview ¶
Package markup is the canonical scanner for TTS characterization tags.
Personas and scripts emit bracket-tagged text like
"[whispers]Come here[/]Did you hear that?" "[excited][pause:500ms]Surprise!"
and each TTS provider adapter lowers those tags into its native dialect: ElevenLabs v3 receives them verbatim, OpenAI gpt-4o-mini-tts splits them into a free-form `instructions` field, Cartesia maps known names into its `emotion` array, SSML providers translate them to <prosody>/<break>.
This package owns the parsing and the canonical taxonomy so all providers agree on what the LLM is allowed to emit. Each provider remains free to drop tags it doesn't understand — see "Unknown tags" below.
Tag form ¶
- "[name]" — a flag tag (e.g. [whispers]).
- "[name:value]" — a tag with a value (e.g. [pause:500ms]).
- "[/]" — explicit end of the current span; no value, no name.
- "\[" and "\]" — literal brackets, not part of a tag.
Tag scope runs from the tag itself until the next tag, the end of the containing sentence (`.`, `?`, `!`), or an explicit "[/]" terminator. Spans do not overlap; a new tag implicitly closes the previous one.
Unknown tags ¶
Parsing accepts any name. Whether a name is meaningful is decided by the downstream consumer (ToSSML knows a fixed set; provider adapters know their own set). Unknown names degrade gracefully — they are dropped from SSML output and ignored by ExtractInstructions's textual phrasing.
Index ¶
Constants ¶
const RubricEmotionOnly = `` /* 581-byte string literal not displayed */
RubricEmotionOnly lists only the tags Cartesia maps to its emotion array. Cartesia's vocabulary is narrow (positivity / sadness / anger), so any other tag we include here would be silently dropped by the adapter.
const RubricExpressiveFull = `` /* 865-byte string literal not displayed */
RubricExpressiveFull lists every tag in the canonical taxonomy. Provider adapters that consume the full vocabulary (OpenAI gpt-4o-mini-tts via the instructions field, ElevenLabs v3 inline tags) return this string.
Variables ¶
This section is empty.
Functions ¶
func ExtractInstructions ¶
ExtractInstructions splits text into a free-form instructions phrase (suitable for the OpenAI gpt-4o-mini-tts `instructions` field) and the stripped spoken text. Tags are phrased with [tagPhrasing]; unknown tag names appear verbatim. Close tags ("[/]") are filtered out — they have no instruction value.
Example:
"[whispers]Come here[/]Did you hear that?"
→ ("whisper", "Come here Did you hear that?")
"[excited][pause:500ms]Surprise!"
→ ("excited; pause for 500ms", "Surprise!")
func StripTags ¶
StripTags returns text with every bracket tag removed. Escaped brackets ("\[" and "\]") are unescaped to their literal form. Whitespace collapsing is intentionally minimal — providers should treat the output as the verbatim spoken text and decide their own normalization.
func ToSSML ¶
ToSSML converts text into an SSML fragment for providers that consume SSML natively (Google, Azure). Tags wrap the span they govern:
- whisper/shout/calm/excited/sad/smile → <prosody> with rate/volume/pitch
- pause → <break time="…"/>
- unknown names → dropped (the text segment is rendered without a wrapper)
The returned string is *not* wrapped in <speak>; callers add that boundary when they assemble the request body. Output text is XML-escaped.
Types ¶
type Tag ¶
type Tag struct {
// Name is the tag name, lower-cased and trimmed. "/" indicates the
// explicit end-of-span marker "[/]".
Name string
// Value is the optional value portion ("[pause:500ms]" → "500ms").
// Empty for flag tags.
Value string
// Start is the byte offset in the input where "[" begins.
Start int
// End is the byte offset immediately after the closing "]".
End int
}
Tag is a parsed bracket-tagged directive.