add time generation duration output to api nodes
This commit is contained in:
+14
-4
@@ -94,8 +94,8 @@ class FalAPI_Flux2KleinEdit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_image"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -165,12 +165,19 @@ class FalAPI_Flux2KleinEdit:
|
||||
mean_val = tensor.mean().item()
|
||||
return mean_val < 0.01
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_image(self, api_key, model_variant, prompt, image1, width, height,
|
||||
image2=None, image3=None, negative_prompt="", num_inference_steps=28,
|
||||
guidance_scale=5.0, lora_url="", lora_scale=1.0, seed=-1,
|
||||
output_format="png", enable_safety_checker=True, acceleration="none"):
|
||||
|
||||
print(f"[Flux2KleinEdit] Starting image generation process with {model_variant} model...")
|
||||
start_time = time.time()
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("A FAL API key is required.")
|
||||
@@ -283,7 +290,9 @@ class FalAPI_Flux2KleinEdit:
|
||||
else:
|
||||
batch_tensor = final_tensors[0]
|
||||
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[Flux2KleinEdit] Generation completed in {generation_time} seconds")
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[Flux2KleinEdit] Error: {str(e)}")
|
||||
@@ -296,7 +305,8 @@ class FalAPI_Flux2KleinEdit:
|
||||
"error": f"Flux2KleinEdit generation failed: {str(e)}",
|
||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
finally:
|
||||
# Cleanup temp inputs
|
||||
|
||||
+14
-4
@@ -89,8 +89,8 @@ class FalAPI_Flux2LoraEdit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_image"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -153,12 +153,19 @@ class FalAPI_Flux2LoraEdit:
|
||||
img_array = np.array(pil_img).astype(np.float32) / 255.0
|
||||
return torch.from_numpy(img_array)[None,]
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_image(self, api_key, prompt, image1, width, height,
|
||||
image2=None, image3=None, num_inference_steps=28, guidance_scale=2.5,
|
||||
lora_url="", lora_scale=1.0, seed=-1, output_format="png",
|
||||
enable_safety_checker=True, enable_prompt_expansion=False, acceleration="regular"):
|
||||
|
||||
print("[Flux2LoraEdit] Starting image generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("A FAL API key is required.")
|
||||
@@ -265,7 +272,9 @@ class FalAPI_Flux2LoraEdit:
|
||||
else:
|
||||
batch_tensor = final_tensors[0]
|
||||
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[Flux2LoraEdit] Generation completed in {generation_time} seconds")
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[Flux2LoraEdit] Error: {str(e)}")
|
||||
@@ -278,7 +287,8 @@ class FalAPI_Flux2LoraEdit:
|
||||
"error": f"Flux2LoraEdit generation failed: {str(e)}",
|
||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
finally:
|
||||
# Cleanup temp inputs
|
||||
|
||||
+14
-4
@@ -62,8 +62,8 @@ class FalAPI_Flux2TurboEdit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_image"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -126,11 +126,18 @@ class FalAPI_Flux2TurboEdit:
|
||||
img_array = np.array(pil_img).astype(np.float32) / 255.0
|
||||
return torch.from_numpy(img_array)[None,]
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_image(self, api_key, prompt, image1, width, height,
|
||||
image2=None, image3=None, guidance_scale=2.5,
|
||||
seed=-1, output_format="png", enable_safety_checker=True):
|
||||
|
||||
print("[Flux2TurboEdit] Starting image generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("A FAL API key is required.")
|
||||
@@ -229,7 +236,9 @@ class FalAPI_Flux2TurboEdit:
|
||||
else:
|
||||
batch_tensor = final_tensors[0]
|
||||
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[Flux2TurboEdit] Generation completed in {generation_time} seconds")
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[Flux2TurboEdit] Error: {str(e)}")
|
||||
@@ -242,7 +251,8 @@ class FalAPI_Flux2TurboEdit:
|
||||
"error": f"Flux2TurboEdit generation failed: {str(e)}",
|
||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
finally:
|
||||
# Cleanup temp inputs
|
||||
|
||||
+14
-4
@@ -34,8 +34,8 @@ class FalAPI_kling_video:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING",)
|
||||
RETURN_NAMES = ("video_path", "generation_info",)
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("video_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_video"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -107,11 +107,18 @@ class FalAPI_kling_video:
|
||||
except Exception as e:
|
||||
print(f"[Kling Video] Error in queue update: {e}")
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
def generate_video(self, api_token, image, prompt):
|
||||
"""
|
||||
Generate video using fal-ai/kling-video/v2.1/standard/image-to-video
|
||||
"""
|
||||
print(f"[Kling Video] Starting video generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
# For errors, return empty strings
|
||||
empty_path = ""
|
||||
@@ -231,7 +238,9 @@ class FalAPI_kling_video:
|
||||
print(f"[Kling Video] Saved metadata -> {metadata_path}")
|
||||
|
||||
# 10) Return the video path & metadata JSON string
|
||||
return (video_path, json.dumps(generation_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[Kling Video] Generation completed in {generation_time} seconds")
|
||||
return (video_path, json.dumps(generation_info, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
# Return empty path and an error message in JSON
|
||||
@@ -241,7 +250,8 @@ class FalAPI_kling_video:
|
||||
"model": "fal-ai/kling-video/v2.1/standard/image-to-video"
|
||||
}
|
||||
print(f"[Kling Video] Error: {str(e)}")
|
||||
return (empty_path, json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (empty_path, json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
def tensor_to_tempfile(self, tensor):
|
||||
"""
|
||||
|
||||
+14
-4
@@ -160,8 +160,8 @@ class FalAPI_ltx2_video:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VIDEO", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("video", "video_path", "generation_info",)
|
||||
RETURN_TYPES = ("VIDEO", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("video", "video_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_video"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -230,6 +230,12 @@ class FalAPI_ltx2_video:
|
||||
arr = (arr * 255).clip(0, 255).astype("uint8")
|
||||
return Image.fromarray(arr)
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_video(self, api_token, model_variant, image, prompt, num_frames, width, height, fps, image_strength,
|
||||
negative_prompt="", guidance_scale=3.0, num_inference_steps=40, use_multiscale=True,
|
||||
generate_audio=False, enable_safety_checker=True, acceleration="none",
|
||||
@@ -239,6 +245,7 @@ class FalAPI_ltx2_video:
|
||||
"""Generate video using fal-ai/ltx-2-19b/image-to-video/lora (Async execution)"""
|
||||
|
||||
print(f"[LTX-2 Video] Starting video generation with {model_variant} model...")
|
||||
start_time = time.time()
|
||||
|
||||
empty_path = ""
|
||||
|
||||
@@ -397,7 +404,9 @@ class FalAPI_ltx2_video:
|
||||
# Create VideoFromFile object for ComfyUI's VIDEO type
|
||||
video_output = VideoFromFile(video_path)
|
||||
|
||||
return (video_output, video_path, json.dumps(generation_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[LTX-2 Video] Generation completed in {generation_time} seconds")
|
||||
return (video_output, video_path, json.dumps(generation_info, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
# Clean up temp file on error
|
||||
@@ -413,7 +422,8 @@ class FalAPI_ltx2_video:
|
||||
"model": f"fal-ai/ltx-2-19b/{model_variant}/image-to-video/lora"
|
||||
}
|
||||
print(f"[LTX-2 Video] Error: {str(e)}")
|
||||
return (None, empty_path, json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (None, empty_path, json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, **kwargs):
|
||||
|
||||
+14
-4
@@ -85,8 +85,8 @@ class FalAPI_QwenEditPlus:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_image"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -149,12 +149,19 @@ class FalAPI_QwenEditPlus:
|
||||
img_array = np.array(pil_img).astype(np.float32) / 255.0
|
||||
return torch.from_numpy(img_array)[None,]
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_image(self, api_key, prompt, image1, width, height,
|
||||
image2=None, image3=None, num_inference_steps=28, guidance_scale=4.0,
|
||||
lora_url="", lora_scale=0.84, seed=-1, output_format="png",
|
||||
enable_safety_checker=True, acceleration="regular"):
|
||||
|
||||
print("[QwenEditPlus] Starting image generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("A FAL API key is required.")
|
||||
@@ -260,7 +267,9 @@ class FalAPI_QwenEditPlus:
|
||||
else:
|
||||
batch_tensor = final_tensors[0]
|
||||
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[QwenEditPlus] Generation completed in {generation_time} seconds")
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[QwenEditPlus] Error: {str(e)}")
|
||||
@@ -273,7 +282,8 @@ class FalAPI_QwenEditPlus:
|
||||
"error": f"QwenEditPlus generation failed: {str(e)}",
|
||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
finally:
|
||||
# Cleanup temp inputs
|
||||
|
||||
+14
-4
@@ -33,8 +33,8 @@ class FalAPI_recraft_upscale:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING",)
|
||||
RETURN_NAMES = ("upscaled_image", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("upscaled_image", "generation_info", "generation_time",)
|
||||
FUNCTION = "upscale"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -105,11 +105,18 @@ class FalAPI_recraft_upscale:
|
||||
except Exception as e:
|
||||
print(f"[Recraft Upscale] Error in queue update: {e}")
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
def upscale(self, api_token, image, enable_safety_checker):
|
||||
"""
|
||||
Upscale image using fal-ai/recraft/upscale/crisp
|
||||
"""
|
||||
print(f"[Recraft Upscale] Starting upscale process...")
|
||||
start_time = time.time()
|
||||
|
||||
# For errors, return an empty 1024x1024 image
|
||||
empty_image = torch.zeros((1, 1024, 1024, 3))
|
||||
@@ -241,7 +248,9 @@ class FalAPI_recraft_upscale:
|
||||
print(f"[Recraft Upscale] Final tensor shape: {img_tensor.shape}")
|
||||
|
||||
# 11) Return the image tensor & metadata JSON string
|
||||
return (img_tensor, json.dumps(generation_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[Recraft Upscale] Upscale completed in {generation_time} seconds")
|
||||
return (img_tensor, json.dumps(generation_info, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
# Return an empty image and an error message in JSON
|
||||
@@ -251,7 +260,8 @@ class FalAPI_recraft_upscale:
|
||||
"model": "fal-ai/recraft/upscale/crisp"
|
||||
}
|
||||
print(f"[Recraft Upscale] Error: {str(e)}")
|
||||
return (empty_image, json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (empty_image, json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
def tensor_to_tempfile(self, tensor):
|
||||
"""
|
||||
|
||||
+14
-4
@@ -92,8 +92,8 @@ class FalAPI_seedance_video:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VIDEO", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("video", "video_path", "generation_info",)
|
||||
RETURN_TYPES = ("VIDEO", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("video", "video_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_video"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -140,6 +140,12 @@ class FalAPI_seedance_video:
|
||||
except Exception as e:
|
||||
print(f"[Seedance Video] Error in queue update: {e}")
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_video(self, api_token, image, prompt, aspect_ratio, resolution,
|
||||
duration, camera_fixed, generate_audio, enable_safety_checker, end_image=None, seed=-1):
|
||||
"""
|
||||
@@ -147,6 +153,7 @@ class FalAPI_seedance_video:
|
||||
(Async execution for parallel processing)
|
||||
"""
|
||||
print(f"[Seedance Video] Starting video generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
# For errors, return empty strings
|
||||
empty_path = ""
|
||||
@@ -316,7 +323,9 @@ class FalAPI_seedance_video:
|
||||
video_output = VideoFromFile(video_path)
|
||||
|
||||
# 11) Return the video object, video path string & metadata JSON string
|
||||
return (video_output, video_path, json.dumps(generation_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[Seedance Video] Generation completed in {generation_time} seconds")
|
||||
return (video_output, video_path, json.dumps(generation_info, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
# Return None for video, empty path and an error message in JSON
|
||||
@@ -326,7 +335,8 @@ class FalAPI_seedance_video:
|
||||
"model": "fal-ai/bytedance/seedance/v1.5/pro/image-to-video"
|
||||
}
|
||||
print(f"[Seedance Video] Error: {str(e)}")
|
||||
return (None, empty_path, json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (None, empty_path, json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
def tensor_to_tempfile(self, tensor):
|
||||
"""
|
||||
|
||||
+16
-5
@@ -72,8 +72,8 @@ class FalAPI_NanoBananaPro:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("images", "image_paths", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("images", "image_paths", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_image"
|
||||
CATEGORY = "FAL"
|
||||
|
||||
@@ -132,9 +132,16 @@ class FalAPI_NanoBananaPro:
|
||||
arr = (arr * 255).clip(0, 255).astype("uint8")
|
||||
return Image.fromarray(arr)
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_image(self, api_key, prompt, num_images, image1, aspect_ratio, resolution,
|
||||
image2=None, image3=None, image4=None, seed=-1):
|
||||
print("[NanoBananaPro] Starting generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("A FAL API Key is required.")
|
||||
@@ -238,7 +245,8 @@ class FalAPI_NanoBananaPro:
|
||||
path, _ = await asyncio.to_thread(self.save_image_and_metadata, black_pil, timeout_info, number)
|
||||
saved_paths.append(path)
|
||||
|
||||
return (black_tensor, ";".join(saved_paths), json.dumps(timeout_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (black_tensor, ";".join(saved_paths), json.dumps(timeout_info, indent=2), generation_time)
|
||||
|
||||
# Check status
|
||||
try:
|
||||
@@ -326,7 +334,9 @@ class FalAPI_NanoBananaPro:
|
||||
else:
|
||||
batch_tensor = final_tensors[0]
|
||||
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[NanoBananaPro] Generation completed in {generation_time} seconds")
|
||||
return (batch_tensor, ";".join(saved_paths), json.dumps(result, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[NanoBananaPro] Error: {e}")
|
||||
@@ -337,7 +347,8 @@ class FalAPI_NanoBananaPro:
|
||||
|
||||
# Return empty/error
|
||||
empty = torch.zeros((1, 64, 64, 3))
|
||||
return (empty, "", str(e))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (empty, "", str(e), generation_time)
|
||||
|
||||
finally:
|
||||
# Cleanup temp inputs
|
||||
|
||||
+14
-4
@@ -63,8 +63,8 @@ class WaveSpeedAI_Image:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_image"
|
||||
CATEGORY = "WaveSpeedAI"
|
||||
|
||||
@@ -93,6 +93,7 @@ class WaveSpeedAI_Image:
|
||||
image2=None, image3=None, lora_url="", lora_scale=0.84,
|
||||
seed=-1, output_format="jpeg"):
|
||||
print("[WaveSpeedAI] Starting image generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("A WaveSpeedAI API key is required.")
|
||||
@@ -183,7 +184,9 @@ class WaveSpeedAI_Image:
|
||||
pil_image = Image.open(BytesIO(resp.content))
|
||||
output_tensor = self.pil_to_tensor(pil_image)
|
||||
|
||||
return (output_tensor, image_path, json.dumps(generation_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[WaveSpeedAI] Generation completed in {generation_time} seconds")
|
||||
return (output_tensor, image_path, json.dumps(generation_info, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
error_info = {
|
||||
@@ -191,7 +194,8 @@ class WaveSpeedAI_Image:
|
||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
print(f"[WaveSpeedAI] Error: {str(e)}")
|
||||
return (None, "", json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (None, "", json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
def tensor_to_data_uri(self, tensor, image_format="PNG"):
|
||||
pil_img = self.tensor_to_pil(tensor)
|
||||
@@ -210,6 +214,12 @@ class WaveSpeedAI_Image:
|
||||
img_array = np.array(pil_img).astype(np.float32) / 255.0
|
||||
return torch.from_numpy(img_array)[None,]
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@@ -57,8 +57,8 @@ class WaveSpeedAI_Flux2LoraEdit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info",)
|
||||
RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING",)
|
||||
RETURN_NAMES = ("image", "image_path", "generation_info", "generation_time",)
|
||||
FUNCTION = "generate_image"
|
||||
CATEGORY = "WaveSpeedAI"
|
||||
|
||||
@@ -100,10 +100,17 @@ class WaveSpeedAI_Flux2LoraEdit:
|
||||
img_array = np.array(pil_img).astype(np.float32) / 255.0
|
||||
return torch.from_numpy(img_array)[None,]
|
||||
|
||||
def format_generation_time(self, elapsed_seconds):
|
||||
"""Format elapsed time as 'seconds-centiseconds' (e.g., '14-50' for 14.50 seconds)"""
|
||||
seconds = int(elapsed_seconds)
|
||||
centiseconds = int((elapsed_seconds - seconds) * 100)
|
||||
return f"{seconds}-{centiseconds:02d}"
|
||||
|
||||
async def generate_image(self, api_key, prompt, image1, width, height, image2=None, image3=None,
|
||||
lora_url="", lora_scale=1.0, seed=-1):
|
||||
|
||||
print("[WaveSpeedAI Flux2] Starting image generation process...")
|
||||
start_time = time.time()
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("A WaveSpeedAI API key is required.")
|
||||
@@ -215,7 +222,9 @@ class WaveSpeedAI_Flux2LoraEdit:
|
||||
pil_image = Image.open(BytesIO(resp.content)).convert("RGB")
|
||||
output_tensor = self.pil_to_tensor(pil_image)
|
||||
|
||||
return (output_tensor, image_path, json.dumps(generation_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
print(f"[WaveSpeedAI Flux2] Generation completed in {generation_time} seconds")
|
||||
return (output_tensor, image_path, json.dumps(generation_info, indent=2), generation_time)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[WaveSpeedAI Flux2] Error: {str(e)}")
|
||||
@@ -223,7 +232,8 @@ class WaveSpeedAI_Flux2LoraEdit:
|
||||
"error": f"WaveSpeedAI Flux2 generation failed: {str(e)}",
|
||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2))
|
||||
generation_time = self.format_generation_time(time.time() - start_time)
|
||||
return (torch.zeros((1, 64, 64, 3)), "", json.dumps(error_info, indent=2), generation_time)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user