commit 11d2e188c5aa7efde9cff031f904670a470ceff2 Author: GeekatplayStudio Date: Sun Nov 16 08:26:53 2025 -0700 Initial commit: ComfyUI Text2Speech custom node with local TTS server diff --git a/README.md b/README.md new file mode 100644 index 0000000..5493cff --- /dev/null +++ b/README.md @@ -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. \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..f979853 --- /dev/null +++ b/__init__.py @@ -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, +} \ No newline at end of file diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..c31b690 --- /dev/null +++ b/install.bat @@ -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 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..aa33a59 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +TTS +flask \ No newline at end of file diff --git a/run_tts.bat b/run_tts.bat new file mode 100644 index 0000000..5e92c92 --- /dev/null +++ b/run_tts.bat @@ -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 \ No newline at end of file diff --git a/tts_server.py b/tts_server.py new file mode 100644 index 0000000..63d139b --- /dev/null +++ b/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/", 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) \ No newline at end of file