ComfyUI Node

MegaTTS3 Run

Real voice cloning in ComfyUI, no API key in sight

By billwuhao·Created about a year ago·Updated about a year ago· 211
MegaTTS3 Run
  • audio
  • dialogue_audio_s2
  • audio
text
time_step32
p_w1.60
t_w2.50
unload_modeltrue
audio_npy_file
audio_s2_npy_file

The name sounds like an API wrapper, and that's the first thing to unlearn: MegaTTS3 Run doesn't call any API and needs no key. It's the workhorse of a fully local voice-cloning pack built around ByteDance's open MegaTTS3 model. Drop in a reference clip, type what you want it to say, and you get audio out - in Chinese, in English, or in a cross-lingual mix where a Chinese voice reads your English lines. No ElevenLabs subscription, no uploads, just a ComfyUI graph.

Why you'd reach for it

You want a voice cloned for narration, an audiobook, a character in a video, or a lip-sync pipeline, and you don't want to ship audio anywhere. Among people who have actually benchmarked local TTS, MegaTTS3 lands as the "kept as a backup" pick next to Zonos and IndexTTS - not the fastest model around, but a genuinely good zero-shot cloner. What makes this node notable in that crowd is that it lives inside ComfyUI, so the same graph that renders your frames can also produce their dialogue. The pack's party tricks: extra-long text, and a two-person dialogue mode where speaker labels switch between two cloned voices mid-sentence.

How it works

The reference audio gets aligned into phone/tone sequences by a Whisper-small aligner, a duration LM predicts timing, a diffusion transformer generates new speech conditioned on that prompt, and a WaveVAE decodes it back into a waveform. Long text is chunked automatically (roughly 60 chars a segment for Chinese, 130 for English) and stitched together, with output volume normalized to match the reference clip. All of it runs locally, fp16, and the code falls back to CPU if you have no CUDA - slow there, but it works.

The inputs that actually matter

  • audio - the reference clip whose voice you're cloning. Wire it from the pack's Speakers Preview node, or any AUDIO source.
  • text - a forced-input STRING, so you must wire a text node into it (this is exactly why the pack ships its own Multi Line Text node). Blank lines separate utterances; in dialogue mode you use [S1] and [S2] tags.
  • time_step (default 32) - diffusion sampling steps for the transformer. More steps means crisper output and more waiting; the defaults are a sane place to start.
  • p_w (1.6) and t_w (2.5) - the phone and tone CFG weights. If the cloned voice sounds too flat, nudge t_w up before you touch anything else.
  • unload_model (default True) - tears down the loaded checkpoints after each run to free VRAM. Flip it to False when generating a batch, or you'll pay the reload cost on every single generation.
  • dialogue_audio_s2 (optional) - the second speaker's clip for two-person dialogue.
  • audio_npy_file / audio_s2_npy_file (optional) - precomputed voice latents, if you have them.

One output, audio - wire it into a Preview Audio or Save Audio node to hear or export the result.

Installing it

Install the pack once, then reuse it across all its nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/billwuhao/ComfyUI_MegaTTS3.git
cd ComfyUI_MegaTTS3
pip install -r requirements.txt

On Windows you first need to install the pynini wheel from the author's pynini-windows-wheels releases matching your Python version, plus importlib_resources and WeTextProcessing>=1.0.4 --no-deps - the README has the exact commands. Then download the ByteDance MegaTTS3 model folder from Hugging Face into ComfyUI/models/TTS/MegaTTS3, and drop reference clips into ComfyUI/models/TTS/speakers. ComfyUI Manager works too: search for "MW-ComfyUI_MegaTTS3".

Where people get burned

The big one is the VAE encoder. The stock Hugging Face download only includes the WaveVAE decoder, and without the encoder (wavvae/model_only_last.ckpt) the node refuses to encode a raw reference clip and demands an .npy latent file instead. The author gates that encoder checkpoint behind a WeChat QR code linking to a Google Drive folder - a real speed bump if you're outside that loop. If you can't get it, you'll need precomputed .npy latents for your speakers.

Second, remember text is forced-input: a bare widget won't cut it, and since blank lines are meaningful, whatever text node you use has to preserve them. Third, leave unload_model on True if you only generate occasionally, but expect the several-model reload each time - it's the default and it does cost you. And the language auto-detect treats anything non-English as Chinese, so keep each paragraph to one language if you want clean output.

Category🎤MW/MW-MegaTTS3

Inputs (9)

NameTypeDefaultDescription
audioAUDIO
textSTRING
time_stepINT32
p_wFLOAT1.60
t_wFLOAT2.50
unload_modelBOOLEANtrue
dialogue_audio_s2optAUDIO
audio_npy_fileoptSTRINGNo `npy_file` will use VAE to encode audio. 不提供 .npy 文件, 将使用 WaveVAE 编码音频
audio_s2_npy_fileoptSTRINGNo `npy_file` will use VAE to encode audio. 不提供 .npy 文件, 将使用 WaveVAE 编码音频

Outputs (1)

NameTypeDescription
audioAUDIO