diff --git a/__init__.py b/__init__.py index d08c07c..b79440f 100644 --- a/__init__.py +++ b/__init__.py @@ -71,6 +71,7 @@ from .modules.safetyInputs import safetyInputs from .modules.settings import RunwareSettings from .modules.videoAdvancedFeatureInputs import videoAdvancedFeatureInputs from .modules.advancedFeatureSettings.wanAnimateAdvancedFeatureSettings import RunwareWanAnimateAdvancedFeatureSettings +from .modules.videoOutputs import RunwareVideoInferenceOutputs RUNWARE_COMFYUI_VERSION = "1.4.0 Beta" @@ -156,6 +157,7 @@ NODE_CLASS_MAPPINGS = { "Runware Settings": RunwareSettings, "Runware Video Advanced Feature Inputs": videoAdvancedFeatureInputs, "Runware Wan Animate Advanced Feature Settings": RunwareWanAnimateAdvancedFeatureSettings, + "Runware Video Inference Outputs": RunwareVideoInferenceOutputs, } NODE_DISPLAY_NAME_MAPPINGS = { diff --git a/clientlibs/main.js b/clientlibs/main.js index 3041139..22fde98 100644 --- a/clientlibs/main.js +++ b/clientlibs/main.js @@ -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, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } from "./utils.js"; +import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } from "./utils.js"; import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js"; const nodeInitList = []; @@ -11,6 +11,7 @@ app.registerExtension({ api.addEventListener('runwareImageCaption', captionNodeHandler); api.addEventListener('runwareMediaUUID', mediaUUIDHandler); api.addEventListener('runwareVideoTranscription', videoTranscriptionHandler); + api.addEventListener('runwareVideoOutputs', videoOutputsHandler); }, async nodeCreated(node) { @@ -39,6 +40,18 @@ app.registerExtension({ mediaUUIDWidget.inputEl.style.fontSize = "11px"; mediaUUIDWidget.inputEl.style.fontFamily = "monospace"; } + } else if(nodeClass === RUNWARE_NODE_TYPES.VIDEOINFERENCEOUTPUTS) { + // Style draftId and videoId widgets to show full IDs (like Media Upload) + const draftIdWidget = node.widgets.find(widget => widget.name === "draftId"); + const videoIdWidget = node.widgets.find(widget => widget.name === "videoId"); + for(const w of [draftIdWidget, videoIdWidget]) { + if(w && w.inputEl) { + w.inputEl.style.width = "100%"; + w.inputEl.style.minWidth = "300px"; + w.inputEl.style.fontSize = "11px"; + w.inputEl.style.fontFamily = "monospace"; + } + } } const nodeWidgets = node.widgets; diff --git a/clientlibs/types.js b/clientlibs/types.js index 5d7d325..591f170 100644 --- a/clientlibs/types.js +++ b/clientlibs/types.js @@ -121,6 +121,7 @@ const RUNWARE_NODE_TYPES = { SETTINGS: "Runware Settings", VIDEOADVANCEDFEATUREINPUTS: "Runware Video Advanced Feature Inputs", WANANIMATEADVANCEDFEATURESETTINGS: "Runware Wan Animate Advanced Feature Settings", + VIDEOINFERENCEOUTPUTS: "Runware Video Inference Outputs", }; const RUNWARE_NODE_PROPS = { @@ -420,6 +421,10 @@ const RUNWARE_NODE_PROPS = { bgColor: DEFAULT_BGCOLOR, colorModeOnly: true, }, + [RUNWARE_NODE_TYPES.VIDEOINFERENCEOUTPUTS]: { + bgColor: DEFAULT_BGCOLOR, + colorModeOnly: true, + }, }; export { diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 9a13edf..d03d23b 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -106,6 +106,44 @@ function videoTranscriptionHandler(msgEvent) { return false; } +function videoOutputsHandler(msgEvent) { + const outputData = msgEvent.detail; + const draftId = outputData.draftId || ""; + const videoId = outputData.videoId || ""; + const nodeID = outputData.nodeID; + + if(outputData.success && nodeID !== undefined && nodeID !== null) { + const nodeIdInt = typeof nodeID === 'string' ? parseInt(nodeID) : nodeID; + const outputNode = app.graph.getNodeById(nodeIdInt); + + if(outputNode !== null && outputNode !== undefined) { + const draftIdWidget = outputNode.widgets.find(widget => widget.name === "draftId"); + const videoIdWidget = outputNode.widgets.find(widget => widget.name === "videoId"); + + if(draftIdWidget) { + if(draftIdWidget.value !== undefined) draftIdWidget.value = draftId; + if(draftIdWidget.inputEl) { + draftIdWidget.inputEl.value = draftId; + draftIdWidget.inputEl.dispatchEvent(new Event('input', { bubbles: true })); + draftIdWidget.inputEl.dispatchEvent(new Event('change', { bubbles: true })); + } + } + + if(videoIdWidget) { + if(videoIdWidget.value !== undefined) videoIdWidget.value = videoId; + if(videoIdWidget.inputEl) { + videoIdWidget.inputEl.value = videoId; + videoIdWidget.inputEl.dispatchEvent(new Event('input', { bubbles: true })); + videoIdWidget.inputEl.dispatchEvent(new Event('change', { bubbles: true })); + } + } + + outputNode.setDirtyCanvas(true); + } + } + return false; +} + function notifyUser(message, type="info", title = "Runware", life = 4.5) { app.extensionManager.toast.add({ severity: type, // 'info', 'success', 'warn', 'error' \\ @@ -1131,6 +1169,8 @@ function bytedanceProviderSettingsToggleHandler(bytedanceNode) { const fastModeWidget = bytedanceNode.widgets.find(w => w.name === "fastMode"); const useAudioWidget = bytedanceNode.widgets.find(w => w.name === "useAudio"); const audioWidget = bytedanceNode.widgets.find(w => w.name === "audio"); + const useDraftWidget = bytedanceNode.widgets.find(w => w.name === "useDraft"); + const draftWidget = bytedanceNode.widgets.find(w => w.name === "draft"); // Helper function to toggle widget enabled state (exact same pattern) function toggleWidgetState(useWidget, paramWidget, paramName) { @@ -1189,6 +1229,10 @@ function bytedanceProviderSettingsToggleHandler(bytedanceNode) { if (useAudioWidget && audioWidget) { toggleWidgetState(useAudioWidget, audioWidget, "audio"); } + + if (useDraftWidget && draftWidget) { + toggleWidgetState(useDraftWidget, draftWidget, "draft"); + } } function openaiProviderSettingsToggleHandler(openaiNode) { @@ -3149,6 +3193,7 @@ export { mediaUUIDHandler, captionNodeHandler, videoTranscriptionHandler, + videoOutputsHandler, handleCustomErrors, APIKeyHandler, videoInferenceDimensionsHandler, diff --git a/modules/providerSettings/bytedanceImageProviderSettings.py b/modules/providerSettings/bytedanceImageProviderSettings.py index cd644d6..e8da86f 100644 --- a/modules/providerSettings/bytedanceImageProviderSettings.py +++ b/modules/providerSettings/bytedanceImageProviderSettings.py @@ -47,6 +47,14 @@ class RunwareBytedanceProviderSettings: "tooltip": "Enable audio generation support when available.", "default": False, }), + "useDraft": ("BOOLEAN", { + "tooltip": "Enable to include draft parameter in provider settings", + "default": False, + }), + "draft": ("BOOLEAN", { + "tooltip": "Enable draft mode for Bytedance provider", + "default": False, + }), } } @@ -63,12 +71,14 @@ class RunwareBytedanceProviderSettings: useMaxSequentialImages = kwargs.get("useMaxSequentialImages", False) useFastMode = kwargs.get("useFastMode", False) useAudio = kwargs.get("useAudio", False) + useDraft = kwargs.get("useDraft", False) # Get value parameters cameraFixed = kwargs.get("cameraFixed", False) maxSequentialImages = kwargs.get("maxSequentialImages", 1) fastMode = kwargs.get("fastMode", False) audio = kwargs.get("audio", False) + draft = kwargs.get("draft", False) # Build settings dictionary - only include what is enabled settings = {} @@ -88,6 +98,10 @@ class RunwareBytedanceProviderSettings: # Add audio only if useAudio is enabled if useAudio: settings["audio"] = audio + + # Add draft only if useDraft is enabled + if useDraft: + settings["draft"] = draft # Clean up None values settings = {k: v for k, v in settings.items() if v is not None} diff --git a/modules/utils/runwareUtils.py b/modules/utils/runwareUtils.py index 3be6cd9..fa70e76 100644 --- a/modules/utils/runwareUtils.py +++ b/modules/utils/runwareUtils.py @@ -317,6 +317,19 @@ def sendVideoTranscription(transcriptionText, nodeID): }, ) + +def sendVideoOutputs(draftId, videoId, nodeID): + """Send draftId and videoId to frontend for display in Video Inference Outputs node textboxes.""" + PromptServer.instance.send_sync( + "runwareVideoOutputs", + { + "success": True, + "draftId": draftId or "", + "videoId": videoId or "", + "nodeID": nodeID, + }, + ) + def inferenecRequest(genConfig): global RUNWARE_API_KEY, RUNWARE_API_BASE_URL, SESSION_TIMEOUT RUNWARE_API_KEY = os.getenv("RUNWARE_API_KEY") diff --git a/modules/videoBgRemoval.py b/modules/videoBgRemoval.py index 3b0debf..26c17e8 100644 --- a/modules/videoBgRemoval.py +++ b/modules/videoBgRemoval.py @@ -125,7 +125,8 @@ class videoBgRemoval: if status == "success": if "videoURL" in videoData or "videoBase64Data" in videoData: videos = rwUtils.convertVideoB64List(pollResult, 1920, 1080) - return videos + # SaveVideo expects a single video object, not a tuple + return (videos[0],) if len(videos) > 0 else (None,) comfy.model_management.throw_exception_if_processing_interrupted() diff --git a/modules/videoInference.py b/modules/videoInference.py index 0e8525a..40d1033 100644 --- a/modules/videoInference.py +++ b/modules/videoInference.py @@ -141,8 +141,8 @@ class txt2vid: DESCRIPTION = "Generates Videos Lightning Fast With Runware Video Inference Engine." FUNCTION = "generateVideo" - RETURN_TYPES = ("VIDEO", "RUNWARETASK") - RETURN_NAMES = ("VIDEO", "RW-Task") + RETURN_TYPES = ("VIDEO", "RUNWARETASK", "RUNWARETASK") + RETURN_NAMES = ("VIDEO", "RW-Task", "OUTPUT") CATEGORY = "Runware" def generateVideo(self, **kwargs): @@ -325,7 +325,7 @@ class txt2vid: genConfig[0]["acceleration"] = acceleration if (multiInferenceMode): - return (None, genConfig) + return (None, genConfig, None) else: try: # Debug: Print the request being sent @@ -388,7 +388,9 @@ class txt2vid: if status == "success": if "videoURL" in video_data or "videoBase64Data" in video_data: videos = rwUtils.convertVideoB64List(pollResult, width, height) - return videos + # SaveVideo expects a single video object, not a tuple + video_output = videos[0] if len(videos) > 0 else None + return (video_output, genConfig, pollResult) # If status is "processing", continue polling diff --git a/modules/videoInferenceInputs.py b/modules/videoInferenceInputs.py index cc12b1a..d367eb6 100644 --- a/modules/videoInferenceInputs.py +++ b/modules/videoInferenceInputs.py @@ -43,6 +43,16 @@ class videoInferenceInputs: "Reference Voices": ("RUNWAREREFERENCEVOICES", { "tooltip": "Connect the Reference Voices node to provide reference voice URLs or mediaUUIDs." }), + "draftId": ("STRING", { + "default": "", + "multiline": False, + "tooltip": "Draft ID from a previous Bytedance video generation. Used when continuing or extending a draft output", + }), + "videoId": ("STRING", { + "default": "", + "multiline": False, + "tooltip": "Video ID from a previous generation. Used when extending or editing an existing OpenAI Sora video", + }), } } @@ -65,6 +75,8 @@ class videoInferenceInputs: references = kwargs.get("References", None) referenceVideos = kwargs.get("Reference Videos", None) referenceVoices = kwargs.get("Reference Voices", None) + draftId = kwargs.get("draftId", "") + videoId = kwargs.get("videoId", "") inputs = {} @@ -112,4 +124,10 @@ class videoInferenceInputs: if referenceVoices is not None and len(referenceVoices) > 0: inputs["referenceVoices"] = referenceVoices + if draftId is not None and draftId.strip() != "": + inputs["draftId"] = draftId.strip() + + if videoId is not None and videoId.strip() != "": + inputs["videoId"] = videoId.strip() + return (inputs,) diff --git a/modules/videoOutputs.py b/modules/videoOutputs.py new file mode 100644 index 0000000..ee86f45 --- /dev/null +++ b/modules/videoOutputs.py @@ -0,0 +1,75 @@ +from .utils import runwareUtils as rwUtils + + +class RunwareVideoInferenceOutputs: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "Output": ( + "RUNWARETASK", + { + "tooltip": "Connect the OUTPUT from Runware Video Inference.", + }, + ), + }, + "optional": { + "draftId": ("STRING", { + "placeholder": "Draft ID will appear here after generation.", + "tooltip": "This field will be automatically populated with the draft ID from the video inference output.", + }), + "videoId": ("STRING", { + "placeholder": "Video ID will appear here after generation.", + "tooltip": "This field will be automatically populated with the video ID from the video inference output.", + }), + }, + "hidden": {"node_id": "UNIQUE_ID"}, + } + + DESCRIPTION = "Extracts Runware video inference outputs such as draftId and videoId." + FUNCTION = "get_outputs" + RETURN_TYPES = ("STRING", "STRING") + RETURN_NAMES = ("Draft ID", "Video ID") + CATEGORY = "Runware" + OUTPUT_NODE = True # Ensure node executes even if outputs aren't used + + def get_outputs(self, Output, draftId=None, videoId=None, **kwargs): + draft_id = "" + video_id = "" + + try: + data_list = None + + # Handle different possible response shapes defensively + if isinstance(Output, dict): + if "data" in Output: + data_list = Output.get("data", []) + elif "response" in Output and isinstance(Output["response"], dict): + data_list = Output["response"].get("data", []) + + if data_list and len(data_list) > 0: + first = data_list[0] + outputs = first.get("outputs") or {} + if isinstance(outputs, dict): + # draftId is used by some providers + draft_id = outputs.get("draftId", "") or outputs.get("draftID", "") + # videoId / videoID used by other providers + video_id = outputs.get("videoId", "") or outputs.get("videoID", "") + + # Send to frontend so values appear in textboxes (like Media Upload) + rwUtils.sendVideoOutputs(draft_id, video_id, kwargs.get("node_id")) + + except Exception as e: + print(f"[Runware Video Outputs] Failed to parse outputs: {e}") + + return (draft_id, video_id) + + +NODE_CLASS_MAPPINGS = { + "RunwareVideoInferenceOutputs": RunwareVideoInferenceOutputs, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "RunwareVideoInferenceOutputs": "Runware Video Inference Outputs", +} + diff --git a/modules/videoUpscaler.py b/modules/videoUpscaler.py index ea9b522..735d714 100644 --- a/modules/videoUpscaler.py +++ b/modules/videoUpscaler.py @@ -121,7 +121,8 @@ class videoUpscaler: if status == "success": if "mediaURL" in video_data or "videoURL" in video_data or "videoBase64Data" in video_data: videos = rwUtils.convertVideoB64List(pollResult, 1920, 1080) - return videos + # SaveVideo expects a single video object, not a tuple + return (videos[0],) if len(videos) > 0 else (None,) # If status is "processing", continue polling diff --git a/workflows/Runware_Video_Seedance_1_5_Pro_draftId.json b/workflows/Runware_Video_Seedance_1_5_Pro_draftId.json new file mode 100644 index 0000000..4d1ef3c --- /dev/null +++ b/workflows/Runware_Video_Seedance_1_5_Pro_draftId.json @@ -0,0 +1 @@ +{"id":"6c4c28f8-b635-4821-80f9-9dfe0b5782a3","revision":0,"last_node_id":15,"last_link_id":14,"nodes":[{"id":6,"type":"Runware Bytedance Provider Settings","pos":[629.6443481445312,1101.2879638671875],"size":[336.4712829589844,274],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"useCameraFixed","name":"useCameraFixed","shape":7,"type":"BOOLEAN","widget":{"name":"useCameraFixed"},"link":null},{"localized_name":"cameraFixed","name":"cameraFixed","shape":7,"type":"BOOLEAN","widget":{"name":"cameraFixed"},"link":null},{"localized_name":"useMaxSequentialImages","name":"useMaxSequentialImages","shape":7,"type":"BOOLEAN","widget":{"name":"useMaxSequentialImages"},"link":null},{"localized_name":"maxSequentialImages","name":"maxSequentialImages","shape":7,"type":"INT","widget":{"name":"maxSequentialImages"},"link":null},{"localized_name":"useFastMode","name":"useFastMode","shape":7,"type":"BOOLEAN","widget":{"name":"useFastMode"},"link":null},{"localized_name":"fastMode","name":"fastMode","shape":7,"type":"BOOLEAN","widget":{"name":"fastMode"},"link":null},{"localized_name":"useAudio","name":"useAudio","shape":7,"type":"BOOLEAN","widget":{"name":"useAudio"},"link":null},{"localized_name":"audio","name":"audio","shape":7,"type":"BOOLEAN","widget":{"name":"audio"},"link":null},{"localized_name":"useDraft","name":"useDraft","shape":7,"type":"BOOLEAN","widget":{"name":"useDraft"},"link":null},{"localized_name":"draft","name":"draft","shape":7,"type":"BOOLEAN","widget":{"name":"draft"},"link":null}],"outputs":[{"localized_name":"providerSettings","name":"providerSettings","type":"RUNWAREPROVIDERSETTINGS","links":[5]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"8b8e95b0681cf99f2e9857fe92a83cd38cea8c11","Node name for S&R":"Runware Bytedance Provider Settings"},"widgets_values":[false,false,false,1,false,false,true,true,true,true],"bgcolor":"#5345bf"},{"id":5,"type":"Runware Video Model Search","pos":[-144.4015350341797,658.8407592773438],"size":[287.380859375,290],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"Model Search","name":"Model Search","type":"STRING","widget":{"name":"Model Search"},"link":null},{"localized_name":"Model Architecture","name":"Model Architecture","type":"COMBO","widget":{"name":"Model Architecture"},"link":null},{"localized_name":"VideoList","name":"VideoList","type":"COMBO","widget":{"name":"VideoList"},"link":null},{"localized_name":"Use Search Value","name":"Use Search Value","type":"BOOLEAN","widget":{"name":"Use Search Value"},"link":null},{"localized_name":"useCustomDimensions","name":"useCustomDimensions","type":"COMBO","widget":{"name":"useCustomDimensions"},"link":null},{"localized_name":"Width","name":"Width","type":"INT","widget":{"name":"Width"},"link":null},{"localized_name":"Height","name":"Height","type":"INT","widget":{"name":"Height"},"link":null},{"localized_name":"useResolution","name":"useResolution","type":"BOOLEAN","widget":{"name":"useResolution"},"link":null},{"localized_name":"resolution","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null}],"outputs":[{"localized_name":"Runware Video Model","name":"Runware Video Model","type":"RUNWAREVIDEOMODEL","links":[4]},{"localized_name":"Width","name":"Width","type":"INT","links":null},{"localized_name":"Height","name":"Height","type":"INT","links":null}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"aae3a8f4a4e3019c2b2debece39adf32b33cd078","Node name for S&R":"Runware Video Model Search"},"widgets_values":["","Bytedance","bytedance:seedance@1.5-pro (Seedance 1.5 Pro)",false,"Model Default",864,480,false,"1080p"],"bgcolor":"#5345bf"},{"id":2,"type":"SaveVideo","pos":[650.3009643554688,676.3864135742188],"size":[270,368],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"video","name":"video","type":"VIDEO","link":3},{"localized_name":"filename_prefix","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"format","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"codec","name":"codec","type":"COMBO","widget":{"name":"codec"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.46","Node name for S&R":"SaveVideo"},"widgets_values":["video/ComfyUI","auto","auto"]},{"id":1,"type":"Runware Video Inference","pos":[192.32894897460938,676.3584594726562],"size":[400,760],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"Model","name":"Model","type":"RUNWAREVIDEOMODEL","link":4},{"localized_name":"frameImages","name":"frameImages","shape":7,"type":"RUNWAREFRAMEIMAGES","link":null},{"localized_name":"referenceImages","name":"referenceImages","shape":7,"type":"RUNWAREREFERENCEIMAGES","link":null},{"localized_name":"providerSettings","name":"providerSettings","shape":7,"type":"RUNWAREPROVIDERSETTINGS","link":5},{"localized_name":"inputAudios","name":"inputAudios","shape":7,"type":"RUNWAREINPUTAUDIOS","link":null},{"localized_name":"referenceVideos","name":"referenceVideos","shape":7,"type":"RUNWAREREFERENCEVIDEOS","link":null},{"localized_name":"inputs","name":"inputs","shape":7,"type":"RUNWAREVIDEOINFERENCEINPUTS","link":null},{"localized_name":"safetyInputs","name":"safetyInputs","shape":7,"type":"RUNWARESAFETYINPUTS","link":null},{"localized_name":"videoAdvancedFeatureInputs","name":"videoAdvancedFeatureInputs","shape":7,"type":"RUNWAREVIDEOADVANCEDFEATUREINPUTS","link":null},{"localized_name":"Accelerator","name":"Accelerator","shape":7,"type":"RUNWAREACCELERATOR","link":null},{"localized_name":"Multi Inference Mode","name":"Multi Inference Mode","type":"BOOLEAN","widget":{"name":"Multi Inference Mode"},"link":null},{"localized_name":"Prompt Weighting","name":"Prompt Weighting","type":"COMBO","widget":{"name":"Prompt Weighting"},"link":null},{"localized_name":"useDuration","name":"useDuration","type":"BOOLEAN","widget":{"name":"useDuration"},"link":null},{"localized_name":"duration","name":"duration","type":"INT","widget":{"name":"duration"},"link":null},{"localized_name":"useFps","name":"useFps","type":"BOOLEAN","widget":{"name":"useFps"},"link":null},{"localized_name":"fps","name":"fps","type":"INT","widget":{"name":"fps"},"link":null},{"localized_name":"outputFormat","name":"outputFormat","type":"COMBO","widget":{"name":"outputFormat"},"link":null},{"localized_name":"useSeed","name":"useSeed","type":"BOOLEAN","widget":{"name":"useSeed"},"link":null},{"localized_name":"seed","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"useSteps","name":"useSteps","type":"BOOLEAN","widget":{"name":"useSteps"},"link":null},{"localized_name":"steps","name":"steps","type":"INT","widget":{"name":"steps"},"link":null},{"localized_name":"useBatchSize","name":"useBatchSize","type":"BOOLEAN","widget":{"name":"useBatchSize"},"link":null},{"localized_name":"batchSize","name":"batchSize","type":"INT","widget":{"name":"batchSize"},"link":null},{"localized_name":"acceleration","name":"acceleration","type":"COMBO","widget":{"name":"acceleration"},"link":null},{"localized_name":"positivePrompt","name":"positivePrompt","shape":7,"type":"STRING","widget":{"name":"positivePrompt"},"link":null},{"localized_name":"negativePrompt","name":"negativePrompt","shape":7,"type":"STRING","widget":{"name":"negativePrompt"},"link":null},{"localized_name":"speechVoice","name":"speechVoice","shape":7,"type":"STRING","widget":{"name":"speechVoice"},"link":null},{"localized_name":"speechText","name":"speechText","shape":7,"type":"STRING","widget":{"name":"speechText"},"link":null}],"outputs":[{"localized_name":"VIDEO","name":"VIDEO","type":"VIDEO","links":[3]},{"localized_name":"RW-Task","name":"RW-Task","type":"RUNWARETASK","links":[]},{"localized_name":"OUTPUT","name":"OUTPUT","type":"RUNWARETASK","links":[14]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"aae3a8f4a4e3019c2b2debece39adf32b33cd078","Node name for S&R":"Runware Video Inference"},"widgets_values":[false,"Disabled",true,5,false,24,"mp4",true,1421673473,"randomize",false,20,false,1,"none","A confident man in his 30s stands at a podium, delivering a passionate speech to a large audience in a modern auditorium.","","",""],"bgcolor":"#5345bf"},{"id":15,"type":"Runware Video Inference Outputs","pos":[967.6734619140625,707.1176147460938],"size":[310.5494079589844,102],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"Output","name":"Output","type":"RUNWARETASK","link":14},{"localized_name":"draftId","name":"draftId","shape":7,"type":"STRING","widget":{"name":"draftId"},"link":null},{"localized_name":"videoId","name":"videoId","shape":7,"type":"STRING","widget":{"name":"videoId"},"link":null}],"outputs":[{"localized_name":"Draft ID","name":"Draft ID","type":"STRING","links":null},{"localized_name":"Video ID","name":"Video ID","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"534c6ece24b9843c104740428137dc12fd791d04","Node name for S&R":"Runware Video Inference Outputs"},"widgets_values":["",""],"bgcolor":"#5345bf"}],"links":[[3,1,0,2,0,"VIDEO"],[4,5,0,1,0,"RUNWAREVIDEOMODEL"],[5,6,0,1,3,"RUNWAREPROVIDERSETTINGS"],[14,1,2,15,0,"RUNWARETASK"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.682112756645477,"offset":[547.1011561383572,-419.0151571108246]}},"version":0.4} \ No newline at end of file