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

125 lines
5.0 KiB
Python

"""
Runware Audio Inference Speech node: builds the speech payload for Runware Audio Inference.
Connect its output to the "speech" input of Runware Audio Inference for speech synthesis (e.g. Minimax).
"""
from typing import Dict, Any
class RunwareAudioInferenceSpeech:
"""Builds speech payload (text, voice, speed, volume, pitch?, emotion?, tone?) for Runware Audio Inference."""
EMOTIONS = [
"happy", "sad", "angry", "fearful", "disgusted", "surprised",
"calm", "fluent", "whisper",
]
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {
"multiline": True,
"default": "Hello, this is a test of the speech synthesis model.",
"tooltip": "Text to synthesize as speech (speech.text)",
}),
},
"optional": {
"useVoice": ("BOOLEAN", {
"default": False,
"tooltip": "Enable to include voice in speech synthesis (speech.voice).",
}),
"voice": ("STRING", {
"default": "",
"tooltip": "Voice identifier.",
}),
"useSpeed": ("BOOLEAN", {"default": True, "tooltip": "Include speed (speech.speed)"}),
"speed": ("FLOAT", {
"default": 1.0,
"min": 0.5,
"max": 2.0,
"step": 0.01,
"tooltip": "Speech rate multiplier (speech.speed)",
}),
"useVolume": ("BOOLEAN", {"default": True, "tooltip": "Include volume (speech.volume)"}),
"volume": ("FLOAT", {
"default": 1.0,
"min": 1.0,
"max": 10.0,
"step": 0.1,
"tooltip": "Volume level 1-10 (speech.volume)",
}),
"usePitch": ("BOOLEAN", {"default": False, "tooltip": "Include pitch (speech.pitch)"}),
"pitch": ("FLOAT", {
"default": 0.0,
"min": -12.0,
"max": 12.0,
"step": 0.1,
"tooltip": "Pitch multiplier -12 to 12 (speech.pitch)",
}),
"useEmotion": ("BOOLEAN", {"default": False, "tooltip": "Include emotion (not available for speech.turbo)"}),
"emotion": (cls.EMOTIONS, {"default": "calm", "tooltip": "Emotion for speech (speech.emotion)"}),
"useTone": ("BOOLEAN", {"default": False, "tooltip": "Include pronunciation dictionary (speech.tone)"}),
"tone": ("STRING", {
"multiline": True,
"default": "",
"placeholder": "omg/oh my god\nother/other expansion",
"tooltip": "Pronunciation dictionary, one mapping per line (e.g. omg/oh my god)",
}),
}
}
RETURN_TYPES = ("RUNWARESPEECH",)
RETURN_NAMES = ("speech",)
FUNCTION = "createSpeech"
CATEGORY = "Runware/Audio"
DESCRIPTION = "Build speech parameters for Runware Audio Inference. Connect output to the 'speech' input of Runware Audio Inference."
def createSpeech(self, **kwargs) -> tuple:
"""Build the speech object for the API (connect to Runware Audio Inference 'speech' input)."""
text = (kwargs.get("text") or "").strip()
voice = (kwargs.get("voice") or "").strip()
use_voice = kwargs.get("useVoice", False)
use_speed = kwargs.get("useSpeed", True)
speed = float(kwargs.get("speed", 1.0))
use_volume = kwargs.get("useVolume", True)
volume = float(kwargs.get("volume", 1.0))
use_pitch = kwargs.get("usePitch", False)
pitch = float(kwargs.get("pitch", 0.0))
use_emotion = kwargs.get("useEmotion", False)
emotion = kwargs.get("emotion", "calm")
use_tone = kwargs.get("useTone", False)
tone_str = kwargs.get("tone", "") or ""
speech: Dict[str, Any] = {"text": text}
if use_voice:
speech["voice"] = voice
if use_speed:
speech["speed"] = speed
if use_volume:
speech["volume"] = volume
if use_pitch:
speech["pitch"] = pitch
if use_emotion:
speech["emotion"] = emotion
if use_tone and tone_str.strip():
tone_lines = [s.strip() for s in tone_str.replace(",", "\n").split("\n") if s.strip()]
if tone_lines:
speech["tone"] = tone_lines
if not text:
return ({},)
return (speech,)
NODE_CLASS_MAPPINGS = {
"RunwareAudioInferenceSpeech": RunwareAudioInferenceSpeech,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RunwareAudioInferenceSpeech": "Runware Audio Inference Speech",
}