commit 65c2ea3d504e975d971594e0864772e7bf87b156 Author: hermes Date: Sat Jul 4 01:38:23 2026 +0800 feat(pinokio): clean one-click launcher for multi-tts-server - install: clone app source, create venv, install deps + torch + models - start: daemon uvicorn on 127.0.0.1 with auto-captured URL - reset: remove venv/cache/models but keep source - update: pull both launcher and app, then re-install - sanitized: no local env details, no TODO/DONE - icon.png included diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3438f9c --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +Thumbs.db +app/venv/ +app/cache/ +app/models/ +app/__pycache__/ +app/*.pyc +app/.env +logs/ +pinokio/logs/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe0784a --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# Multi-TTS-Server Pinokio Launcher + +One-click Pinokio launcher for [hermes/multi-tts-server](https://gitea.amakusa.ru/hermes/multi-tts-server). + +## What it installs + +This launcher downloads the TTS server source code, creates a Python virtual environment, installs dependencies, installs the correct PyTorch build for your GPU, and downloads the required voice models. + +## Requirements + +- Windows, macOS, or Linux +- NVIDIA GPU with CUDA 12.8, AMD GPU with DirectML (Windows only), or CPU +- At least 16 GB of system RAM +- ~8 GB of free disk space (venv + models) + +## Included engines + +- **F5-TTS** — Russian model `Misha24-10/F5-TTS_RUSSIAN` (~1.3 GB) +- **XTTS-v2** — Russian model `NeuroDonu/RU-XTTS-DonuModel` (~5.3 GB) +- **CPU fallback** for machines without a compatible GPU + +## One-click usage + +1. Open Pinokio. +2. Install this launcher. +3. Click **Install**. +4. When install completes, click **Start**. +5. The Gradio Web UI and FastAPI docs will open automatically. + +## Features + +- OpenAI-compatible speech endpoint: `POST /v1/audio/speech` +- MultiTTS Android-compatible endpoint: `GET /tts?text=...&voice=...&engine=f5-tts` +- Engine load/unload controls: `POST /engines/{name}/load` and `/engines/{name}/unload` +- MultiTTS Android export: `GET /export/multitts` + +## Reset + +Click **Reset** to remove the virtual environment, cached files, and downloaded models. The source code in `app/` is kept so the next install only recreates the venv and re-downloads models. + +## Update + +Click **Update** to pull the latest launcher and app source code, then re-run the install steps. + +## License + +This launcher wraps the multi-tts-server project. Use in accordance with the licenses of F5-TTS, XTTS-v2, and the upstream project. diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/icon.png differ diff --git a/install.js b/install.js new file mode 100644 index 0000000..8f5f440 --- /dev/null +++ b/install.js @@ -0,0 +1,74 @@ +// Multi-TTS-Server installer +// 1. Clone app source code into app/ +// 2. Create venv under app/ and install Python deps +// 3. Install platform-specific torch (CUDA 12.8 / DirectML / CPU) +// 4. Pre-download the minimal TTS model set (~6.7 GB): +// - NeuroDonu/RU-XTTS-DonuModel (5.3 GB) +// - Misha24-10/F5-TTS_RUSSIAN/F5TTS_v1_Base_v2 (1.3 GB) +// - pavolgebciar/vocos-mel-24khz (52 MB) +module.exports = { + requires: { + bundle: "ai", + }, + run: [ + // 1. Clone the app source code + { + method: "shell.run", + params: { + message: [ + "git clone https://gitea.amakusa.ru/hermes/multi-tts-server.git app" + ] + } + }, + + // 2. Create venv under app/ and install Python deps + { + method: "shell.run", + params: { + venv: "venv", + path: "app", + message: [ + "uv venv --python 3.11", + "uv pip install --upgrade pip wheel setuptools==80.9.0", + "uv pip install -r requirements.txt", + ] + } + }, + + // 3. Platform-specific torch install (CUDA 12.8 for NVIDIA, DirectML for AMD, CPU fallback) + { + method: "script.start", + params: { + uri: "torch.js", + params: { venv: "venv", path: "app" } + } + }, + + // 4. Download only the required TTS models (~6.7 GB total): + // - NeuroDonu/RU-XTTS-DonuModel ~5.3 GB + // - Misha24-10/F5-TTS_RUSSIAN ~1.3 GB + // - pavolgebciar/vocos-mel-24khz ~52 MB + { + method: "shell.run", + params: { + venv: "venv", + path: "app", + message: [ + "python -c \"from huggingface_hub import snapshot_download; snapshot_download('NeuroDonu/RU-XTTS-DonuModel', local_dir='models/xtts-v2/NeuroDonu__RU-XTTS-DonuModel')\"", + "python -c \"from huggingface_hub import snapshot_download; repo='Misha24-10/F5-TTS_RUSSIAN'; base='models/f5-tts/Misha24-10__F5-TTS_RUSSIAN'; snapshot_download(repo, local_dir=base, ignore_patterns=['**/F5TTS_v1_Base_v4_winter/**','**/F5TTS_v1_Base_accent_tune/**','**/F5TTS_v1_Base/**/model_last.pt','**/F5TTS_v1_Base/**/model_last.safetensors','**/F5TTS_v1_Base_v2/**/model_last.pt'])\"", + "python -c \"from huggingface_hub import snapshot_download; snapshot_download('pavolgebciar/vocos-mel-24khz', local_dir='models/vocos/pavolgebciar__vocos-mel-24khz')\"", + ] + } + }, + + // 5. Install Done modal + { + id: "end", + method: "input", + params: { + title: "Install Complete", + description: "Multi-TTS-Server is ready. Click Start to launch the API + Gradio Web UI." + } + } + ] +} diff --git a/pinokio.js b/pinokio.js new file mode 100644 index 0000000..38332b4 --- /dev/null +++ b/pinokio.js @@ -0,0 +1,94 @@ +// Multi-TTS-Server Pinokio launcher +// One-click install/start for hermes/multi-tts-server +module.exports = { + version: "1.0.0", + title: "Multi-TTS-Server", + description: "XTTS + F5-TTS server with OpenAI-compatible API, Gradio Web UI, and MultiTTS Android export.", + icon: "icon.png", + menu: async (kernel, info) => { + // Marker: app/venv exists after install + let installed = info.exists("app/venv/Scripts/python.exe") || + info.exists("app/venv/bin/python") + + let running = { + install: info.running("install.js"), + start: info.running("start.js"), + update: info.running("update.js"), + reset: info.running("reset.js"), + } + + if (running.install) { + return [{ + default: true, + icon: "fa-solid fa-plug", + text: "Installing", + href: "install.js", + }] + } + + if (running.start) { + let local = info.local("start.js") + if (local && local.url) { + return [{ + default: true, + icon: "fa-solid fa-rocket", + text: "Open Web UI", + href: local.url, + }, { + icon: "fa-solid fa-terminal", + text: "Terminal", + href: "start.js", + }] + } + return [{ + default: true, + icon: "fa-solid fa-terminal", + text: "Starting", + href: "start.js", + }] + } + + if (running.update) { + return [{ + default: true, + icon: "fa-solid fa-terminal", + text: "Updating", + href: "update.js", + }] + } + + if (running.reset) { + return [{ + default: true, + icon: "fa-solid fa-terminal", + text: "Resetting", + href: "reset.js", + }] + } + + if (installed) { + return [{ + default: true, + icon: "fa-solid fa-power-off", + text: "Start", + href: "start.js", + }, { + icon: "fa-solid fa-plug", + text: "Update", + href: "update.js", + }, { + icon: "fa-regular fa-circle-xmark", + text: "
Reset
Revert to pre-install state
", + href: "reset.js", + confirm: "Are you sure you wish to reset the app? This deletes the venv and any downloaded models.", + }] + } + + return [{ + default: true, + icon: "fa-solid fa-plug", + text: "Install", + href: "install.js", + }] + } +} diff --git a/pinokio.json b/pinokio.json new file mode 100644 index 0000000..e92e314 --- /dev/null +++ b/pinokio.json @@ -0,0 +1,8 @@ +{ + "name": "multi-tts-server-launcher", + "version": "1.0.0", + "description": "Pinokio one-click launcher for Multi-TTS-Server (XTTS + F5-TTS + OpenAI-compatible API + MultiTTS Android export)", + "repository": "https://gitea.amakusa.ru/hermes/multi-tts-server-launcher", + "icon": "icon.png", + "license": "MIT" +} diff --git a/reset.js b/reset.js new file mode 100644 index 0000000..43e2ec1 --- /dev/null +++ b/reset.js @@ -0,0 +1,19 @@ +// Reset Multi-TTS-Server to pre-install state. +// Removes the venv, downloaded caches, and downloaded models. +// Keeps the cloned app/ source code so the next install is just venv + models. +module.exports = { + run: [ + { + method: "fs.rm", + params: { path: "app/venv" } + }, + { + method: "fs.rm", + params: { path: "app/cache" } + }, + { + method: "fs.rm", + params: { path: "app/models" } + } + ] +} diff --git a/start.js b/start.js new file mode 100644 index 0000000..5bfcf91 --- /dev/null +++ b/start.js @@ -0,0 +1,48 @@ +// Multi-TTS-Server launcher daemon. +// Runs uvicorn in the background and exposes the URL via local.set so the +// menu can render an "Open Web UI" button. +module.exports = { + requires: { bundle: "ai" }, + daemon: true, + run: [ + { + method: "shell.run", + params: { + venv: "venv", + path: "app", + env: { + // Workaround for Coqui TTS on Windows when no system Local AppData is available + TTS_HOME: "{{cwd}}\\app\\cache\\tts_home", + HF_HOME: "{{cwd}}\\app\\cache\\hf", + XDG_DATA_HOME: "{{cwd}}\\app\\cache\\appdata", + LOCALAPPDATA: "{{cwd}}\\app\\cache\\appdata", + TRANSFORMERS_CACHE: "{{cwd}}\\app\\cache\\hf", + HF_HUB_CACHE: "{{cwd}}\\app\\cache\\hf", + PYTHONUTF8: "1", + }, + message: [ + "python -m uvicorn app.main:app --host 127.0.0.1 --port {{port}}" + ], + on: [ + // Watch stdout for uvicorn's "Uvicorn running on..." line and capture URL. + // The single capture group is fed to local.set.url below via input.event[1]. + { + "event": "/Uvicorn running on (https?:\\/\\/[^\\s]+)/", + "done": true + }, + { + "event": "/error:/i", + "break": false + } + ] + } + }, + { + method: "local.set", + params: { + // input.event[1] is the first capture group from the regex (the URL). + url: "{{input.event && input.event[1] ? input.event[1] : ''}}" + } + } + ] +} diff --git a/torch.js b/torch.js new file mode 100644 index 0000000..8ffe9f7 --- /dev/null +++ b/torch.js @@ -0,0 +1,86 @@ +// Platform-aware PyTorch installer. +// CUDA 12.8 wheels for NVIDIA, DirectML for AMD, CPU fallback. +module.exports = { + run: [ + // Windows + NVIDIA + { + "when": "{{platform === 'win32' && gpu === 'nvidia'}}", + method: "shell.run", + params: { + venv: "{{args.venv}}", + path: "{{args.path}}", + message: [ + "uv pip install torch==2.11.0 torchvision==0.21.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cu128 --force-reinstall" + ] + }, + next: null + }, + // Windows + AMD (DirectML) + { + "when": "{{platform === 'win32' && gpu === 'amd'}}", + method: "shell.run", + params: { + venv: "{{args.venv}}", + path: "{{args.path}}", + message: "uv pip install torch-directml torchaudio torchvision --force-reinstall" + }, + next: null + }, + // Windows CPU + { + "when": "{{platform === 'win32' && (gpu !== 'nvidia' && gpu !== 'amd')}}", + method: "shell.run", + params: { + venv: "{{args.venv}}", + path: "{{args.path}}", + message: "uv pip install torch==2.11.0 torchvision==0.21.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cpu --force-reinstall" + }, + next: null + }, + // macOS (CPU only — Apple Silicon uses MPS automatically) + { + "when": "{{platform === 'darwin'}}", + method: "shell.run", + params: { + venv: "{{args.venv}}", + path: "{{args.path}}", + message: "uv pip install torch==2.11.0 torchvision==0.21.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cpu --force-reinstall" + }, + next: null + }, + // Linux + NVIDIA + { + "when": "{{platform === 'linux' && gpu === 'nvidia'}}", + method: "shell.run", + params: { + venv: "{{args.venv}}", + path: "{{args.path}}", + message: [ + "uv pip install torch==2.11.0 torchvision==0.21.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cu128 --force-reinstall" + ] + }, + next: null + }, + // Linux + AMD (ROCm 6.4) + { + "when": "{{platform === 'linux' && gpu === 'amd'}}", + method: "shell.run", + params: { + venv: "{{args.venv}}", + path: "{{args.path}}", + message: "uv pip install torch==2.11.0 torchvision==0.21.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/rocm6.4 --force-reinstall" + }, + next: null + }, + // Linux CPU + { + "when": "{{platform === 'linux' && (gpu !== 'amd' && gpu !== 'nvidia')}}", + method: "shell.run", + params: { + venv: "{{args.venv}}", + path: "{{args.path}}", + message: "uv pip install torch==2.11.0 torchvision==0.21.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cpu --force-reinstall" + } + } + ] +} diff --git a/update.js b/update.js new file mode 100644 index 0000000..bf91992 --- /dev/null +++ b/update.js @@ -0,0 +1,17 @@ +// Pull latest launcher scripts and app source code, then re-run install. +module.exports = { + run: [ + { + method: "shell.run", + params: { message: "git pull" } + }, + { + method: "shell.run", + params: { path: "app", message: "git pull" } + }, + { + method: "script.start", + params: { uri: "install.js" } + } + ] +}