Merge pull request #178 from Runware/feature-Seed-audio

Added support for Seed Audio 1
This commit is contained in:
Sirshendu Ganguly
2026-06-30 16:35:54 +05:30
committed by GitHub
7 changed files with 117 additions and 17 deletions
+57
View File
@@ -3601,6 +3601,9 @@ function audioModelSearchFilterHandler(audioModelSearchNode) {
"alibaba:qwen@3-tts-1.7b-customvoice (Qwen3 TTS 1.7B Custom Voice)",
"alibaba:qwen@3-tts-1.7b-base (Qwen3 TTS 1.7B Base)",
],
"Bytedance": [
"bytedance:seed-audio@1.0 (Seed Audio 1.0)",
],
"Dia": [
"runware:dia@v1.0 (Dia 1.6B)",
"runware:dia2@2b (Dia2 2B)",
@@ -4975,6 +4978,7 @@ function audioInferenceInputsToggleHandler(audioInputsNode) {
const videoWidget = audioInputsNode.widgets.find(w => w && w.name === "Video");
const useVideosWidget = audioInputsNode.widgets.find(w => w && w.name === "useVideos");
const useAudiosWidget = audioInputsNode.widgets.find(w => w && w.name === "useAudios");
const useReferenceAudiosWidget = audioInputsNode.widgets.find(w => w && w.name === "useReferenceAudios");
// Helper function to toggle widget enabled state
function toggleWidgetState(useWidget, paramWidget, paramName) {
@@ -5136,6 +5140,59 @@ function audioInferenceInputsToggleHandler(audioInputsNode) {
// Initial call to set initial state
setTimeout(toggleVideosEnabled, 100);
}
// Set up toggle handlers for reference audios (Reference Audio 1 … N; N from widgets, fallback to 4)
if (useReferenceAudiosWidget) {
function getAudioInferenceReferenceAudioSlotCount() {
let max = 0;
for (const w of audioInputsNode.widgets) {
if (!w?.name) continue;
const m = /^Reference Audio (\d+)$/.exec(w.name);
if (m) max = Math.max(max, parseInt(m[1], 10));
}
return max > 0 ? max : 4;
}
function toggleReferenceAudiosEnabled() {
const enabled = useReferenceAudiosWidget.value === true;
const slotCount = getAudioInferenceReferenceAudioSlotCount();
for (let i = 1; i <= slotCount; i++) {
const refAudioWidget = audioInputsNode.widgets.find(w => w && w.name === `Reference Audio ${i}`);
if (refAudioWidget) {
if (refAudioWidget.inputEl) {
refAudioWidget.inputEl.disabled = !enabled;
refAudioWidget.inputEl.style.opacity = enabled ? "1" : "0.5";
refAudioWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed";
refAudioWidget.inputEl.readOnly = !enabled;
}
refAudioWidget.disabled = !enabled;
if (!refAudioWidget.inputEl) {
const nodeElement = audioInputsNode.htmlElements?.widgetsContainer || audioInputsNode.htmlElements;
if (nodeElement) {
const input = nodeElement.querySelector(`input[name="Reference Audio ${i}"], textarea[name="Reference Audio ${i}"], select[name="Reference Audio ${i}"]`);
if (input) {
input.disabled = !enabled;
input.style.opacity = enabled ? "1" : "0.5";
input.style.cursor = enabled ? "text" : "not-allowed";
input.readOnly = !enabled;
}
}
}
}
}
audioInputsNode.setDirtyCanvas(true);
}
appendWidgetCB(useReferenceAudiosWidget, () => {
setTimeout(toggleReferenceAudiosEnabled, 50);
});
setTimeout(toggleReferenceAudiosEnabled, 100);
}
}
function audioInferenceSpeechVoicesToggleHandler(voicesNode) {
+39 -1
View File
@@ -7,6 +7,8 @@ class audioInferenceInputs:
MAX_VIDEOS = 4
MAX_AUDIOS = 4
MAX_REFERENCE_IMAGES = 4
MAX_REFERENCE_AUDIOS = 4
@classmethod
def INPUT_TYPES(cls):
@@ -53,6 +55,23 @@ class audioInferenceInputs:
"default": "",
})
for i in range(1, cls.MAX_REFERENCE_IMAGES + 1):
ordinal = rwUtils.getOrdinal(i)
optionalInputs[f"Reference Image {i}"] = ("IMAGE", {
"tooltip": f"Optional {ordinal} reference image for audio inference (inputs.referenceImages).",
})
optionalInputs["useReferenceAudios"] = ("BOOLEAN", {
"tooltip": "Enable to include reference audios in API request (inputs.referenceAudios array).",
"default": False,
})
for i in range(1, cls.MAX_REFERENCE_AUDIOS + 1):
ordinal = rwUtils.getOrdinal(i)
optionalInputs[f"Reference Audio {i}"] = ("STRING", {
"tooltip": f"Audio URL or mediaUUID for the {ordinal} reference audio (inputs.referenceAudios).",
"default": "",
})
optionalInputs["Reference Voice"] = ("RUNWAREAUDIOINFERENCEREFERENCEVOICES", {
"tooltip": "Connect Runware Audio Inference Inputs Reference Audio for zero-shot voice cloning (inputs.referenceVoices).",
})
@@ -65,7 +84,8 @@ class audioInferenceInputs:
DESCRIPTION = (
"Configure custom inputs for Runware Audio Inference, including optional single or multiple audio URL/mediaUUID "
"(inputs.audio or inputs.audios), reference voice for cloning (inputs.referenceVoices), "
"and single or multiple video inputs for audio extraction or generation."
"single or multiple video inputs for audio extraction or generation, up to 4 reference images "
"(inputs.referenceImages), and up to 4 reference audios (inputs.referenceAudios)."
)
FUNCTION = "createInputs"
RETURN_TYPES = ("RUNWAREAUDIOINFERENCEINPUTS",)
@@ -80,6 +100,7 @@ class audioInferenceInputs:
useVideo = kwargs.get("useVideo", False)
video = kwargs.get("Video", None)
useVideos = kwargs.get("useVideos", False)
useReferenceAudios = kwargs.get("useReferenceAudios", False)
referenceVoices = kwargs.get("Reference Voice", None)
inputs = {}
@@ -116,6 +137,23 @@ class audioInferenceInputs:
if len(videoList) > 0:
inputs["videos"] = videoList
referenceImages = []
for i in range(1, self.MAX_REFERENCE_IMAGES + 1):
image = kwargs.get(f"Reference Image {i}", None)
if image is not None:
referenceImages.append(rwUtils.convertTensor2IMG(image))
if len(referenceImages) > 0:
inputs["referenceImages"] = referenceImages
if useReferenceAudios:
referenceAudios = []
for i in range(1, self.MAX_REFERENCE_AUDIOS + 1):
audioUrl = kwargs.get(f"Reference Audio {i}", None)
if audioUrl and isinstance(audioUrl, str) and audioUrl.strip() != "":
referenceAudios.append(audioUrl.strip())
if len(referenceAudios) > 0:
inputs["referenceAudios"] = referenceAudios
if referenceVoices is not None and isinstance(referenceVoices, list) and len(referenceVoices) > 0:
inputs["referenceVoices"] = referenceVoices
+14 -14
View File
@@ -23,8 +23,8 @@ class RunwareAudioInferenceSpeech:
"required": {
"text": ("STRING", {
"multiline": True,
"default": "Hello, this is a test of the speech synthesis model.",
"tooltip": "Text to synthesize as speech (speech.text)",
"default": "",
"tooltip": "Text to synthesize as speech (speech.text). Optional when positivePrompt on Runware Audio Inference carries the script (e.g. Seed Audio).",
}),
},
"optional": {
@@ -38,19 +38,19 @@ class RunwareAudioInferenceSpeech:
}),
"useSpeed": ("BOOLEAN", {"default": False, "tooltip": "Include speed (speech.speed)"}),
"speed": ("FLOAT", {
"default": 1.0,
"min": 0.5,
"default": 0.0,
"min": 0.0,
"max": 2.0,
"step": 0.01,
"tooltip": "Speech rate multiplier (speech.speed)",
"tooltip": "Speech rate adjustment (speech.speed). 0 = no change for Seed Audio.",
}),
"useVolume": ("BOOLEAN", {"default": False, "tooltip": "Include volume (speech.volume)"}),
"volume": ("FLOAT", {
"default": 1.0,
"min": 1.0,
"default": 0.0,
"min": 0.0,
"max": 10.0,
"step": 0.1,
"tooltip": "Volume level 1-10 (speech.volume)",
"tooltip": "Volume adjustment (speech.volume). 0 = no change.",
}),
"usePitch": ("BOOLEAN", {"default": False, "tooltip": "Include pitch (speech.pitch)"}),
"pitch": ("FLOAT", {
@@ -98,9 +98,9 @@ class RunwareAudioInferenceSpeech:
voice = (kwargs.get("voice") or "").strip()
use_voice = kwargs.get("useVoice", False)
use_speed = kwargs.get("useSpeed", False)
speed = float(kwargs.get("speed", 1.0))
speed = float(kwargs.get("speed", 0.0))
use_volume = kwargs.get("useVolume", False)
volume = float(kwargs.get("volume", 1.0))
volume = float(kwargs.get("volume", 0.0))
use_pitch = kwargs.get("usePitch", False)
pitch = float(kwargs.get("pitch", 0.0))
use_emotion = kwargs.get("useEmotion", False)
@@ -111,10 +111,12 @@ class RunwareAudioInferenceSpeech:
language = (kwargs.get("language") or "Auto").strip()
voices = kwargs.get("voices")
speech: Dict[str, Any] = {"text": text}
speech: Dict[str, Any] = {}
if text:
speech["text"] = text
if isinstance(voices, list) and len(voices) > 0:
speech["voices"] = voices
elif use_voice:
elif use_voice and voice:
speech["voice"] = voice
if use_speed:
speech["speed"] = speed
@@ -131,8 +133,6 @@ class RunwareAudioInferenceSpeech:
if use_language:
speech["language"] = language
if not text:
return ({},)
return (speech,)
+4
View File
@@ -27,6 +27,9 @@ class RunwareAudioModelSearch:
"alibaba:qwen@3-tts-1.7b-customvoice (Qwen3 TTS 1.7B Custom Voice)",
"alibaba:qwen@3-tts-1.7b-base (Qwen3 TTS 1.7B Base)",
],
"Bytedance": [
"bytedance:seed-audio@1.0 (Seed Audio 1.0)",
],
"Dia": [
"runware:dia@v1.0 (Dia 1.6B)",
"runware:dia2@2b (Dia2 2B)",
@@ -59,6 +62,7 @@ class RunwareAudioModelSearch:
"Mirelo",
"Ace",
"Alibaba",
"Bytedance",
"Dia",
"xAI",
"MiniMax",
+1 -1
View File
@@ -1 +1 @@
__version__ = "1.9.1"
__version__ = "1.9.2"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long