Files
Superside-comfyui-superside…/modules/bria_replace_background_node.py
T
Superside ComfyUI NodesandClaude Sonnet 5 1d6c8ce140 Revert to bria/replace-background (that IS "Replace Background V2")
The previous commit wrongly switched to fal-ai/bria/background/replace.
Inspecting fal's model page, its endpoint dropdown lists "Replace Background
V2" and "Background Replace" as two DISTINCT options: "Replace Background V2"
maps to endpoint bria/replace-background (the eCommerce product-shot model,
the page the user referenced), while fal-ai/bria/background/replace is the
separate "Background Replace" option. So bria/replace-background is the V2 -
restore it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 12:00:58 -04:00

124 lines
4.3 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 V2 Node: Replace an image's background using
Bria's Replace Background V2 model on fal.ai (endpoint id
"bria/replace-background" - note there is no "fal-ai/" prefix on this
one; the prefixed form 404s).
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 V2 on "
"fal.ai (endpoint bria/replace-background). 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