Qwen3-TTS Finetune
Train a real dedicated voice inside ComfyUI — and what those VRAM knobs actually do
- model_path
- custom_speaker_name
Qwen3-TTS Finetune is the serious node in this pack, and the reason most people install it: it trains a dedicated model on your own voice data. Where Voice Clone extracts a voice from a short reference clip, fine-tuning teaches the whole model to be that voice - the difference between a thin imitation and a stable, high-fidelity speaker. It's a genuine training loop running inside ComfyUI, with all the VRAM-management muscle that implies, and it's the closest thing this pack has to LoRA training, except it's a full fine-tune of the Base model rather than a small adapter.
Fair warning before you dive in: this is not a two-minute node. It expects a properly prepared pipeline (Dataset Maker → Data Prep → this node), downloads the Base model if you haven't got it, and a real fine-tune on a 1.7B model takes a while on a consumer GPU. If you just want a character voice for a quick clip, Voice Clone is the cheaper path. If you need a speaker you can trust across hours of content, fine-tune.
What it trains
The key input is init_model, and it's restricted to the Base variants (Qwen/Qwen3-TTS-12Hz-1.7B-Base or the 0.6B) - the CustomVoice/VoiceDesign checkpoints are excluded because you can't sensibly train on top of a preset-voice model. The node loads the Base model, enables gradients on everything, and trains with a proper optimizer loop: AdamW (or 8-bit AdamW if bitsandbytes is installed and use_8bit_optimizer is on), bf16 mixed precision by default (auto-falling back to fp32 on pre-Ampere GPUs), and the training data comes from the train_jsonl you wired in.
Two design choices the author got right, and they're baked into the tooltips:
lrdefaults to 2e-6, not the 2e-5 Qwen ships with. The tooltip explains: "Qwen default (2e-5) is too aggressive for small batches, causing noise output." If you've ever fine-tuned a TTS and gotten crackly garbage, this is that exact failure pre-solved. Leave it at 2e-6.speaker_nameis how you summon the trained voice later. The node outputs it back to you (custom_speaker_name), and you type it into Qwen3-TTS Custom Voice'scustom_speaker_namefield to generate with the trained voice - it won't show up in the preset dropdown.
The inputs that matter
The VRAM trinity is where beginners should look first:
gradient_checkpointing(default on) - recomputes activations instead of storing them, ~30-40% VRAM savings.use_8bit_optimizer(default on) - 8-bit AdamW, ~50% less optimizer VRAM. Requiresbitsandbytes; the node silently falls back to regular AdamW and prints a note if it's missing.batch_size(default 2) +gradient_accumulation(default 4) - effective batch size isbatch_size × gradient_accumulation. Keepbatch_sizelow and let accumulation do the work on a small GPU.
save_every_epochs (default 1) writes per-epoch checkpoints into output_dir; resume_training picks up the most recent one and continues. save_optimizer_state doubles checkpoint size for a perfect resume - leave it off unless you're doing long multi-session trains. Both outputs, model_path and custom_speaker_name, are strings you feed back into the loader and generator.
Installing & troubleshooting
Pack install as usual: ComfyUI Manager (search "ComfyUI-Qwen3-TTS") or git clone https://github.com/DarioFT/ComfyUI-Qwen3-TTS into custom_nodes, pip install -r requirements.txt by hand. The qwen-tts transformers==4.57.3 pin is the sharpest edge here because you're about to add accelerate, librosa, tensorboard and a training stack to a shared environment - the README's advice about a separate Python env is aimed squarely at this node.
The classic failures: OOM during training (drop batch_size, keep gradient checkpointing on), noisy/crackly output (your learning rate drifted from 2e-6, or your dataset is bad - clean single-speaker clips), and a GPU pinned at 100% that never finishes (the known Qwen3-TTS hang; it's rarer in training but the kill-and-restart advice still applies). Training progress goes to the ComfyUI UI, so "is it alive?" is answered by watching the console.
When it works, load the checkpoint through Qwen3-TTS Loader's local_model_path (point at output_dir/epoch_X) and generate with Custom Voice using your speaker_name. That's the whole arc: data → train → evaluate → use.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| train_jsonl | STRING | Path to the preprocessed JSONL file containing training data with audio codes. | |
| init_model | COMBO | Qwen/Qwen3-TTS-12Hz-1.7B-Base | Base model to fine-tune. Must be a 'Base' model variant. |
| source | COMBO | HuggingFace | Download source if model is not found locally. |
| output_dir | STRING | output/finetuned_model | Directory to save checkpoints and final model. |
| epochs | INT | 31–1000 | Number of training epochs to run. |
| batch_size | INT | 21–64 | Number of samples per batch. Lower values use less VRAM. |
| lr | FLOAT | 0 | Learning rate. Qwen default (2e-5) is too aggressive for small batches, causing noise output. Defaults to 2e-6 for stability. |
| speaker_name | STRING | my_speaker | Name for the custom speaker. Use this name when generating with the fine-tuned model. |
| seed | INT | 420–18446744073709550000 | Random seed for reproducibility. |
| resume_trainingopt | BOOLEAN | false | Continue training from the latest checkpoint in output_dir. |
| log_every_stepsopt | INT | 101–1000 | Log training progress every N steps. |
| save_every_epochsopt | INT | 10–100 | Save checkpoint every N epochs. Set to 0 to only save final epoch. Ignored if save_every_steps > 0. |
| save_every_stepsopt | INT | 00–100000 | Save checkpoint every N steps. Set to 0 to use epoch-based saving instead. |
| mixed_precisionopt | COMBO | bf16 | bf16 recommended. Use fp32 only if GPU doesn't support bf16 (pre-Ampere). |
| gradient_accumulationopt | INT | 41–32 | Accumulate gradients over N steps before updating. Effective batch size = batch_size * gradient_accumulation. |
| gradient_checkpointingopt | BOOLEAN | true | Trade compute for VRAM by recomputing activations. Saves ~30-40% VRAM. |
| use_8bit_optimizeropt | BOOLEAN | true | Use 8-bit AdamW optimizer. Saves ~50% optimizer VRAM. Requires bitsandbytes. |
| weight_decayopt | FLOAT | 0.0100–1 | L2 regularization strength to prevent overfitting. |
| max_grad_normopt | FLOAT | 1.00.1–10 | Gradient clipping threshold to prevent exploding gradients. |
| warmup_stepsopt | INT | 00–10000 | Number of warmup steps. Set to 0 to disable warmup. Recommended: 5-10% of total steps. |
| warmup_ratioopt | FLOAT | 0.000–0.5 | Warmup as ratio of total steps. Ignored if warmup_steps > 0. E.g., 0.1 = 10% warmup. |
| save_optimizer_stateopt | BOOLEAN | false | Save optimizer/scheduler state in checkpoints. Enables perfect resume but doubles checkpoint size. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| model_path | STRING | — |
| custom_speaker_name | STRING | — |