EmpirioLabs AI Text to Speech
Skip the audio dependency stack
- audio
Audio is the newest, thinnest layer of the ComfyUI stack, and the tooling shows it. Local TTS works - Chatterbox is genuinely close to the paid bar, Kokoro runs on a CPU - but in ComfyUI it arrives inside node packs that each bring their own runtime, and the standing failure mode of that arrangement is dependency conflict: one audio suite's v5 rewrite existed largely because version fights between its own engines kept breaking installs. This node takes the other road. No model file, no third TTS runtime, one HTTP call.
When that's the right call
If you need a single voice line, a narration pass over a clip, or a scratch track to test an image-to-video pipeline, calling out beats installing a stack you'll maintain. If you're synthesizing an audiobook, fussy about a specific cloned voice, or want the output to stay on your machine, run Chatterbox or Higgs locally instead - the quality gap to hosted is real but no longer embarrassing, and the volume math flips fast once every sentence is billable. Hosted still wins the reliability-and-languages corner, at per-call prices and behind a filter you can't remove.
How it works
The node POSTs {"model", "input": <your text>} to /v1/audio/speech, adding voice if you set one. The response is handled generously, because speech APIs disagree about how to answer: if the server streams audio back directly it uses those bytes, and if it answers with JSON it either polls a job or downloads the file from the link it was given. Either way the file is decoded with PyAV into ComfyUI's AUDIO value - a float32 waveform tensor plus a sample_rate.
That sample rate is whatever the model returned. The node doesn't resample to a house standard, it just tells you what came back, which is worth remembering when you chain several TTS outputs into one edit.
The inputs that matter
There are only four, and one of them is optional:
model- combo from the EmpirioLabs catalog, filtered to speech models.tts-2-flashis the default and the fallback the pack uses when the catalog doesn't load.text- what to speak. Required; blank is an error, not an empty request.voice- a plain string, not a dropdown, and leaving it empty uses the model's default voice. Each model lists its voices on its catalog page, so the name has to match exactly - a typo isn't caught by the node, it comes back as an API error. Copy the string from the model page rather than typing it from memory.extra_parameters- JSON for anything else the model takes: speed, stability, style, whatever that model documents. It can't setmodelorinput, since those are the node's own. One small thing: the field's tooltip offers{"negative_prompt": "blurry"}as an example, which is copy-paste from the image node and meaningless for speech. Go to the model page for real fields.
There's no seed and no length control here - pitch and voice come from voice, and length comes from your text. Speeding it up is an extra_parameters question, not a knob on the node.
The single output is audio (AUDIO). Wire it to a Save Audio node to keep the file, or into whatever consumes audio - a video muxer, a lip-sync pipeline, an audio-reactive graph.
Install and the key
ComfyUI Manager → Custom Nodes Manager → search EmpirioLabs AI → install → restart. By hand:
cd ComfyUI/custom_nodes
git clone https://github.com/EmpirioLabs-AI/comfyui-empiriolabs.git
ComfyUI 0.3.48 or newer, because the pack uses the newer comfy_api node class rather than the legacy node mappings. Nothing extra to pip install.
The key comes from platform.empiriolabs.ai and starts sk-empiriolabs-. Put it in the EMPIRIOLABS_API_KEY environment variable and restart ComfyUI, or copy config.example.ini to config.ini in the pack folder and paste it after api_key = - that file is re-read every run, so no restart needed. Folder name differs by install route: custom_nodes/comfyui-empiriolabs for git, custom_nodes/empiriolabs for the registry version.
Where it goes wrong
An unknown voice. The API returns its own message plus a request ID. The node shows it as-is; read it, it usually names the voice it didn't recognise.
Long text, short result. Speech models have length ceilings, and the node won't chunk for you. Split narration into paragraphs and join the pieces afterwards.
One model in the dropdown. The catalog didn't load at startup. The node still works on its single fallback model and quietly retries; reload the browser page to get the full list.
Surprise bills. Every run is a request and every request is metered, which is exactly why a save node at the end is not optional - the underlying file link expires.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| model | COMBO | tts-2-flash | Text to speech model from the EmpirioLabs AI catalog. Prices and details: https://empiriolabs.ai/models |
| text | STRING | The text to speak. | |
| voiceopt | STRING | Voice for the selected model. Leave empty to use the model's default voice. Each model lists its voices on its page at https://empiriolabs.ai/models. | |
| extra_parametersopt | STRING | Optional request fields as a JSON object, for example {"negative_prompt": "blurry"}. Each model lists the fields it accepts on its page at https://empiriolabs.ai/models. Fields set here take precedence over the dropdowns above. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |