# 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({
"2": {
"class_type": "SaveVideo",
"inputs": {
"codec": "auto",
"filename_prefix": "video/video/MiniMax_H3_t2v_768P",
"format": "auto",
"format.codec": "auto",
"video": [
"31",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"7": {
"class_type": "MinimaxHailuo03ContextIRNode",
"inputs": {
"model": "MiniMax H3",
"model.duration": 5,
"model.prompt": [
"14",
0
],
"model.ratio": "adaptive"
},
"_meta": {
"title": "MiniMax H3 Context IR (Prompt Enhancer)"
}
},
"8": {
"class_type": "SaveText",
"inputs": {
"filename_prefix": "H3_prompt",
"format": "txt",
"text": [
"12",
0
]
},
"_meta": {
"title": "Save Text"
}
},
"10": {
"class_type": "MinimaxHailuo03RegenerateNode",
"inputs": {
"model": "MiniMax H3",
"model.prompt": [
"8",
0
],
"model.resolution": "2K",
"video": [
"2",
0
],
"watermark": False
},
"_meta": {
"title": "MiniMax H3 Regenerate to 2K"
}
},
"11": {
"class_type": "SaveVideo",
"inputs": {
"codec": "auto",
"filename_prefix": "video/Minimax_h3_max",
"format": "auto",
"format.codec": "auto",
"video": [
"13",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"12": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"14",
0
],
"on_true": [
"7",
0
],
"switch": [
"18",
0
]
},
"_meta": {
"title": "If/Else Switch"
}
},
"13": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"31",
0
],
"on_true": [
"10",
0
],
"switch": [
"19",
0
]
},
"_meta": {
"title": "If/Else Switch"
}
},
"14": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "[Global Lock]: High-energy music video, theme \"INSTANT\": the world is slow, we are fast. 5 seconds, 16:9, third person, protagonist a young woman in a black sporty windbreaker. Aesthetic: night-city speed, neon and headlight trails, teal-orange contrast grade, heavy grain, subtle motion blur. Five shots, four hard cuts on a 140 BPM grid, constant motion inside every shot, crisp editing. Lyrics as spatial graphic layer: oversized type, hugging architecture, motion-trailing, max one line per shot.\n\nShot 1 (0.0s-0.8s): Ground-level tracking shot, the protagonist sprinting down a night street, sneakers slapping puddles into spray, neon streaking into light trails behind her. Oversized cyan type \"SLOW WORLD\" sweeps across from the left.\nCut: kick.\n\nShot 2 (0.8s-1.8s): A subway train roars into the station, window light bands streaking horizontally, the protagonist standing still against the crowd flow, only her hair and hem lifted by the draft, a moving-vs-still contrast. Glitchy white type \"YOU CRAWL\" flashes in as the train passes.\nCut: snare.\n\nShot 3 (1.8s-2.6s): Inside the car, one hand on the hanging strap, the train at full speed, tunnel lights streaking across her face as a high-speed light band, her eyes razor sharp into the lens. Ice-blue type \"I MOVE\" hugs the window glass with a reflective motion trail.\nCut: 808 hit.\n\nShot 4 (2.6s-3.8s): Aerial dive, she sprints across an intersection, traffic light trails weaving a net around her, the camera plunging from high altitude down to her run, windbreaker snapping. No text, pure visual burst.\nCut: closing accent.\n\nShot 5 (3.8s-5.0s): She bolts onto a footbridge, brakes, and turns to face the lens, the whole street's car lights smearing into a river of time behind her; oversized cyan type \"INSTANT\" smashes in, and the last beat freezes the frame. Audio: 140 BPM fast electronic beat, kick, snare, 808, and closing accent on the four cuts, city noise, wind, and train roar as the bed, the last beat dropping to silence leaving a single heartbeat.\nNegative hard locks: static shots, statically centered subtitles, dissolves, soft transitions, overused slow motion, subtitle bars, logos."
},
"_meta": {
"title": "Text (Prompt)"
}
},
"18": {
"class_type": "PrimitiveBoolean",
"inputs": {
"value": False
},
"_meta": {
"title": "Boolean (Prompt Enhance)"
}
},
"19": {
"class_type": "PrimitiveBoolean",
"inputs": {
"value": False
},
"_meta": {
"title": "Boolean (Upscale to 2K)"
}
},
"31": {
"class_type": "MinimaxHailuo03TextToVideoNode",
"inputs": {
"model": "MiniMax H3 Max",
"model.duration": 5,
"model.prompt": [
"12",
0
],
"model.prompt_expansion_mode": "balanced",
"model.ratio": "16:9",
"model.resolution": "768P",
"seed": 2967573614,
"watermark": False
},
"_meta": {
"title": "MiniMax H3 Text to Video"
}
}
})
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)