Files
Runware-ComfyUI-Runware/modules/audioInferenceSpeechVoices.py
T

88 lines
2.8 KiB
Python

"""
Runware Audio Inference Speech Voices node:
Builds speech.voices[] for multi-speaker audio inference speech payloads.
"""
import re
from typing import Dict, List
class RunwareAudioInferenceSpeechVoices:
"""Build speech.voices[] list for Runware Audio Inference."""
MAX_VOICES = 4
_SPEAKER_ALIAS_PATTERN = re.compile(r"^[A-Za-z0-9]+$")
@classmethod
def INPUT_TYPES(cls):
optional_inputs = {}
for i in range(1, cls.MAX_VOICES + 1):
optional_inputs[f"useVoice{i}"] = ("BOOLEAN", {
"default": False,
"tooltip": f"Enable to include speaker/voice pair #{i} in speech.voices.",
})
optional_inputs[f"speaker{i}"] = ("STRING", {
"default": f"Speaker{i}",
"tooltip": "Unique alphanumeric speaker alias (speech.voices[].speaker).",
})
optional_inputs[f"voice{i}"] = ("STRING", {
"default": "",
"tooltip": "Voice name for this speaker (speech.voices[].voice).",
})
return {
"required": {},
"optional": optional_inputs,
}
RETURN_TYPES = ("RUNWAREAUDIOINFERENCESPEECHVOICES",)
RETURN_NAMES = ("voices",)
FUNCTION = "createVoices"
CATEGORY = "Runware/Audio"
DESCRIPTION = (
"Build speech.voices[] for multi-speaker synthesis. "
"Each item contains speaker (unique alphanumeric alias) and voice name."
)
def createVoices(self, **kwargs) -> tuple[list[dict[str, str]],]:
voices: list[dict[str, str]] = []
seen_speakers = set()
for i in range(1, self.MAX_VOICES + 1):
use_voice = bool(kwargs.get(f"useVoice{i}", False))
if not use_voice:
continue
speaker = (kwargs.get(f"speaker{i}") or "").strip()
voice = (kwargs.get(f"voice{i}") or "").strip()
if not speaker or not voice:
raise Exception(
f"Voice #{i} is enabled, but speaker{i} and voice{i} must both be provided."
)
if not self._SPEAKER_ALIAS_PATTERN.match(speaker):
raise Exception(
f"speaker{i} must be alphanumeric only (got: '{speaker}')."
)
if speaker in seen_speakers:
raise Exception(
f"Duplicate speaker alias '{speaker}'. Each speaker must be unique."
)
seen_speakers.add(speaker)
voices.append({
"speaker": speaker,
"voice": voice,
})
return (voices,)
NODE_CLASS_MAPPINGS = {
"RunwareAudioInferenceSpeechVoices": RunwareAudioInferenceSpeechVoices,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RunwareAudioInferenceSpeechVoices": "Runware Audio Inference Speech Voices",
}