Files
Comfyui-JSON-Manager/json_loader.py

307 lines
10 KiB
Python

import json
import os
# --- Shared Helper ---
def read_json_data(json_path):
if not os.path.exists(json_path):
print(f"[JSON Loader] Warning: File not found at {json_path}")
return {}
try:
with open(json_path, 'r') as f:
return json.load(f)
except Exception as e:
print(f"[JSON Loader] Error: {e}")
return {}
# ==========================================
# 1. STANDARD NODES (Single File)
# ==========================================
class JSONLoaderLoRA:
@classmethod
def INPUT_TYPES(s):
return {"required": {"json_path": ("STRING", {"default": "", "multiline": False})}}
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
RETURN_NAMES = (
"lora_1_high", "lora_1_low",
"lora_2_high", "lora_2_low",
"lora_3_high", "lora_3_low"
)
FUNCTION = "load_loras"
CATEGORY = "utils/json"
def load_loras(self, json_path):
data = read_json_data(json_path)
return (
str(data.get("lora 1 high", "")),
str(data.get("lora 1 low", "")),
str(data.get("lora 2 high", "")),
str(data.get("lora 2 low", "")),
str(data.get("lora 3 high", "")),
str(data.get("lora 3 low", ""))
)
class JSONLoaderStandard:
@classmethod
def INPUT_TYPES(s):
return {"required": {"json_path": ("STRING", {"default": "", "multiline": False})}}
RETURN_TYPES = (
"STRING", "STRING", "STRING", "STRING",
"STRING", "FLOAT", "INT",
"STRING", "STRING", "STRING"
)
RETURN_NAMES = (
"general_prompt", "general_negative", "current_prompt", "negative",
"camera", "flf", "seed",
"video_file_path", "reference_image_path", "flf_image_path"
)
FUNCTION = "load_standard"
CATEGORY = "utils/json"
def load_standard(self, json_path):
data = read_json_data(json_path)
def to_float(val):
try: return float(val)
except: return 0.0
def to_int(val):
try: return int(float(val))
except: return 0
return (
str(data.get("general_prompt", "")),
str(data.get("general_negative", "")),
str(data.get("current_prompt", "")),
str(data.get("negative", "")),
str(data.get("camera", "")),
to_float(data.get("flf", 0.0)),
to_int(data.get("seed", 0)),
str(data.get("video file path", "")),
str(data.get("reference image path", "")),
str(data.get("flf image path", ""))
)
class JSONLoaderVACE:
@classmethod
def INPUT_TYPES(s):
return {"required": {"json_path": ("STRING", {"default": "", "multiline": False})}}
RETURN_TYPES = (
"STRING", "STRING", "STRING", "STRING",
"STRING", "FLOAT", "INT",
"INT", "INT", "INT", "STRING", "INT", "INT",
"STRING", "STRING"
)
RETURN_NAMES = (
"general_prompt", "general_negative", "current_prompt", "negative",
"camera", "flf", "seed",
"frame_to_skip", "input_a_frames", "input_b_frames", "reference_path", "reference_switch", "vace_schedule",
"video_file_path", "reference_image_path"
)
FUNCTION = "load_vace"
CATEGORY = "utils/json"
def load_vace(self, json_path):
data = read_json_data(json_path)
def to_float(val):
try: return float(val)
except: return 0.0
def to_int(val):
try: return int(float(val))
except: return 0
return (
str(data.get("general_prompt", "")),
str(data.get("general_negative", "")),
str(data.get("current_prompt", "")),
str(data.get("negative", "")),
str(data.get("camera", "")),
to_float(data.get("flf", 0.0)),
to_int(data.get("seed", 0)),
to_int(data.get("frame_to_skip", 81)),
to_int(data.get("input_a_frames", 0)),
to_int(data.get("input_b_frames", 0)),
str(data.get("reference path", "")),
to_int(data.get("reference switch", 1)),
to_int(data.get("vace schedule", 1)),
str(data.get("video file path", "")),
str(data.get("reference image path", ""))
)
# ==========================================
# 3. BATCH NODES (Sequence Support)
# ==========================================
# --- NEW: BATCH LORA ---
class JSONLoaderBatchLoRA:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"json_path": ("STRING", {"default": "", "multiline": False}),
"sequence_number": ("INT", {"default": 1, "min": 1, "max": 9999})
}
}
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
RETURN_NAMES = (
"lora_1_high", "lora_1_low",
"lora_2_high", "lora_2_low",
"lora_3_high", "lora_3_low"
)
FUNCTION = "load_batch_loras"
CATEGORY = "utils/json"
def load_batch_loras(self, json_path, sequence_number):
data = read_json_data(json_path)
# Batch Logic
target_data = data
if "batch_data" in data and isinstance(data["batch_data"], list) and len(data["batch_data"]) > 0:
idx = sequence_number - 1
idx = idx % len(data["batch_data"])
target_data = data["batch_data"][idx]
return (
str(target_data.get("lora 1 high", "")),
str(target_data.get("lora 1 low", "")),
str(target_data.get("lora 2 high", "")),
str(target_data.get("lora 2 low", "")),
str(target_data.get("lora 3 high", "")),
str(target_data.get("lora 3 low", ""))
)
class JSONLoaderBatchI2V:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"json_path": ("STRING", {"default": "", "multiline": False}),
"sequence_number": ("INT", {"default": 1, "min": 1, "max": 9999})
}
}
RETURN_TYPES = (
"STRING", "STRING", "STRING", "STRING",
"STRING", "FLOAT", "INT",
"STRING", "STRING", "STRING"
)
RETURN_NAMES = (
"general_prompt", "general_negative", "current_prompt", "negative",
"camera", "flf", "seed",
"video_file_path", "reference_image_path", "flf_image_path"
)
FUNCTION = "load_batch_i2v"
CATEGORY = "utils/json"
def load_batch_i2v(self, json_path, sequence_number):
data = read_json_data(json_path)
target_data = data
if "batch_data" in data and isinstance(data["batch_data"], list) and len(data["batch_data"]) > 0:
idx = sequence_number - 1
idx = idx % len(data["batch_data"])
target_data = data["batch_data"][idx]
def to_float(val):
try: return float(val)
except: return 0.0
def to_int(val):
try: return int(float(val))
except: return 0
return (
str(target_data.get("general_prompt", "")),
str(target_data.get("general_negative", "")),
str(target_data.get("current_prompt", "")),
str(target_data.get("negative", "")),
str(target_data.get("camera", "")),
to_float(target_data.get("flf", 0.0)),
to_int(target_data.get("seed", 0)),
str(target_data.get("video file path", "")),
str(target_data.get("reference image path", "")),
str(target_data.get("flf image path", ""))
)
class JSONLoaderBatchVACE:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"json_path": ("STRING", {"default": "", "multiline": False}),
"sequence_number": ("INT", {"default": 1, "min": 1, "max": 9999})
}
}
RETURN_TYPES = (
"STRING", "STRING", "STRING", "STRING",
"STRING", "FLOAT", "INT",
"INT", "INT", "INT", "STRING", "INT", "INT",
"STRING", "STRING"
)
RETURN_NAMES = (
"general_prompt", "general_negative", "current_prompt", "negative",
"camera", "flf", "seed",
"frame_to_skip", "input_a_frames", "input_b_frames", "reference_path", "reference_switch", "vace_schedule",
"video_file_path", "reference_image_path"
)
FUNCTION = "load_batch_vace"
CATEGORY = "utils/json"
def load_batch_vace(self, json_path, sequence_number):
data = read_json_data(json_path)
target_data = data
if "batch_data" in data and isinstance(data["batch_data"], list) and len(data["batch_data"]) > 0:
idx = sequence_number - 1
idx = idx % len(data["batch_data"])
target_data = data["batch_data"][idx]
def to_float(val):
try: return float(val)
except: return 0.0
def to_int(val):
try: return int(float(val))
except: return 0
return (
str(target_data.get("general_prompt", "")),
str(target_data.get("general_negative", "")),
str(target_data.get("current_prompt", "")),
str(target_data.get("negative", "")),
str(target_data.get("camera", "")),
to_float(target_data.get("flf", 0.0)),
to_int(target_data.get("seed", 0)),
to_int(target_data.get("frame_to_skip", 81)),
to_int(target_data.get("input_a_frames", 0)),
to_int(target_data.get("input_b_frames", 0)),
str(target_data.get("reference path", "")),
to_int(target_data.get("reference switch", 1)),
to_int(target_data.get("vace schedule", 1)),
str(target_data.get("video file path", "")),
str(target_data.get("reference image path", ""))
)
# --- Mappings ---
NODE_CLASS_MAPPINGS = {
"JSONLoaderLoRA": JSONLoaderLoRA,
"JSONLoaderStandard": JSONLoaderStandard,
"JSONLoaderVACE": JSONLoaderVACE,
"JSONLoaderBatchLoRA": JSONLoaderBatchLoRA,
"JSONLoaderBatchI2V": JSONLoaderBatchI2V,
"JSONLoaderBatchVACE": JSONLoaderBatchVACE
}
NODE_DISPLAY_NAME_MAPPINGS = {
"JSONLoaderLoRA": "JSON Loader (LoRAs Only)",
"JSONLoaderStandard": "JSON Loader (Standard/I2V)",
"JSONLoaderVACE": "JSON Loader (VACE Full)",
"JSONLoaderBatchLoRA": "JSON Batch Loader (LoRAs)",
"JSONLoaderBatchI2V": "JSON Batch Loader (I2V)",
"JSONLoaderBatchVACE": "JSON Batch Loader (VACE)"
}