feat(voice_loop): --voice-Option + saubere Default-Stimme je TTS-Provider
- voice_loop.py: --voice reicht die Stimme im Start-Frame durch (nur wenn gesetzt), sonst greift der Provider-Default. Beispiele in Docstring/Help. - ws.py/speak.py/chat.py: ohne explizite Stimme None durchreichen statt die OpenRouter-Stimme zu erzwingen -> jeder Provider nimmt SEINEN Default (OPENROUTER_TTS_VOICE bzw. PIPER_VOICE). Ungenutzten settings-Import in speak.py entfernt. - Doku: BEDIENUNGSANLEITUNG (--voice + Default-Stimme je Provider). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
a40ae75c5f
commit
9d0019274a
5 changed files with 22 additions and 7 deletions
|
|
@ -323,8 +323,16 @@ curl -s -X POST "$URL/api/speak" -H 'Content-Type: application/json' \
|
|||
# anderes TTS-Modell (andere Stimmenfamilie):
|
||||
echo 'OPENROUTER_TTS_MODEL=openai/gpt-4o-mini-tts' >> .env
|
||||
```
|
||||
Das Feld `voice` gibt es im Body von `/api/speak` und `/api/chat`. Hinweis:
|
||||
`scripts/voice_loop.py` hat **keine** `--voice`-Option — dort gilt der Server-Default.
|
||||
Das Feld `voice` gibt es im Body von `/api/speak` und `/api/chat`. Im Sprech-Loop
|
||||
direkt durchprobieren mit `--voice` (ohne Angabe gilt der Provider-Default):
|
||||
```bash
|
||||
python scripts/voice_loop.py --tts-provider openrouter --voice Puck # Cloud-Stimme
|
||||
python scripts/voice_loop.py --tts-provider piper --voice de_DE-kerstin-low # lokale Stimme
|
||||
```
|
||||
**Default-Stimme je Provider:** Wird keine Stimme angefragt, nimmt jeder TTS-Provider
|
||||
seinen eigenen Default — OpenRouter `OPENROUTER_TTS_VOICE`, piper `PIPER_VOICE`. `--voice`
|
||||
ist provider-spezifisch: ein Gemini-/OpenAI-Stimmenname für `openrouter`, ein Modellname
|
||||
für `piper` (ein unpassender Name fällt bei piper auf `PIPER_VOICE` zurück).
|
||||
|
||||
## B2. Soundquelle & Ausgabe-Gerät wechseln (Mikrofon, Lautsprecher, Bluetooth, Handy)
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ async def chat(
|
|||
"llm_provider": payload.llm_provider,
|
||||
"tts_provider": payload.tts_provider,
|
||||
}
|
||||
voice = payload.voice or settings.openrouter_tts_voice
|
||||
# None -> der gewaehlte TTS-Provider nimmt seinen eigenen Default.
|
||||
voice = payload.voice
|
||||
|
||||
store = get_store()
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from io import BytesIO
|
|||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from app.config import settings
|
||||
from app.errors import RoutingError
|
||||
from app.auth import require_user
|
||||
from app.store import User, SessionOwnershipError
|
||||
|
|
@ -33,7 +32,8 @@ async def speak(
|
|||
"language": payload.language,
|
||||
"tts_provider": payload.tts_provider,
|
||||
}
|
||||
voice = payload.voice or settings.openrouter_tts_voice
|
||||
# None -> der gewaehlte TTS-Provider nimmt seinen eigenen Default.
|
||||
voice = payload.voice
|
||||
|
||||
try:
|
||||
route = resolve_route(user, session_id, overrides)
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@ async def _run_turn(websocket, store, user, session_id, route, orchestrator, out
|
|||
|
||||
await websocket.send_json({"type": "ack", "route": route.as_dict()})
|
||||
|
||||
voice = options.get("voice") or settings.openrouter_tts_voice
|
||||
# Ohne explizite Stimme None lassen -> jeder TTS-Provider nimmt SEINEN Default
|
||||
# (OpenRouter: OPENROUTER_TTS_VOICE, piper: PIPER_VOICE).
|
||||
voice = options.get("voice")
|
||||
stream = bool(options.get("stream"))
|
||||
# audio_stream: explizite Anfrage gewinnt, sonst der serverseitige Default (Admin).
|
||||
audio_stream = bool(options["audio_stream"]) if "audio_stream" in options \
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ Beispiele:
|
|||
python scripts/voice_loop.py --url ws://localhost:8003/ws/voice --session oma-anna
|
||||
python scripts/voice_loop.py --device hw:1,0 # bestimmtes Mikrofon (arecord -L)
|
||||
python scripts/voice_loop.py --llm-provider openrouter --tts-provider openrouter
|
||||
python scripts/voice_loop.py --tts-provider openrouter --voice Puck # Cloud-Stimme testen
|
||||
python scripts/voice_loop.py --file frage.wav # ohne Mikrofon (Test)
|
||||
|
||||
Voraussetzungen: laufendes Gateway, `arecord` (Aufnahme), ein Player
|
||||
|
|
@ -211,7 +212,7 @@ def _start_frame(args) -> dict:
|
|||
frame["audio_stream"] = args.stream_audio
|
||||
if getattr(args, "stream_text", False):
|
||||
frame["stream"] = True
|
||||
for key in ("stt_provider", "llm_provider", "tts_provider", "language"):
|
||||
for key in ("stt_provider", "llm_provider", "tts_provider", "language", "voice"):
|
||||
value = getattr(args, key, None)
|
||||
if value:
|
||||
frame[key] = value
|
||||
|
|
@ -346,6 +347,9 @@ def main() -> None:
|
|||
p.add_argument("--stt-provider", dest="stt_provider", default=None)
|
||||
p.add_argument("--llm-provider", dest="llm_provider", default=None)
|
||||
p.add_argument("--tts-provider", dest="tts_provider", default=None)
|
||||
p.add_argument("--voice", default=None,
|
||||
help="TTS-Stimme (provider-spezifisch; ohne Angabe gilt der Provider-Default, "
|
||||
"z. B. OPENROUTER_TTS_VOICE bzw. PIPER_VOICE)")
|
||||
p.add_argument("--language", default=None)
|
||||
# Audio-Streaming: Default entscheidet der Server (AUDIO_STREAM_DEFAULT, i. d. R. an).
|
||||
audio_grp = p.add_mutually_exclusive_group()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue