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.. 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 ) 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 "" }