Root cause of nodes not appearing in ComfyUI: this package's node classes originally reused the exact same class names as the internal fal-flux-nodes package it was migrated from (e.g. NanoBananaProEditNode, SeedreamV45EditNode). ComfyUI's NODE_CLASS_MAPPINGS is a flat global dict - when both packages are installed, whichever loads first wins and the other's registration for that key is silently dropped, which is why none of the "Superside "-prefixed nodes were showing up. Every class is now uniquely prefixed (e.g. SupersideNanoBananaProEditNode), so this package can never collide with fal-flux-nodes, ComfyUI-fal-API, or any other node pack regardless of install order. Updated __init__.py, web/js/show_text.js's TEXT_DISPLAY_NODES list, and README.md to match.
121 lines
4.1 KiB
Python
121 lines
4.1 KiB
Python
import logging
|
|
|
|
from .base_node import (
|
|
SupersideFalNode,
|
|
ImageProcessingMixin,
|
|
APIClientMixin,
|
|
API_KEY_INPUT_SPEC,
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class SupersideBriaReplaceBackgroundNode(
|
|
SupersideFalNode, ImageProcessingMixin, APIClientMixin
|
|
):
|
|
"""
|
|
Bria Replace Background Node: Replace an image's background using
|
|
bria/replace-background.
|
|
|
|
Generates a new background with realistic lighting and perspective
|
|
from a text prompt, trained on licensed data for commercial use.
|
|
"""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
"prompt": (
|
|
"STRING",
|
|
{
|
|
"multiline": True,
|
|
"placeholder": "Describe the new background scene",
|
|
},
|
|
),
|
|
"api_key": API_KEY_INPUT_SPEC,
|
|
},
|
|
"optional": {
|
|
"negative_prompt": (
|
|
"STRING",
|
|
{
|
|
"multiline": True,
|
|
"default": "",
|
|
"placeholder": "Describe what to avoid in the background",
|
|
},
|
|
),
|
|
"steps_num": ("INT", {"default": 30, "min": 1, "max": 100}),
|
|
"seed": ("INT", {"default": -1, "min": -1, "max": 2147483647, "tooltip": "-1 = random"}),
|
|
"sync_mode": ("BOOLEAN", {"default": False}),
|
|
},
|
|
"hidden": {
|
|
"unique_id": "UNIQUE_ID",
|
|
"extra_pnginfo": "EXTRA_PNGINFO",
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE", "STRING")
|
|
RETURN_NAMES = ("image", "info")
|
|
FUNCTION = "generate"
|
|
OUTPUT_NODE = True
|
|
DESCRIPTION = (
|
|
"Replace an image's background using Bria Replace Background on fal.ai. "
|
|
"Generates realistic lighting and perspective from a text prompt."
|
|
)
|
|
|
|
def prepare_arguments(self, client, image, prompt, **kwargs):
|
|
image_url = self.upload_image(client, image)
|
|
|
|
arguments = {
|
|
"image_url": image_url,
|
|
"prompt": prompt,
|
|
}
|
|
|
|
if kwargs.get("negative_prompt"):
|
|
arguments["negative_prompt"] = kwargs["negative_prompt"]
|
|
|
|
if kwargs.get("steps_num") is not None:
|
|
arguments["steps_num"] = kwargs["steps_num"]
|
|
|
|
seed = kwargs.get("seed", -1)
|
|
if seed is not None and seed != -1:
|
|
arguments["seed"] = seed
|
|
|
|
if kwargs.get("sync_mode") is not None:
|
|
arguments["sync_mode"] = kwargs["sync_mode"]
|
|
|
|
return arguments
|
|
|
|
def generate(self, image, prompt, api_key, unique_id=None, extra_pnginfo=None, **kwargs):
|
|
try:
|
|
client = self.get_client(api_key)
|
|
arguments = self.prepare_arguments(client, image, prompt, **kwargs)
|
|
result = self.call_api(client, "bria/replace-background", arguments)
|
|
|
|
# This endpoint returns a single "image" object, not an "images" list.
|
|
image_data = result.get("image")
|
|
if not isinstance(image_data, dict) or "url" not in image_data:
|
|
raise RuntimeError("No image was generated by the API.")
|
|
|
|
images = self.process_images({"images": [image_data]})
|
|
info = image_data.get("url", "")
|
|
|
|
if unique_id is not None and extra_pnginfo is not None:
|
|
if (
|
|
isinstance(extra_pnginfo, list)
|
|
and isinstance(extra_pnginfo[0], dict)
|
|
and "workflow" in extra_pnginfo[0]
|
|
):
|
|
workflow = extra_pnginfo[0]["workflow"]
|
|
node = next(
|
|
(x for x in workflow["nodes"] if str(x["id"]) == str(unique_id)),
|
|
None,
|
|
)
|
|
if node:
|
|
node["widgets_values"] = [info]
|
|
|
|
return {"ui": {"text": [info]}, "result": (images[0], info)}
|
|
except Exception as e:
|
|
logger.error(f"Bria replace background failed: {str(e)}")
|
|
raise RuntimeError(f"Bria replace background failed: {str(e)}") from e
|