Nodes/ComfyUI-ChatTTS/ChatTTS Text Normalizer
ComfyUI Node

ChatTTS Text Normalizer

Get the model to read numbers like a human

By neverbiasu·Created about a year ago·Updated about a year ago· 4
ChatTTS Text Normalizer
    • STRING
    text
    languageauto
    do_text_normalizationtrue
    do_homophone_replacementtrue

    Ever had a TTS model read "The meeting is at 2:30 PM, unit 42, $1,234.56" like a stranger reciting a barcode? That's what this node fixes. The Text Normalizer takes raw text and rewrites it the way a human would actually speak it - numbers become words, dates and times get expanded, units and currency get spelled out - before it ever reaches the sampler.

    Here's the thing: ChatTTS runs this normalization internally anyway, every time you sample. The node exists to expose that step so you can control it, inspect what the model will actually "read," and normalize once instead of on every run.

    The inputs

    • text - the required input, multiline. Whatever you'd otherwise paste straight into the Sampler.
    • language - auto (default), en, or zh. Set it when auto-detection guesses wrong; for a Chinese sentence with mixed English, telling it explicitly can clean up how numbers and dates come out.
    • do_text_normalization - on by default. This is the "spell it out" pass: 123 → "one hundred twenty-three", 2026 → "twenty twenty-six" (context-dependent, like a real reader).
    • do_homophone_replacement - on by default. Uses ChatTTS's homophone map to fix common same-sound wrong-character errors, which matters most for Chinese text. Turning it off is the debugging move if a sentence is being mangled.

    Output is a single STRING - the cleaned text, ready for the Sampler or a Text Splitter.

    How it works

    The node borrows ChatTTS's built-in normalizer directly (it constructs a Chat object just for its normalizer). It's the same code the sampler calls mid-pipeline - you're just getting it on the front end. One practical effect: you can eyeball the normalized output and see exactly what the model is about to say, which makes "why did it pronounce that wrong?" much easier to answer.

    When it earns its place

    • Numbers, dates, prices, units in your script. This is the difference between a demo and a finished voiceover.
    • Chinese text with English mixed in, where homophone replacement and language hints do the heavy lifting.
    • Making a workflow deterministic. If you normalize once and reuse the string across seeds, you're not re-running the same text processing every time - and it's a visible, debuggable step in the graph.

    The honest take: for simple English paragraphs you can skip it and the sampler's internal pass handles it. Reach for it when output text is genuinely messy - product descriptions, timestamps, anything with figures - or when you want to see what the model thinks your text says. Wiring it in is one connection upstream of the sampler, and it's the cheapest quality upgrade in the pack.

    Categorychattts

    Inputs (4)

    NameTypeDefaultDescription
    textSTRING
    languageoptCOMBOauto3 options: auto, en, zh
    do_text_normalizationoptBOOLEANtrue
    do_homophone_replacementoptBOOLEANtrue

    Outputs (1)

    NameTypeDescription
    STRINGSTRING