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.
- qwentts.cpp bauen. Es gibt kein vorkompiliertes Windows-Binary, daher muss aus dem Quellcode gebaut werden:
Unter Windows: Installiere VS 2022 (oder neuer) Build Tools mit dem C++-Workload, CMake, Ninja und dem CUDA Toolkit, führe danngit 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)buildcuda.cmdaus dem Repository aus. Wennvcvars64.batwoanders 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. - 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 - say.py darauf verweisen wenn du andere Ordner verwendet hast: setze
QWEN_TTS_HOME(das Checkout-Verzeichnis),QWEN_TTS_EXE(die Binary) oderQWEN_TTS_MODELS(der .gguf-Ordner). Unter Windows fügtsay.py%CUDA_PATH%\bin\x64zum PATH hinzu (überschreibbar mitCUDA_BIN). say.py --checkerneut 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
- 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,app2undsay.pywarnt, wenn eine davon läuft. - 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.
- 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.mdaus demwhiteboard-explainer-Skill (gleiches Plugin,references/) und führe dessenscripts/aispeak_scan.pyaus, das einscript.pyoder 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:
| Flag | Funktionsweise |
|---|---|
--speaker | aiden (Standard); ryan ist die andere englische Muttersprachlerstimme |
--instruct | Stiltext, z. B. „Aufgeregt, schnell“ oder „Ruhig und ernst“ |
--seed N | Erzeugt einen wiederholbaren Durchlauf |
--gap S | Sekunden Stille zwischen den Zeilen in einer zusammengefügten Datei |
--srt F | Schreibe auch Untertitel zeitlich abgestimmt auf die zusammengefügte WAV (siehe Untertitel) |
--quant | Q8_0 (Standard, beste Qualität) oder Q4_K_M (kleiner, etwas flacher; zuerst herunterladen) |
--check | Zeige 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.srthinzu (erfordert ein.wav-o). Die Untertitel stimmen genau mit der zusammengefügten Spur überein. - In deiner eigenen Pipeline: rufe
scripts/srt.pyauf,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.srtnebenVideo-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 sichqwen-tts.exestill ohne Ausgabe.say.pyfügt ihn für dich hinzu. --stream-by-line -o -schreibt Streaming-WAV-Header (Größen 0x7fffffff), einen pro Zeile. Teile beiRIFF....WAVEfmtund 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.pyundtts_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.
- 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
- 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
- Testdurchlauf. Generiere
eval/lines.txtmit dem Kandidaten. Bewerte ihn gegen den Champion mitscripts/voice_metrics.py(pip install numpy librosa; die Champion- und Baseline-Aufnahmen befinden sich ineval/):- 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.
- Hören. Bitte den Benutzer, zwischen dem Kandidaten und
eval/champion_*.wavnach Gehör zu wählen (ffplay -nodisp -autoexit datei.wav). Die Metriken erstellen nur eine Shortlist; das Ohr entscheidet. - 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, ersetzeeval/champion_*.wavund aktualisieresay.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.