updated images with ai images
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
"""Single test clip — corrected WanImageToVideo workflow."""
|
||||
import json, time, urllib.request, os, random
|
||||
|
||||
COMFY = "http://localhost:8188"
|
||||
IMAGE_PATH = "assets/images/hero/hero-carpet-cleaning.webp"
|
||||
OUT_DIR = "assets/videos/clips"
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def upload_image(image_path):
|
||||
fname = os.path.basename(image_path)
|
||||
with open(image_path, "rb") as f:
|
||||
img_data = f.read()
|
||||
boundary = "----FormBoundary123456"
|
||||
body = (
|
||||
f"--{boundary}\r\n"
|
||||
f'Content-Disposition: form-data; name="image"; filename="{fname}"\r\n'
|
||||
f"Content-Type: image/webp\r\n\r\n"
|
||||
).encode() + img_data + f"\r\n--{boundary}--\r\n".encode()
|
||||
req = urllib.request.Request(
|
||||
f"{COMFY}/upload/image", data=body,
|
||||
headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
|
||||
)
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
result = json.loads(resp.read())
|
||||
print(f" uploaded: {result['name']}")
|
||||
return result["name"]
|
||||
|
||||
|
||||
def build_workflow(image_name, prompt, frames=25):
|
||||
# WanImageToVideo is a conditioning node, NOT a sampler.
|
||||
# outputs: [0]=positive CONDITIONING, [1]=negative CONDITIONING, [2]=latent LATENT
|
||||
# start_image is optional IMAGE — anchors first frame.
|
||||
return {
|
||||
"1": {"class_type": "UnetLoaderGGUF", "inputs": {"unet_name": "Wan2.2-TI2V-5B-Q4_K_M.gguf"}},
|
||||
"2": {"class_type": "CLIPLoader", "inputs": {"clip_name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors", "type": "wan"}},
|
||||
"3": {"class_type": "VAELoader", "inputs": {"vae_name": "wan_2.1_vae.safetensors"}},
|
||||
"4": {"class_type": "LoadImage", "inputs": {"image": image_name}},
|
||||
"5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["2", 0], "text": prompt}},
|
||||
"6": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["2", 0], "text": "blur, low quality, distortion, text, watermark, people, jitter"}},
|
||||
"7": {
|
||||
"class_type": "WanImageToVideo",
|
||||
"inputs": {
|
||||
"positive": ["5", 0],
|
||||
"negative": ["6", 0],
|
||||
"vae": ["3", 0],
|
||||
"start_image": ["4", 0],
|
||||
"width": 832, "height": 480, "length": frames, "batch_size": 1,
|
||||
},
|
||||
},
|
||||
"8": {
|
||||
"class_type": "KSampler",
|
||||
"inputs": {
|
||||
"model": ["1", 0],
|
||||
"positive": ["7", 0],
|
||||
"negative": ["7", 1],
|
||||
"latent_image": ["7", 2],
|
||||
"seed": 42, "steps": 20, "cfg": 6.0,
|
||||
"sampler_name": "uni_pc", "scheduler": "simple", "denoise": 1.0,
|
||||
},
|
||||
},
|
||||
# VAEDecodeTiled handles video (5D) latents — VAEDecode only handles images (4D)
|
||||
"9": {"class_type": "VAEDecodeTiled", "inputs": {"samples": ["8", 0], "vae": ["3", 0], "tile_size": 512, "overlap": 64, "temporal_size": 64, "temporal_overlap": 8}},
|
||||
"10": {
|
||||
"class_type": "SaveAnimatedWEBP",
|
||||
"inputs": {"images": ["9", 0], "filename_prefix": "wan_test", "fps": 12, "lossless": False, "quality": 85, "method": "default"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def queue_prompt(workflow):
|
||||
data = json.dumps({"prompt": workflow}).encode()
|
||||
req = urllib.request.Request(f"{COMFY}/prompt", data=data, headers={"Content-Type": "application/json"})
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
return json.loads(resp.read())["prompt_id"]
|
||||
|
||||
|
||||
def wait_for_result(prompt_id, timeout=1800):
|
||||
start = time.time()
|
||||
while time.time() - start < timeout:
|
||||
with urllib.request.urlopen(f"{COMFY}/history/{prompt_id}") as resp:
|
||||
hist = json.loads(resp.read())
|
||||
if prompt_id in hist:
|
||||
entry = hist[prompt_id]
|
||||
if entry.get("status", {}).get("status_str") == "error":
|
||||
print(f" ERROR: {entry['status'].get('messages', '')}")
|
||||
return None
|
||||
for node_out in entry.get("outputs", {}).values():
|
||||
if "gifs" in node_out:
|
||||
return node_out["gifs"]
|
||||
if "images" in node_out:
|
||||
return node_out["images"]
|
||||
elapsed = int(time.time() - start)
|
||||
print(f" waiting... {elapsed}s", flush=True)
|
||||
time.sleep(15)
|
||||
return None
|
||||
|
||||
|
||||
def download_output(vid_info, out_path):
|
||||
fname = vid_info["filename"]
|
||||
subfolder = vid_info.get("subfolder", "")
|
||||
img_type = vid_info.get("type", "output")
|
||||
url = f"{COMFY}/view?filename={fname}&subfolder={subfolder}&type={img_type}"
|
||||
with urllib.request.urlopen(url) as resp:
|
||||
data = resp.read()
|
||||
with open(out_path, "wb") as f:
|
||||
f.write(data)
|
||||
print(f" saved: {out_path} ({len(data)//1024}KB)")
|
||||
|
||||
|
||||
print("[TEST v2] WanImageToVideo → KSampler → VAEDecode → SaveAnimatedWEBP")
|
||||
image_name = upload_image(IMAGE_PATH)
|
||||
workflow = build_workflow(
|
||||
image_name,
|
||||
"slow dolly forward across clean plush cream carpet, gentle camera push toward the far wall, warm afternoon light, cinematic smooth motion",
|
||||
frames=9,
|
||||
)
|
||||
prompt_id = queue_prompt(workflow)
|
||||
print(f" queued: {prompt_id}")
|
||||
results = wait_for_result(prompt_id)
|
||||
if results:
|
||||
download_output(results[0], f"{OUT_DIR}/test-clip-01.webp")
|
||||
print("SUCCESS")
|
||||
else:
|
||||
print("FAILED")
|
||||
Reference in New Issue
Block a user