my_voice_assistant_v3_jamulix/Docs/stimmen-inventar.md
dschlueter 6bf281fc30 fix(tts): voice_gender im UserPrefs-Schema -> Stimmwahl wirkt endlich
Eigentliche Ursache für 'immer weibliche Stimme, egal welcher Provider':
UserPrefs kannte kein Feld voice_gender, daher verwarf pydantic in
PUT /api/me/prefs die Geschlechtswahl still. resolve_route sah immer 'any'
-> Piper/Cartesia lieferten die weibliche Stimme (kerstin bzw. Alina).

- voice_gender zum Schema hinzugefügt; Frontend sendet es bereits, resolve_route
  liest es bereits (ROUTE_KEYS), voice_for_route mappt m/f bereits.
- Regressions-Test: voice_gender persistiert über /api/me/prefs.
- Docs/stimmen-inventar.md: zentrale Übersicht aller Stimmen je Provider/
  Sprache/Geschlecht (Name, Datei, UUID) inkl. Fundstellen im Code.

Live verifiziert (Profil jamulix, de): m -> de_DE-thorsten-high,
f -> de_DE-kerstin-low.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 03:13:27 +02:00

5.5 KiB

Stimmen-Inventar (TTS) — eine Quelle der Wahrheit

Diese Datei listet alle TTS-Stimmen je Provider, Sprache und Geschlecht: Stimmenname, Datei bzw. UUID und die Stelle im Code/Config, an der sie definiert ist. Ziel: Schluss mit dem Suchen über mehrere Dateien.

Wer wählt die Stimme? app/dependencies.py::voice_for_route(tts_provider, language, voice_gender). Es liest voice_gender aus der aufgelösten Route (resolve_route), die es wiederum aus den Nutzer-Prefs zieht. Die Geschlechtswahl im Web-UI wird über PUT /api/me/prefs gespeichert — dafür muss voice_gender im Schema app/schemas.py::UserPrefs stehen (sonst verwirft pydantic das Feld still → Nutzer hört immer „any" = weiblich).

Legende: ♀ = weiblich, ♂ = männlich · „—" = nicht vorhanden/keine Geschlechtswahl.


1. Piper (lokal, Standard im Profil jamulix)

  • Definition Geschlecht→Stimme: app/dependencies.pyPIPER_VOICE_GENDERED (mit Geschlecht) und LANG_TO_PIPER_VOICE (geschlechtsloser Fallback).
  • Modelldateien: config/voices/<name>.onnx (+ .onnx.json); Verzeichnis aus config/voice-assistant.toml::piper_voices_dir.
Sprache ♀ Stimme Datei (.onnx) ♂ Stimme Datei (.onnx)
de de_DE-kerstin-low de_DE-kerstin-low de_DE-thorsten-high de_DE-thorsten-high
en en_US-amy-medium en_US-amy-medium en_US-lessac-high en_US-lessac-high
fr fr_FR-siwis-medium fr_FR-siwis-medium fr_FR-tom-medium fr_FR-tom-medium
es es_ES-sharvard-medium #1 es_ES-sharvard-medium (Speaker 1=F) es_ES-sharvard-medium #0 es_ES-sharvard-medium (Speaker 0=M)
it it_IT-paola-medium it_IT-paola-medium it_IT-riccardo-x_low it_IT-riccardo-x_low
ru ru_RU-irina-medium ru_RU-irina-medium ru_RU-ruslan-medium ru_RU-ruslan-medium
pl pl_PL-gosia-medium pl_PL-gosia-medium pl_PL-darkman-medium pl_PL-darkman-medium
pt (keine ♀ in Piper) pt_BR-faber-medium pt_BR-faber-medium
ar (keine ♀ in Piper) ar_JO-kareem-medium ar_JO-kareem-medium
zh / cmn zh_CN-huayan-medium zh_CN-huayan-medium (kein ♂ nutzbar)

Hinweise:

  • es ist ein Multi-Speaker-Modell: Speaker-Index #0=männlich, #1=weiblich (speaker_id_map).
  • pt/ar/zh haben in Piper keine Geschlechts-Varianten → beide Schalterstellungen liefern dieselbe Stimme (Fallback aus LANG_TO_PIPER_VOICE).
  • zh ♂ wäre nur über zh_CN-chaowen-medium möglich, das aber phoneme_type=pinyin (g2pW) braucht — in dieser Installation nicht lauffähig (erzeugt kein Audio).

2. Cartesia (Cloud, Modell sonic-turbo)

  • Definition: config/voice-assistant.toml::cartesia_voices, Format lang:gender:uuid:name.
  • Auflösung UUID: app/providers/tts/cartesia.py::_resolve_voice_id (Fallback-Kette f→m→any→cartesia_voice_id).
Sprache Geschlecht Name UUID
de Sebastian b7187e84-fe22-4344-ba4a-bc013fcb533e
de Alina 38aabb6a-f52b-4fb0-a3d1-988518f4dc06
en Caspar 4f7f1324-1853-48a6-b294-4e78e8036a83
en Gemma 62ae83ad-4f6a-430b-af41-a9bede9286ca
fr Antoine 0418348a-0ca2-4e90-9986-800fb8b3bbc0
fr Amélie 7c58f4a4-a72c-42fa-a503-41b9408820f3
es Augustin (mx) 2695b6b5-5543-4be1-96d9-3967fb5e7fec
es Daniela (mx) 5c5ad5e7-1020-476b-8b91-fdcbe9cc313c
pt Bruno b603811e-54c2-4a0a-8854-09eab9ffa63f
pt Isabella c9611be8-aae9-4a93-bb1c-98dd6b7d52a4
it sonic-turbo unterstützt IT nicht (auskommentiert)
pl sonic-turbo unterstützt PL nicht (auskommentiert)
ru sonic-turbo unterstützt RU nicht (auskommentiert)
ar Cartesia unterstützt Arabic-TTS nicht
zh nicht konfiguriert

Für it/pl/ru/ar/zh greift bei Cartesia die globale Fallback-Kette → letztlich tts_fallback (config/voice-assistant.toml, aktuell piper).


3. OpenRouter (Cloud, Modell openai/gpt-4o-mini-tts)

  • Definition: app/config.py::openrouter_tts_voice (Default alloy), openrouter_tts_model.
  • Keine Geschlechts- oder Sprachauswahl: eine feste Stimme für alle Sprachen. voice_for_route gibt für OpenRouter None zurück → Default-Stimme.
Sprache
alle — (eine feste Stimme alloy)

4. Chatterbox (lokaler GPU-Dienst, Voice-Cloning)

  • Definition: app/config.py::chatterbox_*; Referenz-WAV je Sprache unter chatterbox_voices_dir als config/voices/<lang>.wav.
  • Keine Geschlechtswahl: pro Sprache eine geklonte Stimme (Geschlecht = Aufnahme).
vorhandene Referenz-WAVs en, es, fr, it, nl, ru, zh
ohne <lang>.wav → globale Default-Stimme de, pt, pl, ar, …

Lücken-Überblick (welche Kombination fehlt)

Sprache Piper Cartesia OpenRouter Chatterbox
de, en, fr, es ♀+♂ ♀+♂ nur 1 fix 1 (Klon)
pt nur ♂ ♀+♂ nur 1 fix Default
it, pl, ru ♀+♂ nur 1 fix teils 1
ar nur ♂ nur 1 fix Default
zh nur ♀ nur 1 fix 1 (Klon)

Für die echten Lücken (pt ♀ / ar ♀ / zh ♂) braucht es sprach-/geschlechtsabhängiges Provider-Routing (z. B. pt ♀ → Cartesia Isabella) plus UI-Ausgrauen nicht verfügbarer Kombinationen. Siehe MULTITOOL_AUSBAU_PLAN.md / offene Aufgaben.