# 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({
"31": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_first_frame_FILENAME"
},
"_meta": {
"title": "Load First Frame"
}
},
"39": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_last_frame_FILENAME"
},
"_meta": {
"title": "Load Last Frame"
}
},
"68": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "video/ltx2.3_flf2v",
"format": "auto",
"format.codec": "auto",
"video": [
"122",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"98": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 720
},
"_meta": {
"title": "HEIGHT"
}
},
"99": {
"class_type": "LTXVPreprocess",
"inputs": {
"image": [
"125",
0
],
"img_compression": 25
},
"_meta": {
"title": "LTXV Preprocess"
}
},
"100": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 315253765879496
},
"_meta": {
"title": "RandomNoise"
}
},
"101": {
"class_type": "LTXVEmptyLatentAudio",
"inputs": {
"audio_vae": [
"126",
0
],
"batch_size": 1,
"frame_rate": [
"114",
0
],
"frames_number": [
"102",
0
]
},
"_meta": {
"title": "Empty LTXV Latent Audio"
}
},
"102": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 121
},
"_meta": {
"title": "Length"
}
},
"103": {
"class_type": "LTXAVTextEncoderLoader",
"inputs": {
"ckpt_name": "ltx-2.3-22b-distilled-fp8.safetensors",
"device": "default",
"text_encoder": "gemma_3_12B_it_fp4_mixed.safetensors"
},
"_meta": {
"title": "Load LTXV Audio Text Encoder"
}
},
"104": {
"class_type": "LTXVPreprocess",
"inputs": {
"image": [
"124",
0
],
"img_compression": 25
},
"_meta": {
"title": "LTXV Preprocess"
}
},
"105": {
"class_type": "VAEDecodeTiled",
"inputs": {
"overlap": 64,
"samples": [
"106",
2
],
"temporal_overlap": 64,
"temporal_size": 4096,
"tile_size": 768,
"vae": [
"127",
2
]
},
"_meta": {
"title": "VAE Decode (Tiled)"
}
},
"106": {
"class_type": "LTXVCropGuides",
"inputs": {
"latent": [
"121",
0
],
"negative": [
"111",
1
],
"positive": [
"111",
0
]
},
"_meta": {
"title": "LTXVCropGuides"
}
},
"107": {
"class_type": "LTXVAudioVAEDecode",
"inputs": {
"audio_vae": [
"126",
0
],
"samples": [
"121",
1
]
},
"_meta": {
"title": "LTXV Audio VAE Decode"
}
},
"108": {
"class_type": "EmptyLTXVLatentVideo",
"inputs": {
"batch_size": 1,
"height": [
"110",
1
],
"length": [
"102",
0
],
"width": [
"110",
0
]
},
"_meta": {
"title": "Empty LTXV Latent Video"
}
},
"109": {
"class_type": "LTXVConditioning",
"inputs": {
"frame_rate": [
"123",
0
],
"negative": [
"112",
0
],
"positive": [
"128",
0
]
},
"_meta": {
"title": "LTXVConditioning"
}
},
"110": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"124",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"111": {
"class_type": "LTXVAddGuide",
"inputs": {
"frame_idx": -1,
"image": [
"99",
0
],
"latent": [
"115",
2
],
"negative": [
"115",
1
],
"positive": [
"115",
0
],
"strength": 0.7,
"vae": [
"127",
2
]
},
"_meta": {
"title": "LTXVAddGuide"
}
},
"112": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"103",
0
],
"text": "blurry, out of focus, overexposed, underexposed, low contrast, washed out colors, excessive noise, grainy texture, poor lighting, flickering, motion blur, distorted proportions, unnatural skin tones, deformed facial features, asymmetrical face, missing facial features, extra limbs, disfigured hands, wrong hand count, artifacts around text, unreadable text on shirt or hat, incorrect lettering on cap (“PNTR”), incorrect t-shirt slogan (“JUST DO IT”), missing microphone, misplaced microphone, inconsistent perspective, camera shake, incorrect depth of field, background too sharp, background clutter, distracting reflections, harsh shadows, inconsistent lighting direction, color banding, cartoonish rendering, 3D CGI look, unrealistic materials, uncanny valley effect, incorrect ethnicity, wrong gender, exaggerated expressions, smiling, laughing, exaggerated sadness, wrong gaze direction, eyes looking at camera, mismatched lip sync, silent or muted audio, distorted voice, robotic voice, echo, background noise, off-sync audio, missing sniff sounds, incorrect dialogue, added dialogue, repetitive speech, jittery movement, awkward pauses, incorrect timing, unnatural transitions, inconsistent framing, tilted camera, missing door or shelves, missing shallow depth of field, flat lighting, inconsistent tone, cinematic oversaturation, stylized filters, or AI artifacts."
},
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"113": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 1280
},
"_meta": {
"title": "WIDTH"
}
},
"114": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 25
},
"_meta": {
"title": "Frame Rate(int)"
}
},
"115": {
"class_type": "LTXVAddGuide",
"inputs": {
"frame_idx": 0,
"image": [
"104",
0
],
"latent": [
"108",
0
],
"negative": [
"109",
1
],
"positive": [
"109",
0
],
"strength": 0.7,
"vae": [
"127",
2
]
},
"_meta": {
"title": "LTXVAddGuide"
}
},
"116": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 1,
"model": [
"127",
0
],
"negative": [
"111",
1
],
"positive": [
"111",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"117": {
"class_type": "SamplerEulerAncestral",
"inputs": {
"eta": 0,
"s_noise": 1
},
"_meta": {
"title": "SamplerEulerAncestral"
}
},
"118": {
"class_type": "ManualSigmas",
"inputs": {
"sigmas": "1., 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0"
},
"_meta": {
"title": "ManualSigmas"
}
},
"119": {
"class_type": "LTXVConcatAVLatent",
"inputs": {
"audio_latent": [
"101",
0
],
"video_latent": [
"111",
2
]
},
"_meta": {
"title": "Concat AV Latent"
}
},
"120": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"116",
0
],
"latent_image": [
"119",
0
],
"noise": [
"100",
0
],
"sampler": [
"117",
0
],
"sigmas": [
"118",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"121": {
"class_type": "LTXVSeparateAVLatent",
"inputs": {
"av_latent": [
"120",
1
]
},
"_meta": {
"title": "Separate AV Latent"
}
},
"122": {
"class_type": "CreateVideo",
"inputs": {
"audio": [
"107",
0
],
"bit_depth": "auto",
"codec": "none",
"color_space": "sRGB",
"fps": [
"123",
0
],
"images": [
"105",
0
]
},
"_meta": {
"title": "Create Video"
}
},
"123": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "a",
"values.a": [
"114",
0
]
},
"_meta": {
"title": "Math Expression"
}
},
"124": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"input": [
"31",
0
],
"resize_type": "scale dimensions",
"resize_type.crop": "center",
"resize_type.height": [
"98",
0
],
"resize_type.width": [
"113",
0
],
"scale_method": "nearest-exact"
},
"_meta": {
"title": "Resize Image/Mask"
}
},
"125": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"input": [
"39",
0
],
"resize_type": "scale dimensions",
"resize_type.crop": "center",
"resize_type.height": [
"98",
0
],
"resize_type.width": [
"113",
0
],
"scale_method": "nearest-exact"
},
"_meta": {
"title": "Resize Image/Mask"
}
},
"126": {
"class_type": "LTXVAudioVAELoader",
"inputs": {
"ckpt_name": "ltx-2.3-22b-distilled-fp8.safetensors"
},
"_meta": {
"title": "Load LTXV Audio VAE"
}
},
"127": {
"class_type": "CheckpointLoaderSimple",
"inputs": {
"ckpt_name": "ltx-2.3-22b-distilled-fp8.safetensors"
},
"_meta": {
"title": "Load Checkpoint"
}
},
"128": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"103",
0
],
"text": "The camera starts high above the empty desert road, looking down at the rider sitting on his tan scrambler motorcycle, then cranes smoothly down in one continuous move until it is low near the asphalt, looking up at him against the warm evening sky, keeping him centred the whole time. He turns his head to follow the lens, rests a hand on the helmet on the tank and gives a slow, easy smile. Dust drifts across the road in the low sunset light and long shadows stretch over the cracked pavement. Sound: a dry desert wind, gravel crunching under his boot, the motorcycle engine ticking as it cools, and a lone hawk calling in the distance."
},
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
}
})
workflow.set_input("31", "image", client.assets.from_url("https://comfy.org/catalog-media/39789dba-718f-474c-8417-7b506c845164/8581bf55-6f97-4ea7-a968-56d85727af90"))
workflow.set_input("39", "image", client.assets.from_url("https://comfy.org/catalog-media/49043d45-d01f-42a1-b425-5217ca403e50/af788406-c94b-402e-8dd5-a41e3de97841"))
# 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("68"):
output.to_file(output.name)