Files
talk/.superpowers/sdd/plan/task-2-brief.md
T

2.0 KiB

Task 2: Erste Ansage end-to-end (OS-TTS)

Blockiert durch: 01. Liefert: talk "Hallo Welt" spricht über OS-TTS.

  • internal/langdetect: reine Funktion Detect(text string) string → "de" | "en" (Default "de"); Heuristik: Common-Word-Listen + Umlaute/ß; tischgesteuerte Tests (de/en/gemischt/leer).
  • internal/provider: Interface Provider mit Name() string, Available(ctx) bool, Synthesize(ctx, text string, lang string) ([]byte, error) (Rückgabe: dekodierbare Audio-Bytes, Format von der Implementierung dokumentiert; osbuiltin liefert WAV/PCM).
    • Implementierung osbuiltin: Linux über espeak/speech-dispatcher-Fallback (externer Prozess — OK, es ist der Notnagel-Provider; wenn Binary fehlt: Available() == false), macOS über say (Ausgabe in temporäre WAV-Datei), Windows über SAPI (PowerShell System.Speech). Fehlende Binary/Runtime → klarer Fehler, kein Panik.
  • internal/audio: Sink-Interface (Play(ctx, data []byte) error, Name() string); Implementierungen oto (embedded Playback, PCM/WAV) und null (verwirft, loggt). Auswahl per Config audio.sink = "oto"|"null" (Default oto).
  • internal/config: minimale Auflösung: Defaults + TOML-Datei (falls vorhanden) + Env-Overrides (TALK_AUDIO_SINK); Platform-Pfad-Auflösung (~/.config/talk | ~/Library/Application Support/talk | %APPDATA%\talk, respektive XDG_CONFIG_HOME/Env); tischgesteuerte Unit-Tests für Merge + Pfadlogik (Pfade injizierbar).
  • cmd/talk: say-Pfad implementiert: Text (Arg oder stdin) → langdetect → Providerauswahl (hier: osbuiltin, Kette kommt in Task 03; Struktur so, dass --provider-Flag schon existiert und osbuiltin default ist) → Synthesize → Sink.Play. Blocking (Daemon kommt in Task 04).
  • Abnahme: talk "Hallo Welt" erzeugt hörbare Ausgabe auf dem Dev-Host (Linux; espeak vorhanden oder als Dev-Abhängigkeit dokumentiert); TALK_AUDIO_SINK=null läuft ohne Ton durch; go test ./... grün (langdetect + config + provider-mit-fake-proc wo sinnvoll).