Created a ComfyUI custom node that integrates Puter.js. - Added package.json for Node dependencies. - Added puter_bridge.js to communicate with Puter.js. - Added puter_node.py to define the ComfyUI nodes, communicating with the Node.js bridge. - Added install.py for autoinstallation through ComfyUI manager. - Updated README.md with prerequisites and installation instructions.
86 lines
3.2 KiB
Python
86 lines
3.2 KiB
Python
import os
|
|
import subprocess
|
|
import tempfile
|
|
import torch
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
class PuterImageGenerator:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"prompt": ("STRING", {"multiline": True, "default": "A peaceful mountain landscape at sunset"}),
|
|
"model": ([
|
|
"default",
|
|
"gemini-3.1-flash-image-preview",
|
|
"gemini-3-pro-image-preview",
|
|
"gemini-2.5-flash-image-preview",
|
|
"gpt-image-2",
|
|
"dall-e-3",
|
|
"black-forest-labs/flux-schnell",
|
|
"black-forest-labs/flux-1.1-pro",
|
|
"google/imagen-4.0-ultra",
|
|
"stabilityai/stable-diffusion-xl-base-1.0"
|
|
], {"default": "default"}),
|
|
"quality": (["default", "low", "medium", "high", "standard", "hd"], {"default": "default"}),
|
|
},
|
|
"optional": {
|
|
"image": ("IMAGE", ), # Entrada opcional para img2img
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "generate_image"
|
|
CATEGORY = "PuterAI"
|
|
|
|
def generate_image(self, prompt, model, quality, image=None):
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
bridge_script = os.path.join(current_dir, "puter_bridge.js")
|
|
|
|
# Archivo temporal para la imagen que generará Puter
|
|
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp_out:
|
|
output_path = temp_out.name
|
|
|
|
# Preparar la imagen de entrada si el usuario conectó una
|
|
input_path = "none"
|
|
if image is not None:
|
|
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp_in:
|
|
input_path = temp_in.name
|
|
|
|
img_tensor = image[0]
|
|
img_np = (img_tensor.cpu().numpy() * 255.0).clip(0, 255).astype(np.uint8)
|
|
pil_img = Image.fromarray(img_np)
|
|
pil_img.save(input_path)
|
|
|
|
try:
|
|
# Llamada al script puente de Node.js
|
|
cmd = ["node", bridge_script, prompt, model, quality, output_path, input_path]
|
|
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
|
|
# Cargar la imagen generada en ComfyUI
|
|
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
|
img = Image.open(output_path).convert("RGB")
|
|
image_np = np.array(img).astype(np.float32) / 255.0
|
|
image_tensor = torch.from_numpy(image_np)[None, ...]
|
|
return (image_tensor,)
|
|
else:
|
|
raise RuntimeError(f"El puente de Node.js falló. Error: {result.stderr}")
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
raise RuntimeError(f"Error al ejecutar Puter.js: {e.stderr}")
|
|
finally:
|
|
# Limpiar todos los archivos temporales
|
|
if os.path.exists(output_path):
|
|
os.remove(output_path)
|
|
if input_path != "none" and os.path.exists(input_path):
|
|
os.remove(input_path)
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"PuterImageGenerator": PuterImageGenerator
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"PuterImageGenerator": "Puter.js Image Generator"
|
|
}
|