Communitygithub.com

lokal-tts

Erzeuge natürlich klingende Sprache auf deiner eigenen GPU (oder CPU) ohne API-Kosten – Voiceovers, Erzählungen für Erklärvideos, Vorlesen von Text und Audioclips inklusive passender .srt-Untertitel aus den bekannten Zeitspannen.

Was ist lokal-tts?

Local TTS ermöglicht die lokale Sprachsynthese mittels Qwen3-TTS 1.7B (8-bit GGUF) ausgeführt durch qwentts.cpp. Der Standard-Sprecher „Aiden“ wurde in einem Blindtest gegen mehrere Alternativen (Kokoro, Chatterbox, PyTorch Qwen3-TTS, VoxCPM2, Phonon) bevorzugt. Auf einer RTX 4070 Laptop GPU mit 8 GB VRAM läuft die Generierung etwa 4x Echtzeit – eine 18-minütige Erzählung wird in ca. 4,5 Minuten erzeugt. Das Skill unterstützt Windows, Linux und macOS, erfordert eine einmalige Einrichtung (Bau von qwentts.cpp, Download der Modelldateien, Konfiguration) und bietet Optionen wie verschiedene Sprecher, Style-Instruktionen, Seeds, Untertitel-Export und CPU-Fallback. Es enthält zudem eine automatisierte Routine, um regelmäßig nach besseren lokalen TTS-Modellen zu suchen und diese zu vergleichen.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Ayushmaniar/claude-explainer-skills/tree/HEAD/plugins/explainer-skills/skills/local-tts

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Local TTS (Lokale Sprachsynthese)

Die Standardstimme: Qwen3-TTS 1.7B CustomVoice, Sprecher aiden, 8-Bit GGUF (Q8_0), ausgeführt durch qwentts.cpp (C++/ggml, MIT) mit folgender Stilanweisung:

Warm, klar und neugierig, wie ein freundlicher Erklärvideo-Sprecher. Entspanntes, gleichmäßiges Tempo.

Sie gewann einen Blindtest gegen Kokoro, Chatterbox, PyTorch Qwen3-TTS, VoxCPM2 und Phonon (siehe references/benchmarks.md). Auf einer 8 GB RTX 4070 Laptop GPU läuft es etwa 4x Echtzeit inklusive Modellladezeit: eine 18-minütige Erzählung dauert ca. 4,5 Minuten.

Setup (einmal pro Maschine)

Führe zuerst python -I <skill>/scripts/say.py --check aus. Wenn OK ausgegeben wird, überspringe diesen Abschnitt. Andernfalls richte die Engine ein – oder bitte den Benutzer darum. Es dauert 10–20 Minuten und benötigt ~2,5 GB Speicherplatz.

  1. qwentts.cpp bauen. Es gibt kein vorkompiliertes Windows-Binary, daher muss aus dem Quellcode gebaut werden:
    git clone --recurse-submodules https://github.com/ServeurpersoCom/qwentts.cpp ~/tools/qwentts.cpp
    cd ~/tools/qwentts.cpp
    ./buildcuda.sh       # NVIDIA (Linux); ./buildvulkan.sh für AMD/Intel; ./buildcpu.sh für CPU-only (z. B. macOS)
    
    Unter Windows: Installiere VS 2022 (oder neuer) Build Tools mit dem C++-Workload, CMake, Ninja und dem CUDA Toolkit, führe dann buildcuda.cmd aus dem Repository aus. Wenn vcvars64.bat woanders liegt, bearbeite den Pfad am Anfang dieses Skripts. Um nur eine GPU anzusprechen, füge -DCMAKE_CUDA_ARCHITECTURES=89 (RTX 40xx; 86 = RTX 30xx, 120 = RTX 50xx) zur cmake-Zeile hinzu.
  2. Die Gewichte herunterladen (~2 GB) von Hugging Face Serveurperso/Qwen3-TTS-GGUF:
    pip install -U huggingface_hub
    hf download Serveurperso/Qwen3-TTS-GGUF qwen-talker-1.7b-customvoice-Q8_0.gguf qwen-tokenizer-12hz-Q8_0.gguf --local-dir ~/tools/qwen-gguf
    
  3. say.py darauf verweisen wenn du andere Ordner verwendet hast: setze QWEN_TTS_HOME (das Checkout-Verzeichnis), QWEN_TTS_EXE (die Binary) oder QWEN_TTS_MODELS (der .gguf-Ordner). Unter Windows fügt say.py %CUDA_PATH%\bin\x64 zum PATH hinzu (überschreibbar mit CUDA_BIN).
  4. say.py --check erneut ausführen, dann eine Testzeile sprechen.

Hardware: 8 GB VRAM reichen locker für Q8_0 (~3 GB Auslastung). Ohne GPU funktioniert ein CPU-Build mit etwa einem Viertel der Geschwindigkeit. GGML_BACKEND=CPU zwingt einen GPU-Build auf die CPU.

Vor der Generierung

  1. Wird die GPU gerade von etwas anderem genutzt? Ein Spiel oder eine andere GPU-intensive Anwendung macht die Generierung ~4x langsamer und lässt diese Anwendung ruckeln. Frage vor einem längeren Job nach. Wenn der Benutzer solche Apps nennt, setze TTS_BUSY_APPS=app1,app2 und say.py warnt, wenn eine davon läuft.
  2. Lohnt sich ein neueres Modell? Siehe „Suche weiter nach besseren Modellen“ unten. Wenn die letzte Prüfung mehr als ~6 Wochen zurückliegt und die Aufgabe eine echte Erzählung (kein Einzeiler-Test) ist, führe zuerst den schnellen Scan durch.
  3. Klingt der Text menschlich? Eine Stimme liest KI-Sprech immer mit dem gleichen Tonfall vor, sodass das Muster stärker auffällt als auf einer Seite. Bei jeder Erzählung länger als ein paar Zeilen lies natural-narration.md aus dem whiteboard-explainer-Skill (gleiches Plugin, references/) und führe dessen scripts/aispeak_scan.py aus, das ein script.py oder eine Textdatei als Eingabe nimmt.

Generieren

Das Skript verwendet nur die Standardbibliothek, daher funktioniert jedes Python 3.10+. <skill> ist der Ordner dieses Skills.

python -I <skill>/scripts/say.py "Erster Satz." "Zweiter Satz." -o ausgabe.wav      # eine WAV, 0,35 s Lücken
python -I <skill>/scripts/say.py --file zeilen.txt -o clips/                          # 000.wav, 001.wav, ...

Optionen:

FlagFunktionsweise
--speakeraiden (Standard); ryan ist die andere englische Muttersprachlerstimme
--instructStiltext, z. B. „Aufgeregt, schnell“ oder „Ruhig und ernst“
--seed NErzeugt einen wiederholbaren Durchlauf
--gap SSekunden Stille zwischen den Zeilen in einer zusammengefügten Datei
--srt FSchreibe auch Untertitel zeitlich abgestimmt auf die zusammengefügte WAV (siehe Untertitel)
--quantQ8_0 (Standard, beste Qualität) oder Q4_K_M (kleiner, etwas flacher; zuerst herunterladen)
--checkZeige die gefundene Engine, Modelle und CUDA-Ordner an

So funktioniert es:

  • Jede Zeile durchläuft einen Prozess, sodass das Modell nur einmal geladen wird (3–8 s). Übergib Zeilen gebündelt, nicht einen Aufruf pro Zeile.
  • Ausgabe ist 24 kHz Mono 16-Bit WAV.

Durchläufe sind unterschiedlich, daher unterscheidet sich jeder Durchlauf:

  • Behalte Clips, die dir gefallen. Cache pro Zeile, basierend auf Text und Einstellungen.
  • Wiederhole eine Zeile, wenn ihre Länge stark von ~0,07 s pro Zeichen abweicht. Das bedeutet, dass Wörter ausgelassen oder erfunden wurden.

Für eine Video-Erzählung zusätzlich:

  • Schneide die Stille jedes Clips auf ~50 ms Polsterung, dann platziere die Zeilen auf der Timeline mit eigenen Abständen.
  • Loudness-normalisiere die endgültige Spur: ffmpeg -af loudnorm=I=-16:TP=-1.5:LRA=11.

Untertitel (.srt): bei jedem Video mit Erzählung anbieten

Du weißt bereits, wann jede Zeile beginnt und endet, also gibt es nichts zu transkribieren. Baue die Untertitel aus diesen Zeitangaben.

  • Mit say.py: füge --srt erzaehlung.srt hinzu (erfordert ein .wav -o). Die Untertitel stimmen genau mit der zusammengefügten Spur überein.
  • In deiner eigenen Pipeline: rufe scripts/srt.py auf, to_srt([(start_s, end_s, text), ...], display=[...]), mit den Start-/Endzeiten der Videozeit pro gesprochener Zeile. Oder verwende die CLI: python srt.py timings.tsv -o video.srt.
  • Korrigiere die Schreibweisen für die Anzeige. Erzähltexte sind oft für die Stimme geschrieben: „D I L“, Namen phonetisch umgeschrieben, „runner dot HTML“, Zahlen in Worten. Bilde sie mit display / --display display.tsv (gesprochengeschrieben) zurück. Verwende die geschriebenen Formen vom Bildschirm, und benutze Ziffern für Zahlen („$232“, „83%“).
  • Überprüfe das Ergebnis. Durchsuche es nach übriggebliebenen Großbuchstaben ([A-Z] [A-Z]) und „ dot “.
  • Regeln, die das Modul anwendet:
    • maximal 2 Zeilen à 42 Zeichen pro Untertitel
    • bricht am Satz, dann am Satzglied, dann am Wort
    • kurze Sätze werden zusammengeführt, damit nichts vorbeiflitzt
    • Zeit proportional zur Länge aufgeteilt
  • Benenne es wie das Video (Video-Name.srt neben Video-Name.mp4), damit Player es automatisch laden. In VLC erzwingt --sub-file= eine Datei.

Das whiteboard-explainer-Skill enthält mit template/narration/build_vo.py eine vollständige Pipeline: Per-Zeilen-Cache, Wiederholungen, Stille kürzen, Pausen formen, Wortausrichtung, eine Cue-Tabelle und eine Lippensynchronisationshüllkurve.

Fallstricke

  • Die CUDA DLLs müssen im PATH sein (Windows). CUDA 13 hält sie in ...\CUDA\v13.x\bin\x64. Ohne diesen Ordner im PATH beendet sich qwen-tts.exe still ohne Ausgabe. say.py fügt ihn für dich hinzu.
  • --stream-by-line -o - schreibt Streaming-WAV-Header (Größen 0x7fffffff), einen pro Zeile. Teile bei RIFF....WAVEfmt und verwerfe jeden 44-Byte-Header. Vertraue nicht den Größenfeldern.
  • Aiden liest einzelne Buchstaben und seltsame Tokens falsch. Gefunden durch ein unaufgefordertes Whisper-Audit:
    • „h star“ kam als „a hap“ oder „our star“, „y t“ als „VT“, „y“ als „we“ und „arXiv“ als „ArcSireFolk“.
    • Diese funktionieren: großes „H star“ / „under H“, „why tee“ / „why tilde“, „archive“ und „SMILES check“.
    • „aitch“ ist unzuverlässig. Ein Name kann allein funktionieren und im Satz verfälscht werden: teste ihn in der gesamten Zeile.
    • Ein satzanfängliches K kann ausfallen („Kwenputer“ → „When Pooter“): beginne solche Zeilen mit „And“ oder „So“.
    • Auditiere, indem du jeden Clip ohne das Skript als initialen Prompt transkribierst und dann mit dem Skript vergleichst. Ein aufgefordertes Whisper „hört“ die beabsichtigten Wörter und verdeckt die Fehler. Werkzeuge: whiteboard-explainer/template/narration/audit_vo.py und tts_try.py.
  • Pausen an Doppelpunkten. Qwen pausiert 0,6–0,8 s an einem Doppelpunkten und manchmal in der Mitte einer Phrase. Begrenze in einer Erzählung jede Stille durch die davorstehende Interpunktion (shape() in der build_vo.py-Vorlage) und vermeide Zeilen, die mit einem Doppelpunkt enden („Zuerst: …“).
  • CPU-Fallback: Kokoro 82M (kokoro-onnx) ist flach, aber schnell auf der CPU, gut für Entwürfe, während die GPU beschäftigt ist.

Suche weiter nach besseren Modellen

Lokale TTS verbessert sich schnell, und die aktuelle Wahl wird bald übertroffen. Behandle sie als aktuellen Champion, nicht als endgültige Antwort. Suche nach neueren und besseren Modellen, insbesondere vor einem großen Erzählungs-Job oder wenn die letzte Prüfung mehr als ~6 Wochen zurückliegt.

  1. Scan. Durchsuche das Web nach Open-Weight-TTS, das seit der letzten Prüfung veröffentlicht oder aktualisiert wurde. Schaue auf:
    • TTS Arena / Artificial Analysis Speech Leaderboards
    • Hugging Face Trending Text-to-Speech-Modelle
    • r/LocalLLaMA
    • GitHub-Releases der unten genannten Engines
  2. Filter. Behalte einen Kandidaten nur, wenn er:
    • lokal kostenlos verwendet werden kann (offene Gewichte, permissive oder persönliche Lizenz)
    • auf dem GPU-Speicher und Betriebssystem des Benutzers läuft
    • die benötigte Sprache spricht
    • den Champion in der Qualität übertrifft oder gleich gut ist, dabei aber deutlich schneller ist
  3. Testdurchlauf. Generiere eval/lines.txt mit dem Kandidaten. Bewerte ihn gegen den Champion mit scripts/voice_metrics.py (pip install numpy librosa; die Champion- und Baseline-Aufnahmen befinden sich in eval/):
    • Tonhöhen-Standardabweichung ≥ ~5 Halbtöne und Tonhöhen-Bereich ≥ ~17 Halbtöne sind nötig, um natürlich zu klingen.
    • Miss Geschwindigkeit als Sekunden Audio pro Sekunde Generierung.
  4. Hören. Bitte den Benutzer, zwischen dem Kandidaten und eval/champion_*.wav nach Gehör zu wählen (ffplay -nodisp -autoexit datei.wav). Die Metriken erstellen nur eine Shortlist; das Ohr entscheidet.
  5. Dokumentieren. Aktualisiere die Zeile „Zuletzt geprüft“ unten und references/benchmarks.md, unabhängig davon, ob sich etwas geändert hat. Wenn der Champion wechselt, ersetze eval/champion_*.wav und aktualisiere say.py, und frage, bevor das alte Modell gelöscht wird.

Zuletzt geprüft: 2026-11-02 (Web-Umfrage plus lokale VoxCPM2 Q8 und Phonon 31m/Miles-Tests). Aiden wurde im Hörtest gegenüber beiden bevorzugt. Noch nicht lokal getestet: Phonon 40m, OmniVoice, Breeze TTS 2, Drama 3, Orpheus, Dia, Sesame CSM, Spark-TTS, IndexTTS-2, VibeVoice, Higgs Audio, Kyutai TTS und Fish/OpenAudio. Details in references/benchmarks.md.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Verwandte Skills