Usability-Schicht für Nutzer, die kein Terminal-Handbuch lesen wollen:
- `talk doctor`: eine Zeile je Prüfpunkt mit klarem Satz, was Sache ist und
was zu tun wäre — Config (kaputt → ✘, die übrigen Prüfungen laufen mit
Defaults weiter), Daemon (läuft / startet beim nächsten Sprechbefehl /
fremder Dienst auf dem Port → ✘ mit Port-Hinweis), Audio (oto-Kontext
wirklich initialisieren; null → ⚠), jede Provider-Stufe (Key-Env-Name,
Endpunkt, Default-Stimme; OS-Stimme nennt den gefundenen Mechanismus),
Mute (an → ⚠ mit unmute-Hinweis), Gesetze inkl. gerade aktiver Ruhezeit.
--probe macht echte Synthese-Proben, --json liefert die Liste. Exit 0
ohne ✘. Windows-Konsolen bekommen [OK]/[WARN]/[FAIL].
- `talk test`: Testsatz direkt über den Sprech-Kern (nicht über den
Daemon), nennt die Stufe, die wirklich gesprochen hat, Synthese- und
Wiedergabezeit; Mute/Ruhezeit gelten bewusst nicht, Mute wird genannt.
- `talk voices`: kuratierter Katalog mit Namen (ElevenLabs-Premade, OpenAI,
Edge-Neural de/en-Locales) als Tabelle, „*“ = effektive Default-Stimme
(Config vor Repo-Default), Config-IDs außerhalb des Katalogs als eigene
Zeile, Filter --provider/--lang, --json.
- `talk setup`: wenige Fragen statt Bubble Tea — Keys nur als Hinweis
(ohne Key läuft die Edge-Stimme), Stimme je Sprache aus dem Katalog mit
Probehören, Ruhezeit; schreibt die config.toml zusammengeführt mit
bestehenden Werten (.bak), spricht einen Testsatz. q bricht ab, bevor
etwas geschrieben wird; ohne Terminal keine Fragen, nur die wirksame
Konfiguration.
Unterbau: provider.Catalog/VoiceName/DefaultVoice, Chain.SpeakOutcome
(Stufe, Bytes, Zeiten) durch speak.Engine bis in Daemon-Log und test,
audio.Check (oto-Initialisierung ohne Ton), config.Path,
OSBuiltin.Describe. README: Abschnitt „Erste Schritte“.
Tests: voices-Zeilen (Default-Markierung, Config-Override, Filter, JSON),
doctor (ohne Daemon, Mute/Key via JSON, fremder Dienst → Exit 1, kaputte
Config → ✘ aber vollständiger Bericht), test (fake espeak), setup
(stdin-Antworten → config.toml-Inhalt, Merge mit .bak, Abbruch schreibt
nichts, Pipe stellt keine Fragen), Prozessgrenze: doctor/--probe/voices/
test gegen echten Daemon.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Speak rief bei ErrNoByteOutput SpeakDirect auf, das einen eigenen
vollständigen walk machte: fehlgeschlagene Cloud-Stufen wurden zweimal
angefragt (doppelte POSTs auf bezahlten APIs), Fehlschlag-Zeilen
verdoppelten sich im Log, die Worst-Case-Latenz verdoppelte sich, und
Bytes aus einer transienten Erholung im zweiten Durchlauf hätten einen
Fehler statt Wiedergabe produziert.
Speak entscheidet jetzt aus EINEM walk-Ergebnis (Bytes → Player,
nur-Direkt-Stufe → SpeakDirect direkt daran, sonst gebündelter
Stufen-Fehler aus dem geteilten Helper walkResult.noTierErr).
Synthesize/SpeakDirect behalten ihre öffentlichen Verträge; null-Player
verwirft tonlos mit Exit 0 wie zuvor.
Test: TestChainDirektEndgameEinDurchlauf pinnt Cloud-Stufe genau 1×
angefragt, jede Fehlschlag-Zeile genau 1×, Direktansage kommt zustande.