📌 Part of Blueprint: AI Agent & Local GPU Automation → L3: Local GPU Inference Stack (RTX 3060)

How I Replaced Cloud TTS with a Self-Hosted Neural Voice Stack on an RTX 3060

· 6 min read · Case Studies ttsain8ngpucosyvoiceself-hosting

For nearly two years, my internal business workflows, Telegram bots, and automated learning summaries relied on cloud-hosted text-to-speech APIs. Initially, Microsoft Edge-TTS provided a generous, zero-cost bridge. But running production workloads over unofficial browser-endpoint scraping is inherently fragile: sudden upstream schema changes, IP rate limits, and latency spikes across international transit routes routinely caused intermittent delivery drops. Commercial APIs like Azure Speech or Google Cloud TTS offered stability, but recurring meter billing scales awkwardly when generating long-form narration.

With a dedicated RTX 3060 12GB GPU passed through to a Windows 11 VM on my Unraid server, I decided to bring the entire speech synthesis stack fully on-premises.

Here is how I architected a self-hosted neural TTS pipeline using Alibaba’s open-source CosyVoice 2, hooked it into my Synology DSM n8n automation cluster, managed GPU memory alongside my other local AI models, and achieved instant sub-second audio responses across Chinese, English, and mixed-language speech.


1. The Design Goals

Before touching code, my target operational envelope required four non-negotiable criteria:

  1. Fluid Bilingual Code-Switching: In Malaysian and Southeast Asian business communication, text is almost never purely monolingual. Sentences naturally mix Chinese syntax with English technical terms (e.g., “请检查这个 pull request 并确认 webhook 状态”). The engine must articulate both languages without sudden cadence jumps or unnatural accent shifts.
  2. Zero-Shot Voice Variety: I needed distinct voice profiles—cheerful child voices for storybook projects, authoritative male anchors for news roundups, and clear conversational female tones for support bots—cloned from brief reference clips without days of fine-tuning.
  3. Constrained VRAM Footprint: The RTX 3060 has 12GB of VRAM. The VM regularly runs local LLMs (Qwen GGUF on LM Studio) and ComfyUI image/video pipelines. The TTS engine had to either idle under ~3.5GB of VRAM or provide frictionless cold-start toggles.
  4. Drop-in Webhook Compatibility: My central automation runs on Synology DSM via n8n (n8n.internal:5678). Replacing cloud nodes could not require rewriting dozens of downstream workflow schemas.

2. Model Selection: Why CosyVoice 2 Won

I evaluated the primary open-source contenders against my bilingual requirement:

Model ArchitectureStrengthsDrawbacksVerdict
Edge-TTS / PiperUltra-lightweight, CPU-onlyRobotic cadence, rigid voices, cloud dependencyDeprecated
ChatTTSConversational laughter, pause tagsUnpredictable halluncinations, weak EnglishNot suitable
GPT-SoVITS v2Unrivaled character cloning accuracyPhoneme boundaries stumble on mixed Chinese-EnglishSecondary / On-demand
CosyVoice 2 (0.5B)Superb bilingual flow, 300ms first-packet latency3.2GB VRAM baselinePrimary Production Engine

CosyVoice 2 (the 0.5B parameter variant from Alibaba’s FunAudioLLM team) emerged as the definitive winner. By combining an autoregressive language model with flow-matching diffusion decoders, it treats cross-lingual text-to-speech as a unified sequence. English terms embedded inside Chinese phrases flow with native pronunciation and natural human breath pauses.


3. Infrastructure & Network Topology

My self-managed infrastructure runs on a tiered hardware split:

[ Internet / Clients ]
         │
         ▼
[ Synology DSM Storage Node ]
  ├── Portainer / Traefik Reverse Proxy
  └── n8n Automation Engine
         │  HTTP POST / GET (/webhook/ltts)
         ▼ (Local 1Gbps LAN)
[ Unraid Host ]
  └── Windows 11 VM (GPU Passthrough)
       ├── NVIDIA GeForce RTX 3060 12GB
       └── CosyVoice 2 FastAPI Service (127.0.0.1:50000)

The Windows VM hosts the CUDA 12.x PyTorch runtime. I exposed a lightweight FastAPI wrapper inside CosyVoice’s runtime script (webui.py), allowing my Synology n8n instance to trigger generation over LAN via http://gpu-node.internal:50000/tts.


4. Managing GPU Memory: Resident vs. On-Demand

Leaving every AI model loaded simultaneously will exhaust 12GB of VRAM instantly. I designed a dual-tier lifecycle:

  1. CosyVoice 2 as the Resident Daemon: Consuming only 3.2 GB of VRAM, CosyVoice 2 runs as an auto-starting background service when Windows boots (shell:startup\CosyVoice 2.lnk). This leaves 8.8 GB free for general desktop and lightweight inference.
  2. One-Click State Toggle Batches: For heavy tasks (such as running 1080p video generation in ComfyUI or 14B LLMs), I created an idempotent batch script on the desktop:
@echo off
title CosyVoice 2 Toggle
for /f "tokens=5" %%a in ('netstat -aon ^| findstr :50000') do (
    taskkill /F /PID %%a >nul 2>&1
    echo STOPPED. GPU memory freed.
    exit /b
)
:: If stopped, launch background worker
start /b python webui.py --port 50000 --model_dir pretrained_models/CosyVoice2-0.5B
echo ONLINE - CosyVoice 2 loaded to GPU.

A single double-click halts the process and reclaims all 3.2GB within 500ms; clicking it again restores the service in under 25 seconds.


5. Integrating with Synology N8N

In n8n, I configured a dedicated workflow: Local TTS API (CosyVoice) listening on /webhook/ltts.

To ensure total interoperability with existing scripts, the workflow accepts both:

The n8n pipeline consists of three streamlined nodes:

  1. Webhook Node: Receives incoming requests.
  2. Parse & Clean Text (Code Node): Normalizes character encodings and defaults voice selections.
  3. HTTP Request Node: Forwards the JSON payload to http://gpu-node.internal:50000/tts and streams the binary audio/wav response directly back to the requester.

6. Curating Zero-Shot Reference Voices

CosyVoice 2 synthesizes speech using zero-shot voice cloning: feeding a 3- to 5-second clean audio sample allows the model to clone the acoustic timbre instantly.

I packaged a library of curated reference samples into asset/voices/ and mapped them to intuitive alias parameters:

Voice KeyStyle ProfileSample Source
child / girlCheerful female child voiceClean 4s preschool dialogue clip
boyEnergetic young boy (anime style)5s youth animation dialogue
male / yunxiEngaging, modern tech male anchor5s professional narration
newsDeep, formal broadcast presenter5s documentary voiceover
femaleWarm, conversational support agent5s acoustic reading sample
defaultOriginal CosyVoice high-fidelity voiceModel’s baseline reference

Switching voices is as simple as passing &voice=child in the query string or {"voice": "male"} in the POST payload.


7. Real-World Performance

Running on the RTX 3060:

Self-hosting modern neural TTS is no longer an exercise in brittle compile scripts and robotic phoneme tables. With open-source diffusion models and a modest 12GB workstation GPU, you can run a private, high-fidelity voice engine that surpasses commercial cloud offerings in customization and control.


Want a private AI voice pipeline for your business?

If your support bots, content workflows, or internal tools are paying recurring cloud TTS bills — or struggling with bilingual Chinese-English code-switching — I design and deploy self-hosted speech and n8n automation stacks on hardware you control.

Lee Teong Hoe

Lee Teong Hoe · Mr Hoelee

Full-stack developer & DevOps engineer based in Malaysia. I run my own production infrastructure and build web systems for small businesses — this blog is the living record.

Hiring? Profile & stack · Malaysian SME? Website design & development ↗ · All posts