# 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({
"125": {
"class_type": "LoadAudio",
"inputs": {
"audio": "UPLOADED_audio_FILENAME"
},
"_meta": {
"title": "Load Audio"
}
},
"284": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_FILENAME"
},
"_meta": {
"title": "Load Image"
}
},
"325": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "video/ComfyUI",
"format": "auto",
"format.codec": "auto",
"video": [
"330:334",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"330:331": {
"class_type": "WanVideoDecode",
"inputs": {
"enable_vae_tiling": False,
"normalization": "default",
"samples": [
"330:333",
0
],
"tile_stride_x": 144,
"tile_stride_y": 128,
"tile_x": 272,
"tile_y": 272,
"vae": [
"330:347",
0
]
},
"_meta": {
"title": "WanVideo Decode"
}
},
"330:332": {
"class_type": "WanVideoTextEncodeCached",
"inputs": {
"device": "gpu",
"model_name": "umt5-xxl-enc-bf16.safetensors",
"negative_prompt": "bright tones, overexposed, static, blurred details, subtitles, static, overall gray, worst quality, low quality, JPEG compression residue, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, fused fingers, still picture, messy background, walking backwards",
"positive_prompt": "The woman leans toward the vintage studio microphone and raps with fierce, emotional intensity, every line landing on the beat. Her eyebrows lift and knit with the rhythm, her head rocks forward on the accents and her shoulders rise as she builds toward the final shout, eyes fixed on the lens. The microphone stays below her chin and never covers her mouth. Rain streams down the window behind her while warm amber light from the room glows on her face. Locked-off camera, single continuous shot, natural lip movement synced to the vocal, realistic skin and expression.",
"precision": "bf16",
"quantization": "disabled",
"use_disk_cache": False
},
"_meta": {
"title": "WanVideo TextEncode Cached"
}
},
"330:333": {
"class_type": "WanVideoSampler",
"inputs": {
"add_noise_to_samples": True,
"batched_cfg": False,
"cfg": 1.0000000000000002,
"denoise_strength": 1,
"end_step": -1,
"force_offload": True,
"image_embeds": [
"330:339",
0
],
"model": [
"330:346",
0
],
"multitalk_embeds": [
"330:337",
0
],
"riflex_freq_index": 0,
"rope_function": "comfy",
"scheduler": "dpm++_sde",
"seed": 940918897846710,
"shift": 11.000000000000002,
"start_step": 0,
"steps": 7,
"text_embeds": [
"330:332",
0
]
},
"_meta": {
"title": "WanVideo Sampler"
}
},
"330:334": {
"class_type": "CreateVideo",
"inputs": {
"audio": [
"125",
0
],
"bit_depth": "auto",
"codec": "none",
"color_space": "sRGB",
"fps": 25,
"images": [
"330:331",
0
]
},
"_meta": {
"title": "Create Video"
}
},
"330:335": {
"class_type": "AudioSeparation",
"inputs": {
"audio": [
"125",
0
],
"chunk_fade_shape": "linear",
"chunk_length": 10,
"chunk_overlap": 0.1
},
"_meta": {
"title": "AudioSeparation"
}
},
"330:336": {
"class_type": "DownloadAndLoadWav2VecModel",
"inputs": {
"base_precision": "fp16",
"load_device": "main_device",
"model": "TencentGameMate/chinese-wav2vec2-base"
},
"_meta": {
"title": "(Down)load Wav2Vec Model"
}
},
"330:337": {
"class_type": "MultiTalkWav2VecEmbeds",
"inputs": {
"add_noise_floor": False,
"audio_1": [
"330:335",
3
],
"audio_cfg_scale": 1,
"audio_scale": 1,
"fps": 25,
"multi_audio_type": "para",
"normalize_loudness": True,
"num_frames": 440,
"smooth_transients": False,
"wav2vec_model": [
"330:336",
0
]
},
"_meta": {
"title": "Multi/InfiniteTalk Wav2vec2 Embeds"
}
},
"330:339": {
"class_type": "WanVideoImageToVideoMultiTalk",
"inputs": {
"clip_embeds": [
"330:342",
0
],
"colormatch": "disabled",
"force_offload": False,
"frame_window_size": 81,
"height": [
"330:341",
2
],
"mode": "infinitetalk",
"motion_frame": 9,
"output_path": "",
"start_image": [
"330:341",
0
],
"tiled_vae": False,
"vae": [
"330:347",
0
],
"width": [
"330:341",
1
]
},
"_meta": {
"title": "WanVideo Long I2V Multi/InfiniteTalk"
}
},
"330:340": {
"class_type": "ImageResizeKJv2",
"inputs": {
"crop_position": "center",
"device": "cpu",
"divisible_by": 16,
"height": 480,
"image": [
"284",
0
],
"keep_proportion": "crop",
"pad_color": "0, 0, 0",
"upscale_method": "lanczos",
"width": 832
},
"_meta": {
"title": "Resize Image v2"
}
},
"330:341": {
"class_type": "GetImageSizeAndCount",
"inputs": {
"image": [
"330:340",
0
]
},
"_meta": {
"title": "Get Image Size & Count"
}
},
"330:342": {
"class_type": "WanVideoClipVisionEncode",
"inputs": {
"clip_vision": [
"330:345",
0
],
"combine_embeds": "average",
"crop": "center",
"force_offload": True,
"image_1": [
"330:341",
0
],
"ratio": 0.5,
"strength_1": 1,
"strength_2": 1,
"tiles": 0
},
"_meta": {
"title": "WanVideo ClipVision Encode"
}
},
"330:343": {
"class_type": "WanVideoLoraSelect",
"inputs": {
"lora": "lightx2v_I2V_14B_480p_cfg_step_distill_rank64_bf16.safetensors",
"low_mem_load": False,
"merge_loras": False,
"strength": 1
},
"_meta": {
"title": "WanVideo Lora Select"
}
},
"330:344": {
"class_type": "MultiTalkModelLoader",
"inputs": {
"model": "Wan2_1-InfiniTetalk-Single_fp16.safetensors"
},
"_meta": {
"title": "Multi/InfiniteTalk Model Loader"
}
},
"330:345": {
"class_type": "CLIPVisionLoader",
"inputs": {
"clip_name": "clip_vision_h.safetensors"
},
"_meta": {
"title": "Load CLIP Vision"
}
},
"330:346": {
"class_type": "WanVideoModelLoader",
"inputs": {
"attention_mode": "sdpa",
"base_precision": "fp16_fast",
"load_device": "offload_device",
"lora": [
"330:343",
0
],
"model": "wan2.1_i2v_480p_14B_fp16.safetensors",
"multitalk_model": [
"330:344",
0
],
"quantization": "disabled",
"rms_norm_function": "default"
},
"_meta": {
"title": "WanVideo Model Loader"
}
},
"330:347": {
"class_type": "WanVideoVAELoader",
"inputs": {
"model_name": "Wan2_1_VAE_bf16.safetensors",
"precision": "bf16",
"use_cpu_cache": False,
"verbose": False
},
"_meta": {
"title": "WanVideo VAE Loader"
}
}
})
workflow.set_input("125", "audio", client.assets.from_url("https://comfy.org/catalog-media/a9599b05-2b5e-4151-b610-5c710b2ab528/d82c4807-73a1-4ddf-a49a-d84635f21bff"))
workflow.set_input("284", "image", client.assets.from_url("https://comfy.org/catalog-media/ed913f9f-0f6a-4b49-a376-3b5430445548/fecb9784-5e2b-4840-b782-01165a1ed6ed"))
# 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("325"):
output.to_file(output.name)