Initial commit: ComfyUI Text2Speech custom node with local TTS server
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
TTS
|
||||
flask
|
||||
+12
@@ -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
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user