Add widget mappings for all WanVideo workflow nodes
All checks were successful
Build and Push Docker Image / build (push) Successful in 4m4s
All checks were successful
Build and Push Docker Image / build (push) Successful in 4m4s
The convert_frontend_to_api() function was missing mappings for most node types, causing "Required input is missing" errors when the API received workflows in frontend format. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
79
handler.py
79
handler.py
@@ -122,46 +122,63 @@ def convert_frontend_to_api(frontend_workflow: dict) -> dict:
|
||||
link_id, src_node, src_slot, dst_node, dst_slot, link_type = link[:6]
|
||||
link_map[link_id] = (str(src_node), src_slot)
|
||||
|
||||
# Widget mappings for each node type: list of input names in order
|
||||
WIDGET_MAPPINGS = {
|
||||
"LoadImage": ["image", "upload"],
|
||||
"CLIPTextEncode": ["text"],
|
||||
"easy int": ["value"],
|
||||
"INTConstant": ["value"],
|
||||
"SaveVideo": ["filename_prefix", "format", "codec"],
|
||||
"CreateVideo": ["fps"],
|
||||
"RIFE VFI": ["ckpt_name", "clear_cache_after_n_frames", "multiplier", "fast_mode", "ensemble", "scale_factor"],
|
||||
"CLIPLoader": ["clip_name", "type", "device"],
|
||||
"GetImageSize": [],
|
||||
"WanVideoTorchCompileSettings": [
|
||||
"backend", "fullgraph", "mode", "dynamic", "dynamo_cache_size_limit",
|
||||
"compile_transformer_blocks_only", "compile_cache_max_entries",
|
||||
"compile_single_blocks", "compile_double_blocks"
|
||||
],
|
||||
"WanVideoBlockSwap": [
|
||||
"blocks_to_swap", "offload_txt_emb", "offload_img_emb", "offload_txt_clip_emb",
|
||||
"offload_modulation", "cpu_offload_streams", "use_async_transfer"
|
||||
],
|
||||
"WanVideoModelLoader": [
|
||||
"model", "base_precision", "quantization", "load_device", "attention_mode", "lora_scale_mode"
|
||||
],
|
||||
"WanVideoLoraSelect": ["lora", "strength", "use_lora_sparse", "sparse_lora_blocks"],
|
||||
"WanVideoVAELoader": ["model_name", "precision"],
|
||||
"WanVideoTextEmbedBridge": [],
|
||||
"WanVideoImageToVideoEncode": [
|
||||
"width", "height", "num_frames", "noise_aug_strength",
|
||||
"start_latent_strength", "end_latent_strength", "image_noise_aug",
|
||||
"mask_noise_aug", "force_offload"
|
||||
],
|
||||
"WanVideoSampler": [
|
||||
"shift", "cfg", "steps", "seed", "seed_mode", "force_offload", "scheduler",
|
||||
"riflex_freq_index", "riflex_freq_dim", "riflex_freq_scale",
|
||||
"use_comfy_pbar", "start_step", "end_step", "denoise"
|
||||
],
|
||||
"WanVideoDecode": [
|
||||
"enable_tiling", "tile_x", "tile_y", "tile_stride_x", "tile_stride_y", "tiling_decoder"
|
||||
],
|
||||
"MathExpression|pysssss": ["expression"],
|
||||
}
|
||||
|
||||
for node in nodes:
|
||||
node_id = str(node["id"])
|
||||
class_type = node.get("type", "")
|
||||
|
||||
inputs = {}
|
||||
|
||||
# Process widget values
|
||||
# Process widget values using mappings
|
||||
widgets_values = node.get("widgets_values", [])
|
||||
widget_names = WIDGET_MAPPINGS.get(class_type, [])
|
||||
|
||||
# Map widget values based on class type
|
||||
# This is a simplified mapping - specific nodes may need custom handling
|
||||
if class_type == "LoadImage" and len(widgets_values) >= 1:
|
||||
inputs["image"] = widgets_values[0]
|
||||
if len(widgets_values) >= 2:
|
||||
inputs["upload"] = widgets_values[1]
|
||||
for i, value in enumerate(widgets_values):
|
||||
if i < len(widget_names) and widget_names[i]:
|
||||
inputs[widget_names[i]] = value
|
||||
|
||||
elif class_type == "CLIPTextEncode" and len(widgets_values) >= 1:
|
||||
inputs["text"] = widgets_values[0]
|
||||
|
||||
elif class_type in ["easy int", "INTConstant"] and len(widgets_values) >= 1:
|
||||
inputs["value"] = widgets_values[0]
|
||||
|
||||
elif class_type == "SaveVideo" and len(widgets_values) >= 1:
|
||||
inputs["filename_prefix"] = widgets_values[0]
|
||||
if len(widgets_values) >= 2:
|
||||
inputs["format"] = widgets_values[1]
|
||||
if len(widgets_values) >= 3:
|
||||
inputs["codec"] = widgets_values[2]
|
||||
|
||||
elif class_type == "CreateVideo" and len(widgets_values) >= 1:
|
||||
inputs["frame_rate"] = widgets_values[0]
|
||||
|
||||
elif class_type == "RIFE VFI" and len(widgets_values) >= 1:
|
||||
inputs["ckpt_name"] = widgets_values[0]
|
||||
if len(widgets_values) >= 2:
|
||||
inputs["clear_cache_after_n_frames"] = widgets_values[1]
|
||||
if len(widgets_values) >= 3:
|
||||
inputs["multiplier"] = widgets_values[2]
|
||||
|
||||
# Process node inputs (connections)
|
||||
# Process node inputs (connections) - these override widget values
|
||||
for inp in node.get("inputs", []):
|
||||
inp_name = inp["name"]
|
||||
link_id = inp.get("link")
|
||||
|
||||
Reference in New Issue
Block a user