Merge pull request #68 from Runware/feature-updateBriaProviderSettings

Feature update bria provider settings
This commit is contained in:
Sirshendu Ganguly
2025-12-23 15:40:01 -05:00
committed by GitHub
9 changed files with 398 additions and 3 deletions
+2
View File
@@ -32,6 +32,7 @@ from .modules.providerSettings.pixverseProviderSettings import RunwarePixversePr
from .modules.providerSettings.openaiProviderSettings import RunwareOpenAIProviderSettings
from .modules.providerSettings.bytedanceImageProviderSettings import RunwareBytedanceProviderSettings
from .modules.providerSettings.briaImageProviderSettings import RunwareBriaProviderSettings
from .modules.providerSettings.briaProviderMask import RunwareBriaProviderMask
from .modules.audioInference import RunwareAudioInference
from .modules.audioModelSearch import RunwareAudioModelSearch
from .modules.audioSections import RunwareAudioSections
@@ -113,6 +114,7 @@ NODE_CLASS_MAPPINGS = {
"Runware OpenAI Provider Settings": RunwareOpenAIProviderSettings,
"Runware Bytedance Provider Settings": RunwareBytedanceProviderSettings,
"Runware Bria Provider Settings": RunwareBriaProviderSettings,
"Runware Bria Provider Mask": RunwareBriaProviderMask,
"Runware Audio Inference": RunwareAudioInference,
"Runware Audio Model Search": RunwareAudioModelSearch,
"Runware Audio Sections": RunwareAudioSections,
+3 -1
View File
@@ -1,6 +1,6 @@
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, videoTranscriptionHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler } from "./utils.js";
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, videoTranscriptionHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler } from "./utils.js";
import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js";
const nodeInitList = [];
@@ -85,6 +85,8 @@ app.registerExtension({
audioInputToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SPEECHINPUT) {
speechInputToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.BRIAPROVIDERMASK) {
briaProviderMaskToggleHandler(node);
}
if(crNodeProps.colorModeOnly === true) return;
+5
View File
@@ -86,6 +86,7 @@ const RUNWARE_NODE_TYPES = {
OPENAIPROVIDERSETTINGS: "Runware OpenAI Provider Settings",
BYTEDANCEPROVIDERSETTINGS: "Runware Bytedance Provider Settings",
BRIAPROVIDERSETTINGS: "Runware Bria Provider Settings",
BRIAPROVIDERMASK: "Runware Bria Provider Mask",
ELEVENLABSPROVIDERSETTINGS: "Runware ElevenLabs Provider Settings",
ELEVENLABSPROVIDERSETTINGSSECTIONS: "Runware ElevenLabs Provider Settings Sections",
VIDUPROVIDERSETTINGS: "Runware Vidu Provider Settings",
@@ -275,6 +276,10 @@ const RUNWARE_NODE_PROPS = {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.BRIAPROVIDERMASK]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.ELEVENLABSPROVIDERSETTINGS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
+107
View File
@@ -1744,6 +1744,9 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
"sync:lipsync-2-pro@1 (Sync LipSync 2 Pro)",
"sync:react-1@1 (Sync React-1)",
],
"Bria": [
"bria:60@1 (Bria Video Eraser)",
],
};
const MODEL_DIMENSIONS = {
@@ -1806,6 +1809,7 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
"sync:lipsync-2@1": {"width": 0, "height": 0},
"sync:lipsync-2-pro@1": {"width": 0, "height": 0},
"sync:react-1@1": {"width": 0, "height": 0},
"bria:60@1": {"width": 1280, "height": 720},
};
const MODEL_RESOLUTIONS = {
@@ -1868,6 +1872,7 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
"sync:lipsync-2@1": "720p",
"sync:lipsync-2-pro@1": "720p",
"sync:react-1@1": "720p",
"bria:60@1": "720p",
};
const DEFAULT_DIMENSIONS = {"width": 1024, "height": 576};
@@ -2427,6 +2432,10 @@ function briaProviderSettingsToggleHandler(briaNode) {
const originalQualityWidget = briaNode.widgets.find(w => w.name === "originalQuality");
const useForceBackgroundDetectionWidget = briaNode.widgets.find(w => w.name === "useForceBackgroundDetection");
const forceBackgroundDetectionWidget = briaNode.widgets.find(w => w.name === "forceBackgroundDetection");
const useAutoTrimWidget = briaNode.widgets.find(w => w.name === "useAutoTrim");
const autoTrimWidget = briaNode.widgets.find(w => w.name === "autoTrim");
const usePreserveAudioWidget = briaNode.widgets.find(w => w.name === "usePreserveAudio");
const preserveAudioWidget = briaNode.widgets.find(w => w.name === "preserveAudio");
// Helper function to toggle widget enabled state (exact same pattern)
function toggleWidgetState(useWidget, paramWidget, paramName) {
@@ -2530,6 +2539,14 @@ function briaProviderSettingsToggleHandler(briaNode) {
if (useForceBackgroundDetectionWidget && forceBackgroundDetectionWidget) {
toggleWidgetState(useForceBackgroundDetectionWidget, forceBackgroundDetectionWidget, "forceBackgroundDetection");
}
if (useAutoTrimWidget && autoTrimWidget) {
toggleWidgetState(useAutoTrimWidget, autoTrimWidget, "autoTrim");
}
if (usePreserveAudioWidget && preserveAudioWidget) {
toggleWidgetState(usePreserveAudioWidget, preserveAudioWidget, "preserveAudio");
}
}
function audioInputToggleHandler(audioInputNode) {
@@ -2646,6 +2663,95 @@ function speechInputToggleHandler(speechInputNode) {
}
}
function briaProviderMaskToggleHandler(maskNode) {
// Helper function to toggle widget enabled state for multiple widgets
function toggleWidgetState(useWidget, paramWidgets, paramNames) {
if (!useWidget || !paramWidgets || paramWidgets.length === 0) return;
function toggleEnabled() {
const enabled = useWidget.value === true;
paramWidgets.forEach((paramWidget, idx) => {
if (!paramWidget) return;
if (paramWidget.inputEl) {
paramWidget.inputEl.disabled = !enabled;
paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5";
paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed";
paramWidget.inputEl.readOnly = !enabled;
}
// Handle dropdown widgets (for Type fields)
if (paramWidget.options && paramWidget.options.element) {
paramWidget.options.element.disabled = !enabled;
paramWidget.options.element.style.opacity = enabled ? "1" : "0.5";
paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none";
}
paramWidget.disabled = !enabled;
// Fallback: try to find inputs via DOM if inputEl is not available
if (!paramWidget.inputEl && paramNames[idx]) {
const nodeElement = maskNode.htmlElements?.widgetsContainer || maskNode.htmlElements;
if (nodeElement) {
const input = nodeElement.querySelector(`input[name="${paramNames[idx]}"], textarea[name="${paramNames[idx]}"], select[name="${paramNames[idx]}"]`);
if (input) {
input.disabled = !enabled;
input.style.opacity = enabled ? "1" : "0.5";
input.style.cursor = enabled ? "text" : "not-allowed";
input.readOnly = !enabled;
if (input.tagName === "SELECT") {
input.style.pointerEvents = enabled ? "auto" : "none";
}
}
}
}
});
maskNode.setDirtyCanvas(true);
}
// Set up callback
appendWidgetCB(useWidget, () => {
setTimeout(toggleEnabled, 50);
});
// Initial call to set initial state
setTimeout(toggleEnabled, 100);
}
// Set up toggle handlers for foreground, prompt, frameIndex
const useForegroundWidget = maskNode.widgets.find(w => w.name === "useForeground");
const foregroundWidget = maskNode.widgets.find(w => w.name === "foreground");
if (useForegroundWidget && foregroundWidget) {
toggleWidgetState(useForegroundWidget, [foregroundWidget], ["foreground"]);
}
const usePromptWidget = maskNode.widgets.find(w => w.name === "usePrompt");
const promptWidget = maskNode.widgets.find(w => w.name === "prompt");
if (usePromptWidget && promptWidget) {
toggleWidgetState(usePromptWidget, [promptWidget], ["prompt"]);
}
const useFrameIndexWidget = maskNode.widgets.find(w => w.name === "useFrameIndex");
const frameIndexWidget = maskNode.widgets.find(w => w.name === "frameIndex");
if (useFrameIndexWidget && frameIndexWidget) {
toggleWidgetState(useFrameIndexWidget, [frameIndexWidget], ["frameIndex"]);
}
// Set up toggle handlers for all 6 key points
for (let i = 1; i <= 6; i++) {
const useWidget = maskNode.widgets.find(w => w.name === `use_${i}`);
const xWidget = maskNode.widgets.find(w => w.name === `X${i}`);
const yWidget = maskNode.widgets.find(w => w.name === `Y${i}`);
const typeWidget = maskNode.widgets.find(w => w.name === `Type${i}`);
if (useWidget && xWidget && yWidget && typeWidget) {
toggleWidgetState(useWidget, [xWidget, yWidget, typeWidget], [`X${i}`, `Y${i}`, `Type${i}`]);
}
}
}
export {
notifyUser,
promptEnhanceHandler,
@@ -2679,6 +2785,7 @@ export {
settingsToggleHandler,
audioInputToggleHandler,
speechInputToggleHandler,
briaProviderMaskToggleHandler,
};
function googleProviderSettingsToggleHandler(googleNode) {
@@ -130,6 +130,29 @@ class RunwareBriaProviderSettings:
"label_on": "Enabled",
"label_off": "Disabled",
}),
"usePreserveAudio": ("BOOLEAN", {
"tooltip": "Enable to include preserveAudio parameter in API request.",
"default": False,
}),
"preserveAudio": ("BOOLEAN", {
"tooltip": "Whether to keep the original audio track. Only used when 'Use Preserve Audio' is enabled.",
"default": True,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"useAutoTrim": ("BOOLEAN", {
"tooltip": "Enable to include autoTrim parameter in API request.",
"default": False,
}),
"autoTrim": ("BOOLEAN", {
"tooltip": "If true, videos longer than 5 seconds are trimmed to the first 5 seconds. If false, videos longer than 5 seconds are rejected. Only used when 'Use Auto Trim' is enabled.",
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"Bria Provider Setting Mask": ("RUNWAREBRIAPROVIDERMASK", {
"tooltip": "Connect Runware Bria Provider Mask node to provide mask configuration for video eraser operations.",
}),
}
}
@@ -155,6 +178,8 @@ class RunwareBriaProviderSettings:
useRefinePrompt = kwargs.get("useRefinePrompt", False)
useOriginalQuality = kwargs.get("useOriginalQuality", False)
useForceBackgroundDetection = kwargs.get("useForceBackgroundDetection", False)
usePreserveAudio = kwargs.get("usePreserveAudio", False)
useAutoTrim = kwargs.get("useAutoTrim", False)
# Get actual parameters
medium = kwargs.get("medium", "photography")
@@ -169,6 +194,9 @@ class RunwareBriaProviderSettings:
refinePrompt = kwargs.get("refinePrompt", True)
originalQuality = kwargs.get("originalQuality", True)
forceBackgroundDetection = kwargs.get("forceBackgroundDetection", False)
preserveAudio = kwargs.get("preserveAudio", True)
autoTrim = kwargs.get("autoTrim", False)
mask = kwargs.get("Bria Provider Setting Mask", None)
# Build settings dictionary
settings = {}
@@ -221,6 +249,18 @@ class RunwareBriaProviderSettings:
if useForceBackgroundDetection:
settings["forceBackgroundDetection"] = forceBackgroundDetection
# Add preserveAudio only if usePreserveAudio is enabled
if usePreserveAudio:
settings["preserveAudio"] = preserveAudio
# Add autoTrim only if useAutoTrim is enabled
if useAutoTrim:
settings["autoTrim"] = autoTrim
# Add mask if provided from Mask node
if mask is not None and isinstance(mask, dict) and len(mask) > 0:
settings["mask"] = mask
# Clean up None values
settings = {k: v for k, v in settings.items() if v is not None}
@@ -0,0 +1,228 @@
"""
Runware Bria Provider Mask Node
Creates mask configuration for Bria video eraser settings
"""
from typing import Optional, Dict, Any, List
class RunwareBriaProviderMask:
"""Runware Bria Provider Mask Node"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"useForeground": ("BOOLEAN", {
"tooltip": "Enable to include mask.foreground parameter in API request.",
"default": False,
}),
"foreground": ("BOOLEAN", {
"tooltip": "Triggers the foreground mask endpoint. Only used when 'Use Foreground' is enabled.",
"default": True,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"usePrompt": ("BOOLEAN", {
"tooltip": "Enable to include mask.prompt parameter in API request.",
"default": False,
}),
"prompt": ("STRING", {
"tooltip": "Text instruction describing the object to be masked. Only used when 'Use Prompt' is enabled.",
"default": "",
"multiline": True,
}),
"useFrameIndex": ("BOOLEAN", {
"tooltip": "Enable to include mask.frameIndex parameter in API request.",
"default": False,
}),
"frameIndex": ("INT", {
"tooltip": "The frame number to apply key points to. Specifies which frame in the video to use for masking. Only used when 'Use Frame Index' is enabled.",
"default": 0,
"min": 0,
}),
"use_1": ("BOOLEAN", {
"tooltip": "Enable to include the first key point in the mask configuration.",
"default": False,
}),
"X1": ("INT", {
"tooltip": "X-coordinate of the first key point on the frame",
"default": 0,
"min": 0,
}),
"Y1": ("INT", {
"tooltip": "Y-coordinate of the first key point on the frame",
"default": 0,
"min": 0,
}),
"Type1": (["positive", "negative"], {
"tooltip": "Type of mask hint for first key point. 'positive' includes area, 'negative' excludes area.",
"default": "positive",
}),
"use_2": ("BOOLEAN", {
"tooltip": "Enable to include the second key point in the mask configuration.",
"default": False,
}),
"X2": ("INT", {
"tooltip": "X-coordinate of the second key point on the frame",
"default": 0,
"min": 0,
}),
"Y2": ("INT", {
"tooltip": "Y-coordinate of the second key point on the frame",
"default": 0,
"min": 0,
}),
"Type2": (["positive", "negative"], {
"tooltip": "Type of mask hint for second key point. 'positive' includes area, 'negative' excludes area.",
"default": "positive",
}),
"use_3": ("BOOLEAN", {
"tooltip": "Enable to include the third key point in the mask configuration.",
"default": False,
}),
"X3": ("INT", {
"tooltip": "X-coordinate of the third key point on the frame",
"default": 0,
"min": 0,
}),
"Y3": ("INT", {
"tooltip": "Y-coordinate of the third key point on the frame",
"default": 0,
"min": 0,
}),
"Type3": (["positive", "negative"], {
"tooltip": "Type of mask hint for third key point. 'positive' includes area, 'negative' excludes area.",
"default": "positive",
}),
"use_4": ("BOOLEAN", {
"tooltip": "Enable to include the fourth key point in the mask configuration.",
"default": False,
}),
"X4": ("INT", {
"tooltip": "X-coordinate of the fourth key point on the frame",
"default": 0,
"min": 0,
}),
"Y4": ("INT", {
"tooltip": "Y-coordinate of the fourth key point on the frame",
"default": 0,
"min": 0,
}),
"Type4": (["positive", "negative"], {
"tooltip": "Type of mask hint for fourth key point. 'positive' includes area, 'negative' excludes area.",
"default": "positive",
}),
"use_5": ("BOOLEAN", {
"tooltip": "Enable to include the fifth key point in the mask configuration.",
"default": False,
}),
"X5": ("INT", {
"tooltip": "X-coordinate of the fifth key point on the frame",
"default": 0,
"min": 0,
}),
"Y5": ("INT", {
"tooltip": "Y-coordinate of the fifth key point on the frame",
"default": 0,
"min": 0,
}),
"Type5": (["positive", "negative"], {
"tooltip": "Type of mask hint for fifth key point. 'positive' includes area, 'negative' excludes area.",
"default": "positive",
}),
"use_6": ("BOOLEAN", {
"tooltip": "Enable to include the sixth key point in the mask configuration.",
"default": False,
}),
"X6": ("INT", {
"tooltip": "X-coordinate of the sixth key point on the frame",
"default": 0,
"min": 0,
}),
"Y6": ("INT", {
"tooltip": "Y-coordinate of the sixth key point on the frame",
"default": 0,
"min": 0,
}),
"Type6": (["positive", "negative"], {
"tooltip": "Type of mask hint for sixth key point. 'positive' includes area, 'negative' excludes area.",
"default": "positive",
}),
}
}
RETURN_TYPES = ("RUNWAREBRIAPROVIDERMASK",)
RETURN_NAMES = ("Bria Provider Setting Mask",)
FUNCTION = "createMask"
CATEGORY = "Runware/Provider Settings"
DESCRIPTION = "Create mask configuration for Bria video eraser settings. Supports foreground mask, text-based masking, and coordinate-based key points for precise object removal."
def createMask(self, **kwargs) -> tuple[Dict[str, Any]]:
"""Create mask configuration from provided parameters"""
mask: Dict[str, Any] = {}
maskEnabled = False
# Handle foreground
useForeground = kwargs.get("useForeground", False)
if useForeground:
foreground = kwargs.get("foreground", True)
mask["foreground"] = foreground
maskEnabled = True
# Handle prompt
usePrompt = kwargs.get("usePrompt", False)
if usePrompt:
prompt = kwargs.get("prompt", "").strip()
if prompt:
mask["prompt"] = prompt
maskEnabled = True
# Handle frameIndex
useFrameIndex = kwargs.get("useFrameIndex", False)
if useFrameIndex:
frameIndex = kwargs.get("frameIndex", 0)
mask["frameIndex"] = frameIndex
maskEnabled = True
# Process key points
keyPoints: List[Dict[str, Any]] = []
for i in range(1, 7):
use_key = kwargs.get(f"use_{i}", False)
# Only process key point if use toggle is enabled
if use_key:
x = kwargs.get(f"X{i}", 0)
y = kwargs.get(f"Y{i}", 0)
point_type = kwargs.get(f"Type{i}", "positive")
# Only add key point if both x and y are provided and at least one is non-zero
if x > 0 or y > 0:
keyPoints.append({
"x": x,
"y": y,
"type": point_type
})
# Add keyPoints if any were provided
if len(keyPoints) > 0:
mask["keyPoints"] = keyPoints
maskEnabled = True
# Only return mask if it has at least one property
if maskEnabled:
return (mask,)
else:
return ({},)
# Node class mappings
NODE_CLASS_MAPPINGS = {
"RunwareBriaProviderMask": RunwareBriaProviderMask,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RunwareBriaProviderMask": "Runware Bria Provider Mask",
}
+11 -1
View File
@@ -86,6 +86,9 @@ class videoModelSearch:
"sync:lipsync-2-pro@1 (Sync LipSync 2 Pro)",
"sync:react-1@1 (Sync React-1)",
],
"Bria": [
"bria:60@1 (Bria Video Eraser)",
],
}
# Model dimensions mapping
@@ -172,6 +175,9 @@ class videoModelSearch:
"sync:lipsync-2@1": {"width": 0, "height": 0},
"sync:lipsync-2-pro@1": {"width": 0, "height": 0},
"sync:react-1@1": {"width": 0, "height": 0},
# Bria Models
"bria:60@1": {"width": 0, "height": 0},
}
# Model resolutions mapping
@@ -258,6 +264,9 @@ class videoModelSearch:
"sync:lipsync-2@1": "720p",
"sync:lipsync-2-pro@1": "720p",
"sync:react-1@1": "720p",
# Bria Models
"bria:60@1": "720p",
}
MODEL_ARCHITECTURES = [
@@ -274,7 +283,8 @@ class videoModelSearch:
"Ovi",
"Runway",
"Luma",
"Sync"
"Sync",
"Bria"
]
DEFAULT_DIMENSIONS = {"width": 1024, "height": 576}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long