Initial commit: ComfyUI Text2Speech custom node with local TTS server

This commit is contained in:
GeekatplayStudio
2025-11-16 08:26:53 -07:00
commit 11d2e188c5
6 changed files with 174 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
# ComfyUI-Text2Speech
A ComfyUI custom node for text-to-speech integration with a local TTS server.
## Features
- Custom ComfyUI node `HttpTTSToAudio` for sending text to a local TTS server.
- Local TTS server using Coqui TTS (XTTS v2 model).
- Easy setup with batch files for Windows.
## Installation
### TTS Server Setup
1. Run `install.bat` to create a virtual environment and install dependencies.
2. Run `run_tts.bat` to start the TTS server on `http://127.0.0.1:5002`.
### ComfyUI Node
1. Copy the `__init__.py` file to your ComfyUI `custom_nodes` folder (e.g., `ComfyUI/custom_nodes/ComfyUI_Text2Speech/__init__.py`).
2. Install `requests` in your ComfyUI environment: `pip install requests`.
3. Restart ComfyUI.
## Usage
- Use the `HttpTTSToAudio` node in ComfyUI under `Audio/TTS`.
- Input text, language, and server URL.
- Output is the path to the generated audio file.
## Workflow
Connect the audio path to audio/video processing nodes in ComfyUI for creating TTS-enhanced content.
+62
View File
@@ -0,0 +1,62 @@
import os
import json
import requests
import folder_paths
class HttpTTSToAudio:
"""
Sends text to a local TTS server and returns an audio file path.
Input: text (string), language (string)
Output: audio filepath (string)
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {
"multiline": True,
"default": "Hello from ComfyUI."
}),
"language": ("STRING", {
"default": "en"
}),
"server_url": ("STRING", {
"default": "http://127.0.0.1:5002/tts"
})
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("audio_path",)
FUNCTION = "do_tts"
CATEGORY = "Audio/TTS"
def do_tts(self, text, language, server_url):
payload = {
"text": text,
"language": language
}
try:
resp = requests.post(server_url, json=payload, timeout=120)
resp.raise_for_status()
data = resp.json()
path = data.get("path")
if not path or not os.path.isfile(path):
raise RuntimeError(f"No file returned from TTS server: {data}")
# Copy to ComfyUI temp dir
with open(path, "rb") as f:
audio_bytes = f.read()
temp_dir = folder_paths.get_temp_directory()
out_name = os.path.basename(path)
out_path = os.path.join(temp_dir, out_name)
with open(out_path, "wb") as f:
f.write(audio_bytes)
return (out_path,)
except Exception as e:
print("TTS HTTP error:", e)
return ("",)
NODE_CLASS_MAPPINGS = {
"HttpTTSToAudio": HttpTTSToAudio,
}
+16
View File
@@ -0,0 +1,16 @@
@echo off
echo Setting up TTS environment...
if not exist venv (
python -m venv venv
) else (
echo Virtual environment already exists.
)
call venv\Scripts\activate
pip install --upgrade pip
pip install -r requirements.txt
echo TTS setup complete. Run run_tts.bat to start the server.
pause
+2
View File
@@ -0,0 +1,2 @@
TTS
flask
+12
View File
@@ -0,0 +1,12 @@
@echo off
echo Starting TTS server...
if not exist venv (
echo Virtual environment not found. Run install.bat first.
pause
exit /b 1
)
call venv\Scripts\activate
python tts_server.py
+50
View File
@@ -0,0 +1,50 @@
from flask import Flask, request, send_file, jsonify
from TTS.api import TTS
import os
import uuid
# Choose a model (example: XTTS v2 multilingual; you can pick any supported model)
MODEL_NAME = "tts_models/multilingual/multi-dataset/xtts_v2"
app = Flask(__name__)
tts = TTS(MODEL_NAME)
OUTPUT_DIR = "outputs"
os.makedirs(OUTPUT_DIR, exist_ok=True)
@app.route("/tts", methods=["POST"])
def tts_route():
data = request.get_json()
text = data.get("text", "").strip()
speaker = data.get("speaker") # optional
language = data.get("language", "en") # optional
if not text:
return jsonify({"error": "No text"}), 400
out_name = f"{uuid.uuid4().hex}.wav"
out_path = os.path.join(OUTPUT_DIR, out_name)
# Generate audio
# For XTTS you can pass language, speaker_wav, etc.; adjust to your chosen model
tts.tts_to_file(
text=text,
file_path=out_path,
language=language
)
return jsonify({
"ok": True,
"file": out_name,
"path": out_path
})
@app.route("/audio/<fname>", methods=["GET"])
def get_audio(fname):
path = os.path.join(OUTPUT_DIR, fname)
if not os.path.isfile(path):
return jsonify({"error": "Not found"}), 404
return send_file(path, mimetype="audio/wav")
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5002)