๐โ๐ TTS - Text to Speech
XTTS voice cloning in ComfyUI (it needs a separate backend server)
- connect_to_workflow
- TTS_URL
- TTS_LANGUAGE
- TTS_SPEAKER
- AUDIO
- audio_path
- audio_full_path
- audio_duration
This node turns text into spoken audio using XTTS v2 - the voice-cloning model - so you can generate speech in any of 17 languages, in a voice you supply from a sample. The headline feature is that it clones: hand it a short .wav of a voice and it'll read your text in that voice, and it'll happily make an English voice sample speak Japanese or vice versa. Useful for narration, lip-sync pipelines (feed the audio to a talking-head model), or just an audible "workflow done" chime.
One thing to be crystal clear about before you get excited: this node is a frontend. It does not run the TTS model itself. It talks to a separate backend server - the author's Bjornulf_XTTS project - which you have to install and run alongside ComfyUI. Without that server running, this node can only replay audio it already generated.
How it works
When you run it, the node sends your text, language, and chosen voice sample to the XTTS server (by default at localhost:8020), gets back synthesized audio, and saves it under ComfyUI/Bjornulf_TTS/ in a folder path built from the language, the voice name, and the text. Here's the clever part: if you run the same node again with identical settings, it finds the already-generated file and just plays it back - no server call, no VRAM used. So once you've generated a line, you can turn the TTS server off (it eats ~3GB of VRAM) and the node still replays that audio. That's the intended way to run TTS alongside image generation without both fighting for VRAM.
The inputs and outputs that matter
text- the multiline text to speak.language- one of 17 (English, French, Japanese, etc.). Note you don't need a matching-language voice sample; any voice can speak any language.speaker_wav- which voice sample to use (defaultdefault). This points at a.wavin thespeakersfolder you set up (see install).overwrite- off (default) reuses the cached file if it exists; on regenerates. Flip it on when you don't like a take and want a fresh one, then flip it back.autoplayandsave_audio- play inside the node on execution / write the file to disk.seed, plus optionalconnect_to_workflow(a wildcard passthrough so you can pre-generate audio in a standalone workflow) andTTS_URL/TTS_LANGUAGE/TTS_SPEAKERinputs from the pack's TTS Configuration node.
Outputs: AUDIO (wire it into a Preview Audio node - the author says this node should always connect to one), plus audio_path, audio_full_path, and audio_duration for chaining into video/sync nodes like MuseTalk.
How to install it
ComfyUI Manager: search Bjornulf_custom_nodes, install, restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/justUmen/Bjornulf_custom_nodes
pip install -r Bjornulf_custom_nodes/requirements.txt
Then the extra steps this node specifically needs:
- Install and run the backend,
Bjornulf_XTTS(github.com/justUmen/Bjornulf_XTTS). This is what actually synthesizes speech. - Create a
speakerslink inside the node folder:ComfyUI/custom_nodes/Bjornulf_custom_nodes/speakers, pointing to wherever your voice samples (likedefault.wav) live. - Test the server in a browser:
http://localhost:8020/tts_stream?language=en&speaker_wav=default&text=Hello.
Common issues
The single biggest one: the node is Linux-first. The author states outright it's "never tested on Windows, only on Linux for now" - and confirmed the same thing publicly when releasing the pack. If you're on Windows, expect this node (and the video nodes) to be the rough edges.
After that, almost every failure is the backend. No audio and it tried to reach the server? The XTTS server isn't running, or isn't on port 8020, or the speakers link isn't set up so it can't find your .wav. Verify with the browser URL above before debugging the node. Remember the server wants ~3GB of VRAM, so if you're also generating images you'll likely want to generate the speech first (or use the pack's Pause node to stop the server before the heavy step). And if you're just replaying an existing line, you don't need the server up at all - that's the whole caching trick.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | โ | |
| language | COMBO | English | 17 options: Arabic, Czech, German, English, Spanish, French, +11 |
| speaker_wav | STRING | default | โ |
| autoplay | BOOLEAN | true | โ |
| save_audio | BOOLEAN | true | โ |
| overwrite | BOOLEAN | false | โ |
| seed | INT | 0 | โ |
| connect_to_workflowopt | * | โ | |
| TTS_URLopt | TTS_URL | โ | |
| TTS_LANGUAGEopt | TTS_LANGUAGE | โ | |
| TTS_SPEAKERopt | TTS_SPEAKER | โ |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| AUDIO | AUDIO | โ |
| audio_path | STRING | โ |
| audio_full_path | STRING | โ |
| audio_duration | FLOAT | โ |