feat(tts): add method selector (speaker | radio) to TTS speak

/setup/tts/speak now accepts a "method" field (and the CLI a --method
flag): "radio" (default, LOCAL_INTERNET_RADIO, no app_key, replaces
source) or "speaker" (POST /speaker notification, ducks+resumes, honours
volume). The speaker method defaults the app_key to "aftertouch" when
none is configured, since the speaker validates it via GET /v1/auth which
we answer 200 regardless.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-05-31 22:35:31 +02:00
co-authored by Claude Opus 4.8
parent 56c4ae4e2d
commit e6d5588b99
2 changed files with 63 additions and 17 deletions
+10 -1
View File
@@ -63,7 +63,12 @@ func ttsSpeakCmd() *cli.Command {
&cli.IntFlag{
Name: "volume",
Aliases: []string{"v"},
Usage: "Playback volume (0-100, 0 = service default)",
Usage: "Playback volume (0-100, 0 = service default; only honoured by --method speaker)",
},
&cli.StringFlag{
Name: "method",
Usage: "Playback method: 'radio' (LOCAL_INTERNET_RADIO, no app_key, replaces source) or 'speaker' (/speaker notification, ducks+resumes, supports volume)",
Value: "radio",
},
),
Action: ttsSpeak,
@@ -100,6 +105,10 @@ func ttsSpeak(c *cli.Context) error {
payload["volume"] = c.Int("volume")
}
if m := c.String("method"); m != "" {
payload["method"] = m
}
body, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("marshal request: %w", err)