Files
talk/internal/provider/voices.go
T

75 lines
2.2 KiB
Go
Raw Permalink Normal View History

package provider
import "sort"
// voiceDefaults are the neutral repo defaults per provider and language
// (part of the public contract: `talk voices` lists them; they are
// overridden by voice.<provider>.<lang> in config.toml or the CLI flag
// --voice).
//
// Decision note on the ElevenLabs voice: spec and plan explicitly treat the
// personal voice KXxZd16DiBqt82nbarJx as the user's PRIVATE default ("not a
// repo default", spec Further Notes); the repo default is therefore the
// neutral, multilingual standard voice "Rachel" (21m00Tcm4TlvDq8ikWAM from
// the public ElevenLabs catalog). The personal voice belongs in one's own
// config.toml:
//
// [voice.elevenlabs]
// de = "KXxZd16DiBqt82nbarJx"
// en = "KXxZd16DiBqt82nbarJx"
//
// OpenAI "alloy" and the Edge neural voices (de-DE-KatjaNeural,
// en-US-AriaNeural) are the respective neutral standard voices of the APIs.
var voiceDefaults = map[string]map[string]string{
"elevenlabs": {
"de": "21m00Tcm4TlvDq8ikWAM", // "Rachel", multilingual
"en": "21m00Tcm4TlvDq8ikWAM",
},
"openai": {
"de": "alloy",
"en": "alloy",
},
"edge": {
"de": "de-DE-KatjaNeural",
"en": "en-US-AriaNeural",
},
"osbuiltin": {
// osbuiltin maps internally on its own (macOS Anna/Samantha, SAPI
// culture, espeak -v <lang>) and has no voice IDs; documented here
// only for completeness.
"de": "",
"en": "",
},
}
// resolveVoice returns the voice ID for a provider and a language.
// Precedence: override (CLI flag --voice or PinVoice) > mapping from
// config.toml > neutral repo default > en default > alphabetically first
// default. An empty result means: the provider has no voice for this
// language (osbuiltin) and decides on its own.
func resolveVoice(name, lang, override string, cfgVoices map[string]string) string {
if override != "" {
return override
}
if v := cfgVoices[lang]; v != "" {
return v
}
def := voiceDefaults[name]
if v := def[lang]; v != "" {
return v
}
if v := def["en"]; v != "" {
return v
}
keys := make([]string, 0, len(def))
for k := range def {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
if v := def[k]; v != "" {
return v
}
}
return ""
}