LTX 2.3 - Lipdub LoRA + Voice Clone
Upload a driving video and prompt the desired dialogue to generate a lipdub of your video using LTX 2.3. The workflow then clones your dubbed audio back to the original character's voice using Chatterbox. It is a fully open source workflow for changing the speech of your character from a driving video.
ワークフローの内部
ソーステンプレートの読み取り専用プレビューです。Cloud で開くと、ノードを確認して変更できます。
Loading the graph
Open full-size workflow preview- 出力
- 動画
- 作成者
- Rob
コードからこのモデルを呼び出す
以下のリクエストでは、Playground と同じ準備済みグラフと設定を使用します。送信ごとに有料実行が開始される場合があります。結果が不明な送信を自動的に再試行しないでください。
What you need
- Runs on
- Comfy Cloud
- キー
- COMFY_API_KEY
- ファイル
- コードによって URL からアップロードされます
有料の Cloud プランとクレジットが必要です。
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"5046": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "output_ltx",
"format": "auto",
"format.codec": "auto",
"video": [
"5049:4849",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"5047": {
"class_type": "LoadVideo",
"inputs": {
"file": "UPLOADED_video_FILENAME"
},
"_meta": {
"title": "Load Video"
}
},
"5048": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "A lean East Asian man in his late forties with swept-back black hair touched with silver at the temples stands on a rainy shopping street, rimless sunglasses pushed up on his head, wearing a loose grey overshirt over a blue button-down shirt. He holds a small silver flip phone at chest height, looks straight into the camera with a dry, amused half smile and raised eyebrows, and speaks in a calm, low, slightly amused voice in English, saying: \"Found it in a drawer last night. Twenty years old, and it still rings.\" Pedestrians with clear umbrellas pass softly out of focus behind him, wet pavement reflects the shop lights, steady camera, natural head and hand movement."
},
"_meta": {
"title": "Prompt"
}
},
"5050": {
"class_type": "GetVideoComponents",
"inputs": {
"video": [
"5047",
0
]
},
"_meta": {
"title": "Get Video Components"
}
},
"5051": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "{DIALOGUE}",
"replace": [
"5052",
0
],
"string": [
"5048",
0
]
},
"_meta": {
"title": "Create Prompt"
}
},
"5052": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "Lipdub workflow is now live on Comfy Hub."
},
"_meta": {
"title": "Dialogue"
}
},
"5053": {
"class_type": "CreateVideo",
"inputs": {
"audio": [
"5055",
0
],
"bit_depth": "auto",
"codec": "none",
"color_space": "sRGB",
"fps": [
"5050",
2
],
"images": [
"5049:4995",
0
]
},
"_meta": {
"title": "Create Video"
}
},
"5054": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "output_ltx_chatterbox",
"format": "auto",
"format.codec": "auto",
"video": [
"5053",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"5055": {
"class_type": "FL_ChatterboxVC",
"inputs": {
"input_audio": [
"5049:4848",
0
],
"keep_model_loaded": True,
"seed": 12345,
"target_voice": [
"5050",
1
],
"use_cpu": False
},
"_meta": {
"title": "FL Chatterbox VC"
}
},
"5049:1241": {
"class_type": "LTXVConditioning",
"inputs": {
"frame_rate": [
"5049:5010",
2
],
"negative": [
"5049:2612",
0
],
"positive": [
"5049:2483",
0
]
},
"_meta": {
"title": "LTXVConditioning"
}
},
"5049:2483": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"5049:4982",
0
],
"text": [
"5051",
0
]
},
"_meta": {
"title": "CLIP Text Encode (Positive Prompt)"
}
},
"5049:2612": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"5049:4982",
0
],
"text": "pc game, console game, video game, cartoon, childish, ugly"
},
"_meta": {
"title": "CLIP Text Encode (Negative Prompt)"
}
},
"5049:3059": {
"class_type": "EmptyLTXVLatentVideo",
"inputs": {
"batch_size": 1,
"height": [
"5049:5023",
2
],
"length": [
"5049:5025",
1
],
"width": [
"5049:5023",
1
]
},
"_meta": {
"title": "Empty LTXV Latent Video"
}
},
"5049:3980": {
"class_type": "LTXVEmptyLatentAudio",
"inputs": {
"audio_vae": [
"5049:4010",
0
],
"batch_size": 1,
"frame_rate": [
"5049:5000",
0
],
"frames_number": [
"5049:5025",
1
]
},
"_meta": {
"title": "Empty LTXV Latent Audio"
}
},
"5049:4010": {
"class_type": "LTXVAudioVAELoader",
"inputs": {
"ckpt_name": "ltx-2.3-22b-dev.safetensors"
},
"_meta": {
"title": "Load LTXV Audio VAE"
}
},
"5049:4528": {
"class_type": "LTXVConcatAVLatent",
"inputs": {
"audio_latent": [
"5049:3980",
0
],
"video_latent": [
"5049:5004",
2
]
},
"_meta": {
"title": "Concat AV Latent"
}
},
"5049:4828": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 1,
"model": [
"5049:5102",
0
],
"negative": [
"5049:5006",
1
],
"positive": [
"5049:5006",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"5049:4829": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"5049:4828",
0
],
"latent_image": [
"5049:4528",
0
],
"noise": [
"5049:4832",
0
],
"sampler": [
"5049:4831",
0
],
"sigmas": [
"5049:4984",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"5049:4831": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "euler"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"5049:4832": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 1
},
"_meta": {
"title": "RandomNoise"
}
},
"5049:4845": {
"class_type": "LTXVSeparateAVLatent",
"inputs": {
"av_latent": [
"5049:4829",
0
]
},
"_meta": {
"title": "Separate AV Latent"
}
},
"5049:4848": {
"class_type": "LTXVAudioVAEDecode",
"inputs": {
"audio_vae": [
"5049:4010",
0
],
"samples": [
"5049:4973",
1
]
},
"_meta": {
"title": "LTXV Audio VAE Decode"
}
},
"5049:4849": {
"class_type": "CreateVideo",
"inputs": {
"audio": [
"5049:4848",
0
],
"bit_depth": "auto",
"codec": "none",
"color_space": "sRGB",
"fps": [
"5049:5010",
2
],
"images": [
"5049:4995",
0
]
},
"_meta": {
"title": "Create Video"
}
},
"5049:4964": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 1,
"model": [
"5049:5102",
0
],
"negative": [
"5049:5014",
1
],
"positive": [
"5049:5014",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"5049:4967": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 222
},
"_meta": {
"title": "RandomNoise"
}
},
"5049:4969": {
"class_type": "LTXVConcatAVLatent",
"inputs": {
"audio_latent": [
"5049:5013",
2
],
"video_latent": [
"5049:5014",
2
]
},
"_meta": {
"title": "Concat AV Latent"
}
},
"5049:4971": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"5049:4964",
0
],
"latent_image": [
"5049:4969",
0
],
"noise": [
"5049:4967",
0
],
"sampler": [
"5049:4976",
0
],
"sigmas": [
"5049:4985",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"5049:4973": {
"class_type": "LTXVSeparateAVLatent",
"inputs": {
"av_latent": [
"5049:4971",
0
]
},
"_meta": {
"title": "Separate AV Latent"
}
},
"5049:4974": {
"class_type": "LatentUpscaleModelLoader",
"inputs": {
"model_name": "ltx-2.3-spatial-upscaler-x2-1.1.safetensors"
},
"_meta": {
"title": "Load Latent Upscale Model"
}
},
"5049:4975": {
"class_type": "LTXVLatentUpsampler",
"inputs": {
"samples": [
"5049:5011",
2
],
"upscale_model": [
"5049:4974",
0
],
"vae": [
"5049:5017",
2
]
},
"_meta": {
"title": "LTXVLatentUpsampler"
}
},
"5049:4976": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "euler"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"5049:4982": {
"class_type": "LTXAVTextEncoderLoader",
"inputs": {
"ckpt_name": "ltx-2.3-22b-dev.safetensors",
"device": "default",
"text_encoder": "gemma_3_12B_it_fp4_mixed.safetensors"
},
"_meta": {
"title": "Load LTXV Audio Text Encoder"
}
},
"5049:4984": {
"class_type": "ManualSigmas",
"inputs": {
"sigmas": "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0"
},
"_meta": {
"title": "ManualSigmas"
}
},
"5049:4985": {
"class_type": "ManualSigmas",
"inputs": {
"sigmas": "0.909375, 0.725, 0.421875, 0.0"
},
"_meta": {
"title": "ManualSigmas"
}
},
"5049:4995": {
"class_type": "LTXVTiledVAEDecode",
"inputs": {
"horizontal_tiles": 2,
"last_frame_fix": False,
"latents": [
"5049:5015",
2
],
"overlap": 6,
"vae": [
"5049:5017",
2
],
"vertical_tiles": 2,
"working_device": "auto",
"working_dtype": "auto"
},
"_meta": {
"title": "🅛🅣🅧 LTXV Tiled VAE Decode"
}
},
"5049:5000": {
"class_type": "LTXFloatToInt",
"inputs": {
"a": [
"5049:5010",
2
]
},
"_meta": {
"title": "🅛🅣🅧 Float To Int"
}
},
"5049:5003": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"input": [
"5049:5010",
0
],
"resize_type": "scale dimensions",
"resize_type.crop": "disabled",
"resize_type.height": [
"5049:5101",
1
],
"resize_type.width": [
"5049:5100",
1
],
"scale_method": "area"
},
"_meta": {
"title": "Resize Image/Mask (s2 size)"
}
},
"5049:5004": {
"class_type": "LTXAddVideoICLoRAGuide",
"inputs": {
"crop": "disabled",
"frame_idx": 0,
"image": [
"5049:5009",
0
],
"latent": [
"5049:3059",
0
],
"latent_downscale_factor": 1,
"negative": [
"5049:1241",
1
],
"positive": [
"5049:1241",
0
],
"strength": 1,
"tile_frames": 97,
"tile_overlap": 64,
"tile_size": 256,
"use_streaming": False,
"use_tiled_encode": True,
"vae": [
"5049:5017",
2
]
},
"_meta": {
"title": "🅛🅣🅧 Add Video IC-LoRA Guide"
}
},
"5049:5005": {
"class_type": "LTXVAudioVAEEncode",
"inputs": {
"audio": [
"5049:5010",
1
],
"audio_vae": [
"5049:4010",
0
]
},
"_meta": {
"title": "LTXV Audio VAE Encode"
}
},
"5049:5006": {
"class_type": "LTXVSetAudioRefTokens",
"inputs": {
"audio_latent": [
"5049:5005",
0
],
"negative": [
"5049:5004",
1
],
"positive": [
"5049:5004",
0
]
},
"_meta": {
"title": "🅛🅣🅧 Set Audio Ref Tokens"
}
},
"5049:5009": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"input": [
"5049:5010",
0
],
"resize_type": "scale dimensions",
"resize_type.crop": "disabled",
"resize_type.height": 544,
"resize_type.width": 960,
"scale_method": "area"
},
"_meta": {
"title": "Resize Image/Mask (s1 size)"
}
},
"5049:5010": {
"class_type": "GetVideoComponents",
"inputs": {
"video": [
"5047",
0
]
},
"_meta": {
"title": "Get Video Components"
}
},
"5049:5011": {
"class_type": "LTXVCropGuides",
"inputs": {
"latent": [
"5049:4845",
0
],
"negative": [
"5049:5004",
1
],
"positive": [
"5049:5004",
0
]
},
"_meta": {
"title": "LTXVCropGuides"
}
},
"5049:5013": {
"class_type": "LTXVSetAudioRefTokens",
"inputs": {
"audio_latent": [
"5049:4845",
1
],
"negative": [
"5049:5011",
1
],
"positive": [
"5049:5011",
0
]
},
"_meta": {
"title": "🅛🅣🅧 Set Audio Ref Tokens"
}
},
"5049:5014": {
"class_type": "LTXAddVideoICLoRAGuide",
"inputs": {
"crop": "disabled",
"frame_idx": 0,
"image": [
"5049:5003",
0
],
"latent": [
"5049:4975",
0
],
"latent_downscale_factor": 1,
"negative": [
"5049:5013",
1
],
"positive": [
"5049:5013",
0
],
"strength": 1,
"tile_frames": 97,
"tile_overlap": 64,
"tile_size": 256,
"use_streaming": False,
"use_tiled_encode": True,
"vae": [
"5049:5017",
2
]
},
"_meta": {
"title": "🅛🅣🅧 Add Video IC-LoRA Guide"
}
},
"5049:5015": {
"class_type": "LTXVCropGuides",
"inputs": {
"latent": [
"5049:4973",
0
],
"negative": [
"5049:5014",
1
],
"positive": [
"5049:5014",
0
]
},
"_meta": {
"title": "LTXVCropGuides"
}
},
"5049:5017": {
"class_type": "CheckpointLoaderSimple",
"inputs": {
"ckpt_name": "ltx-2.3-22b-dev.safetensors"
},
"_meta": {
"title": "Load Checkpoint"
}
},
"5049:5018": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "ltx-2.3-22b-distilled-lora-384-1.1.safetensors",
"model": [
"5049:5017",
0
],
"strength_model": 0.5
},
"_meta": {
"title": "Load LoRA"
}
},
"5049:5023": {
"class_type": "GetImageSizeAndCount",
"inputs": {
"image": [
"5049:5009",
0
]
},
"_meta": {
"title": "Get Image Size & Count"
}
},
"5049:5025": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "(int((a - 1) / 8)) * 8 + 1",
"values.a": [
"5049:5023",
3
]
},
"_meta": {
"title": "Math Expression"
}
},
"5049:5091": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"resize_type": "scale dimensions",
"resize_type.crop": "center",
"resize_type.height": 960,
"resize_type.width": 544,
"scale_method": "area"
},
"_meta": {
"title": "Resize Image/Mask"
}
},
"5049:5096": {
"class_type": "EmptyLTXVLatentVideo",
"inputs": {
"batch_size": 1,
"height": 544,
"length": 121,
"width": 960
},
"_meta": {
"title": "Empty LTXV Latent Video"
}
},
"5049:5100": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "a * 2",
"values.a": [
"5049:5023",
1
]
},
"_meta": {
"title": "Upscaled Width"
}
},
"5049:5101": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "a * 2",
"values.a": [
"5049:5023",
2
]
},
"_meta": {
"title": "Upscaled Height"
}
},
"5049:5102": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "ltx-2.3-22b-ic-lora-lipdub-0.9.safetensors",
"model": [
"5049:5018",
0
],
"strength_model": 1
},
"_meta": {
"title": "Load LoRA"
}
}
})
workflow.set_input("5047", "file", client.assets.from_url("https://comfy.org/catalog-media/8ec5c8bc-e1b1-4b48-8f57-cf50721ff00c/4d895a2f-b562-4898-8318-e65cdacbe834"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)
for output in job.get_outputs("5054"):
output.to_file(output.name)
for output in job.get_outputs("5046"):
output.to_file(output.name)例を試す
このワークフローについて
This workflow builds a full, open‑source lip‑dub pipeline around LTX 2.3 and Chatterbox voice conversion. You provide a "driving" video of a person speaking, plus the dialogue you want them to say. LoadVideo ingests your clip, and GetVideoComponents extracts frames, FPS, and the original audio. Your typed dialogue flows from a PrimitiveStringMultiline prompt through RegexReplace to clean punctuation and spacing, then into the LTX 2.3 Lipdub node (the custom node with ID 1e1eaad5-a949-4d3e-9a68-694e64a936a0).
That node applies a Lipdub LoRA finetune to LTX 2.3 to retime mouth shapes to your script while preserving the subject’s identity, head motion, and scene context.
For audio, the same dialogue drives a temporary dub track that’s then passed to FL_ChatterboxVC. Using the original video’s audio (from GetVideoComponents) as a voice reference, Chatterbox VC re-voices the dub so it matches the speaker’s timbre and vocal traits. Finally, CreateVideo assembles the edited frames and cloned audio at the source FPS, and SaveVideo writes the final lip‑synced render. Note the dimension rule from the MarkdownNote: set input width × height to half your intended final size (for example, 960×544 in gives ~1920×1088 out).
よくある質問
This workflow expects input width × height to be half of your desired output, as noted in the MarkdownNote. For example, 960×544 in will render about 1920×1088 out. Halve your target resolution when setting inputs.
FL_ChatterboxVC uses the original video’s audio (from GetVideoComponents) as a voice reference. It converts the generated dub audio to match the target speaker’s timbre and style, so the lips match your script while the voice still sounds like the on-screen person.
Start with the text: add or remove brief pauses via punctuation (commas/periods), keep sentences concise, and avoid long, run-on phrases. Ensure the CreateVideo FPS matches the source FPS. Clear, front-facing footage with unobstructed lips also improves alignment.
Use short to medium clips with stable lighting and a sharp view of the mouth. For the Chatterbox reference, cleaner speech (minimal music/noise) helps the conversion. If the original track is noisy, trim a clean segment for reference or apply light noise reduction upstream.