- Add Runware Video Background Removal node with Bria support - Add Runware Video Upscaler node with Bria support - Add Runware Vectorize node for image vectorization - Add Lightricks Provider Settings node - Add Video Inference Inputs node for structured inputs - Add Input Audios and Reference Videos nodes - Update video inference with speech support and reference videos - Add new video models: OmniHuman 1/1.5, PixVerse LipSync, LTX - Update Bytedance provider settings with boolean controls - Add corresponding workflow examples
71 lines
3.1 KiB
JavaScript
71 lines
3.1 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
import { api } from "../../scripts/api.js";
|
|
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, handleCustomErrors } from "./utils.js";
|
|
import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js";
|
|
|
|
const nodeInitList = [];
|
|
app.registerExtension({
|
|
name: "runware.ai",
|
|
async setup() {
|
|
api.addEventListener('runwareError', handleCustomErrors);
|
|
api.addEventListener('runwareImageCaption', captionNodeHandler);
|
|
api.addEventListener('runwareMediaUUID', mediaUUIDHandler);
|
|
},
|
|
|
|
async nodeCreated(node) {
|
|
const nodeClass = node.comfyClass;
|
|
let crNodeProps = false;
|
|
if(typeof nodeClass === "string" && Object.values(RUNWARE_NODE_TYPES).includes(nodeClass)) {
|
|
crNodeProps = RUNWARE_NODE_PROPS[nodeClass];
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
node.bgcolor = crNodeProps.bgColor;
|
|
if(nodeClass === RUNWARE_NODE_TYPES.APIMANAGER) {
|
|
APIKeyHandler(node);
|
|
} else if(nodeClass === RUNWARE_NODE_TYPES.IMAGECAPTION) {
|
|
const captionInput = node.widgets[1].inputEl;
|
|
captionInput.style.outline = "none";
|
|
captionInput.readOnly = true;
|
|
return;
|
|
} else if(nodeClass === RUNWARE_NODE_TYPES.MEDIAUPLOAD) {
|
|
// Style the mediaUUID widget to show full UUID
|
|
const mediaUUIDWidget = node.widgets.find(widget => widget.name === "mediaUUID");
|
|
if(mediaUUIDWidget && mediaUUIDWidget.inputEl) {
|
|
mediaUUIDWidget.inputEl.style.width = "100%";
|
|
mediaUUIDWidget.inputEl.style.minWidth = "300px";
|
|
mediaUUIDWidget.inputEl.style.fontSize = "11px";
|
|
mediaUUIDWidget.inputEl.style.fontFamily = "monospace";
|
|
}
|
|
}
|
|
|
|
if(crNodeProps.colorModeOnly === true) return;
|
|
const nodeWidgets = node.widgets;
|
|
if(nodeWidgets.length <= 0) return;
|
|
|
|
for(const nodeWidget of nodeWidgets) {
|
|
const widgetName = nodeWidget.name;
|
|
const widgetType = nodeWidget.type;
|
|
|
|
if(crNodeProps.promptEnhancer === true && widgetType === "customtext") {
|
|
if (widgetName === "positivePrompt" || widgetName === "negativePrompt") {
|
|
nodeWidget.inputEl.addEventListener('keydown', promptEnhanceHandler);
|
|
}
|
|
} else if(crNodeProps.liveDimensions === true && widgetType === "combo" && widgetName === "dimensions") {
|
|
syncDimensionsNodeHandler(node, nodeWidget);
|
|
}
|
|
|
|
if(crNodeProps.liveSearch === true) {
|
|
if(widgetType === "text" && SEARCH_TERMS.includes(widgetName)) {
|
|
node.callback = function(){};
|
|
searchNodeHandler(node, nodeWidget);
|
|
nodeInitList.push(node);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
loadedGraphNode(node) {
|
|
if(nodeInitList.includes(node)) node.callback();
|
|
}
|
|
}) |