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>
This commit is contained in:
Dieter Schlüter 2026-06-27 03:13:27 +02:00
commit 6bf281fc30
3 changed files with 123 additions and 0 deletions

View file

@ -88,6 +88,17 @@ def test_user_prefs_applied_to_route(monkeypatch):
assert resp.headers["X-Output-Endpoint"] == "loopback"
def test_voice_gender_pref_persists(monkeypatch):
# Regression: voice_gender muss im UserPrefs-Schema deklariert sein, sonst verwirft
# pydantic die Stimmwahl still und der Nutzer hoert immer dieselbe (weibliche) Stimme.
_enable_auth(monkeypatch)
auth = {"Authorization": f"Bearer {_create_user('Gender')}"}
client.put("/api/me/prefs", headers=auth, json={"voice_gender": "m"})
prefs = client.get("/api/me", headers=auth).json()["prefs"]
assert prefs.get("voice_gender") == "m"
def test_memories_crud(monkeypatch):
_enable_auth(monkeypatch)
auth = {"Authorization": f"Bearer {_create_user('Mem')}"}