Nodes/ComfyUI Seedance/Doubao 音色克隆 / Seed ICL 2.0 语音合成
ComfyUI Node

Doubao 音色克隆 / Seed ICL 2.0 语音合成

Clone a voice, then make it read your script — one node, two very different jobs

By T8mars·Created 4 months ago·Updated 3 days ago· 43
Doubao 音色克隆 / Seed ICL 2.0 语音合成
  • reference_audio
  • api_config
  • audio
  • audio_url
  • audio_path
  • speaker
  • task_id
  • response
◄modeldoubao-voice-clone►
◄prompt►
◄speaker►
◄audio_url►
◄custom_speaker_id►
◄languageapi_default►
◄reference_text►
◄enable_audio_denoiseapi_default►
◄disable_volume_normalizationapi_default►
◄voice_modelseed-tts-2.0-standard►
◄output_formatmp3►
◄sample_rate24000►
◄speech_rate0►
◄loudness_rate0►
◄pitch0►
◄explicit_languageapi_default►
◄context_texts►
◄advanced_modefalse►
◄training_speaker_id►
◄bit_rate0►
◄max_length_to_filter_parenthesisapi_default►
◄silence_duration0►
◄enable_subtitleapi_default►
◄disable_markdown_filterapi_default►
◄disable_emoji_filterapi_default►
◄enable_latex_tnapi_default►
◄aigc_watermarkapi_default►
◄disable_default_bit_rateapi_default►
◄tone_fidelityapi_default►
◄aigc_metadata_enableapi_default►
◄latex_parserapi_default►
◄section_id►
◄aigc_metadata_content_producer►
◄aigc_metadata_produce_id►
◄aigc_metadata_content_propagator►
◄aigc_metadata_propagate_id►
◄skip_errorfalse►
◄seed0►

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.

CategorySeedance

Inputs (40)

NameTypeDefaultDescription
modelCOMBOdoubao-voice-cloneClone trains a voice; ICL synthesizes with the returned speaker. | Clone 训练音色;ICL 用返回的 speaker 合成。
promptSTRINGClone preview: 4-300 characters; synthesis: 1-10000. | 克隆试听文本 4-300 字符;合成文本 1-10000。
speakerSTRINGICL: connect the training speaker output; use the same account. | ICL:连接训练 speaker 输出,使用同一账号。
audio_urlSTRINGClone: public sample URL, <=10 MB; OR local AUDIO. Raw PCM requires 24 kHz mono. | 克隆:10 MB 内语音直链,与本地音频二选一;裸 PCM 须为 24 kHz 单声道。
custom_speaker_idSTRINGOptional ID: 8-256 characters, English initial. Blank lets the API assign it. | 可选 ID:8-256 字符,英文字母开头;留空由服务分配。
languageCOMBOapi_defaultMatch the recording: 0=Chinese, 1=English. api_default omits the code. | 匹配样本语种:0 中文、1 英语;api_default 不提交代码。
reference_textSTRINGMatching transcript, at most 2000 characters. | 对应参考音频文本,最多 2000 字符。
enable_audio_denoiseCOMBOapi_default3 options: api_default, enabled, disabled
disable_volume_normalizationCOMBOapi_default3 options: api_default, enabled, disabled
voice_modelCOMBOseed-tts-2.0-standardSpecified models omit context_texts instructions. | 指定模型时不提交 context_texts 指令。
output_formatCOMBOmp34 options: wav, mp3, pcm, ogg_opus
sample_rateCOMBO240007 options: 8000, 16000, 22050, 24000, 32000, 44100, +1
speech_rateFLOAT0-50–100—
loudness_rateFLOAT0-50–100—
pitchFLOAT0-12–12—
explicit_languageCOMBOapi_default17 options: api_default, zh-cn, en, ja, es-mx, id, +11
context_textsSTRINGVoice instructions <=500 characters, only with voice_model=api_default. | 音色指令最多 500 字符,仅 voice_model=api_default 时生效。
advanced_modeBOOLEANfalse—
training_speaker_idSTRINGProvider training ID, NOT custom_speaker_id. | 上游训练 ID,不是 custom_speaker_id。
bit_rateINT00–1600000 omits the setting; explicit range 16000-160000. | 0 不提交;手动范围 16000-160000。
max_length_to_filter_parenthesisCOMBOapi_default3 options: api_default, 0, 100
silence_durationINT00–30000—
enable_subtitleCOMBOapi_default3 options: api_default, enabled, disabled
disable_markdown_filterCOMBOapi_default3 options: api_default, enabled, disabled
disable_emoji_filterCOMBOapi_default3 options: api_default, enabled, disabled
enable_latex_tnCOMBOapi_default3 options: api_default, enabled, disabled
aigc_watermarkCOMBOapi_default3 options: api_default, enabled, disabled
disable_default_bit_rateCOMBOapi_default3 options: api_default, enabled, disabled
tone_fidelityCOMBOapi_default3 options: api_default, enabled, disabled
aigc_metadata_enableCOMBOapi_default3 options: api_default, enabled, disabled
latex_parserCOMBOapi_default2 options: api_default, v2
section_idSTRING—
aigc_metadata_content_producerSTRING—
aigc_metadata_produce_idSTRING—
aigc_metadata_content_propagatorSTRING—
aigc_metadata_propagate_idSTRING—
reference_audiooptAUDIOOne clear voice sample; encoded WAV <=10 MB. | 一段清晰人声,编码后 WAV 不超过 10 MB。
api_configoptSEEDANCE_CONFIG—
skip_erroroptBOOLEANfalse—
seedoptINT00–18446744073709550000ComfyUI 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)

NameTypeDescription
audioAUDIO—
audio_urlSTRING—
audio_pathSTRING—
speakerSTRING—
task_idSTRING—
responseSTRING—