Doubao 音色克隆 / Seed ICL 2.0 语音合成
Clone a voice, then make it read your script — one node, two very different jobs
- reference_audio
- api_config
- audio
- audio_url
- audio_path
- speaker
- task_id
- response
This node is two operations wearing one coat. On doubao-voice-clone it takes a short voice sample, trains a voice from it, and hands back a preview clip plus the ID you need later. On doubao-seed-icl-2.0 it takes that ID and makes the voice read whatever you type. Train, then speak. Getting that order right is basically the entire learning curve, and once it clicks this is one of the most immediately useful things in the pack.
Worth situating it: open TTS in ComfyUI is a real option - Kokoro for speed, Chatterbox for zero-shot cloning, F5-TTS for the fast path (audio-generation.md) - but those want a GPU and a download. This wants neither. It's ByteDance's Doubao voice stack behind an API call, and ByteDance keeps its flagship products hosted while the components ship free (bytedance.json), so there's no local version to wait for. The catch is the usual one: your sample and your script leave the machine.
What each mode actually does
In clone mode the payload carries a metadata.audio_url pointing at your uploaded WAV (or a public URL you paste in), plus optional custom_speaker_id, reference_text and language. The prompt in this mode is a 4–300 character preview line - the sentence the freshly trained voice says back to you. It is not a description of the voice. When the job finishes, the node reads the speaker ID out of the response and exposes it on the speaker output.
In ICL mode (doubao-seed-icl-2.0) speaker is required, and the metadata is a synthesis request: output format, sample_rate, speech_rate, loudness_rate, pitch, silence_duration, and a voice_model of seed-tts-2.0-standard or seed-tts-2.0-expressive. The prompt is now your actual script, 1–10000 characters.
The inputs you actually set
model decides which half of the node you're in, and the front-end hides the irrelevant fields when you switch - so clone-only fields like audio_url genuinely disappear in synthesis mode. That's not a bug, it's the reason the node doesn't look like a form from the tax office.
audio_url and the optional reference_audio input are exactly one or the other. Both filled, or neither, and validation stops you before submission. A connected AUDIO gets encoded to WAV and rejected above 10 MB; a pasted URL must be plain HTTP(S). The tooltip notes raw PCM needs 24 kHz mono.
language should match the recording - 0 Chinese, 1 English, or api_default to omit the code. The author validated this node with the English code on an English sample, and a mismatch is the quickest way to a strange-sounding clone.
custom_speaker_id is optional - 8–256 characters, must start with an English letter - and it's your friendly name for the voice. Don't confuse it with training_speaker_id, which hides behind advanced_mode and is the provider's ID. The tooltip is blunt about this because people mix them up: the handle you feed into a synthesis run comes from the speaker output, not from either field.
voice_model matters more than it looks: picking a specific model means context_texts is not sent. Want to instruct the read - "warm, slightly hushed, unhurried", up to 500 characters - and you have to leave voice_model on api_default. Keep advanced_mode off, too; it only reveals seventeen fields like bit rate, subtitle toggles, watermark and LaTeX parsing that you almost certainly don't want.
Outputs
audio is the decoded clip - 24 kHz out of a clone run - into Save Audio or a preview. audio_path is the local file, audio_url the temporary link, task_id the remote job, response the raw JSON. Then speaker, which is the whole point: wire it into a second copy of this node set to ICL.
Two nodes: clone → speaker → a second copy set to ICL, same API key both times, since the trained voice lives in that account. Pasting the ID by hand works, but wiring the output is the reliable path.
Install
Same pack as the rest - Manager search ComfyUI Seedance, or:
cd ComfyUI/custom_nodes
git clone https://github.com/T8mars/ComfyUI_Seedance.git
cd .. && python -m pip install -r custom_nodes/ComfyUI_Seedance/requirements.txt
That's requests>=2.28 and nothing else; no models to download. You still need a key (Seedance API Config node, SEEDANCE_API_KEY, or config/.env) and a restart.
Where people get burned
The clip is too big - the 10 MB encoded limit catches people who upload a two-minute sample when ten seconds of clean speech is plenty. The clone prompt is under four characters, or someone wrote a description there instead of the line to be spoken. A training run finishes but returns no speaker ("training succeeded without a speaker ID") - try a cleaner sample. And people paste custom_speaker_id into the synthesis node's speaker field and get nothing; that's not the handle.
Two practical notes. skip_error here returns one second of silence at 24 kHz so a batch keeps moving, so a silent output means a failed job, not a quiet voice. And cloning is a feature where the rules are yours to keep: get consent for any voice that isn't your own, because the model will happily make it say anything you type.
Inputs (40)
| Name | Type | Default | Description |
|---|---|---|---|
| model | COMBO | doubao-voice-clone | Clone trains a voice; ICL synthesizes with the returned speaker. | Clone 训练音色;ICL 用返回的 speaker 合成。 |
| prompt | STRING | Clone preview: 4-300 characters; synthesis: 1-10000. | 克隆试听文本 4-300 字符;合成文本 1-10000。 | |
| speaker | STRING | ICL: connect the training speaker output; use the same account. | ICL:连接训练 speaker 输出,使用同一账号。 | |
| audio_url | STRING | Clone: public sample URL, <=10 MB; OR local AUDIO. Raw PCM requires 24 kHz mono. | 克隆:10 MB 内语音直链,与本地音频二选一;裸 PCM 须为 24 kHz 单声道。 | |
| custom_speaker_id | STRING | Optional ID: 8-256 characters, English initial. Blank lets the API assign it. | 可选 ID:8-256 字符,英文字母开头;留空由服务分配。 | |
| language | COMBO | api_default | Match the recording: 0=Chinese, 1=English. api_default omits the code. | 匹配样本语种:0 中文、1 英语;api_default 不提交代码。 |
| reference_text | STRING | Matching transcript, at most 2000 characters. | 对应参考音频文本,最多 2000 字符。 | |
| enable_audio_denoise | COMBO | api_default | 3 options: api_default, enabled, disabled |
| disable_volume_normalization | COMBO | api_default | 3 options: api_default, enabled, disabled |
| voice_model | COMBO | seed-tts-2.0-standard | Specified models omit context_texts instructions. | 指定模型时不提交 context_texts 指令。 |
| output_format | COMBO | mp3 | 4 options: wav, mp3, pcm, ogg_opus |
| sample_rate | COMBO | 24000 | 7 options: 8000, 16000, 22050, 24000, 32000, 44100, +1 |
| speech_rate | FLOAT | 0-50–100 | — |
| loudness_rate | FLOAT | 0-50–100 | — |
| pitch | FLOAT | 0-12–12 | — |
| explicit_language | COMBO | api_default | 17 options: api_default, zh-cn, en, ja, es-mx, id, +11 |
| context_texts | STRING | Voice instructions <=500 characters, only with voice_model=api_default. | 音色指令最多 500 字符,仅 voice_model=api_default 时生效。 | |
| advanced_mode | BOOLEAN | false | — |
| training_speaker_id | STRING | Provider training ID, NOT custom_speaker_id. | 上游训练 ID,不是 custom_speaker_id。 | |
| bit_rate | INT | 00–160000 | 0 omits the setting; explicit range 16000-160000. | 0 不提交;手动范围 16000-160000。 |
| max_length_to_filter_parenthesis | COMBO | api_default | 3 options: api_default, 0, 100 |
| silence_duration | INT | 00–30000 | — |
| enable_subtitle | COMBO | api_default | 3 options: api_default, enabled, disabled |
| disable_markdown_filter | COMBO | api_default | 3 options: api_default, enabled, disabled |
| disable_emoji_filter | COMBO | api_default | 3 options: api_default, enabled, disabled |
| enable_latex_tn | COMBO | api_default | 3 options: api_default, enabled, disabled |
| aigc_watermark | COMBO | api_default | 3 options: api_default, enabled, disabled |
| disable_default_bit_rate | COMBO | api_default | 3 options: api_default, enabled, disabled |
| tone_fidelity | COMBO | api_default | 3 options: api_default, enabled, disabled |
| aigc_metadata_enable | COMBO | api_default | 3 options: api_default, enabled, disabled |
| latex_parser | COMBO | api_default | 2 options: api_default, v2 |
| section_id | STRING | — | |
| aigc_metadata_content_producer | STRING | — | |
| aigc_metadata_produce_id | STRING | — | |
| aigc_metadata_content_propagator | STRING | — | |
| aigc_metadata_propagate_id | STRING | — | |
| reference_audioopt | AUDIO | One clear voice sample; encoded WAV <=10 MB. | 一段清晰人声,编码后 WAV 不超过 10 MB。 | |
| api_configopt | SEEDANCE_CONFIG | — | |
| skip_erroropt | BOOLEAN | false | — |
| seedopt | INT | 00–18446744073709550000 | ComfyUI cache seed. Fixed reuses the cached result while all other inputs stay unchanged; randomize/increment/decrement starts a new execution. This value is not sent to models without documented seed support. | ComfyUI 缓存种子;Fixed 在其他输入不变时复用缓存,随机、递增或递减会触发新任务。未声明支持 seed 的模型不会收到此参数。 |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |
| audio_url | STRING | — |
| audio_path | STRING | — |
| speaker | STRING | — |
| task_id | STRING | — |
| response | STRING | — |