package provider import "sort" // Voice ist ein Eintrag des Stimmen-Katalogs: eine bekannte Stimme eines // Providers für eine Sprache, mit lesbarem Namen. Der Katalog ist kuratiert // (die gängigen Standardstimmen), nicht vollständig — jede Voice-ID des // Providers funktioniert auch ohne Katalog-Eintrag (--voice, config). type Voice struct { Provider string Lang string // de | en ID string Name string } // catalog sind die bekannten Stimmen je Provider. ElevenLabs: öffentliche // Premade-Stimmen (multilingual, daher für de UND en gelistet). OpenAI: die // Stimmen der TTS-API (sprachunabhängig). Edge: Neural-Stimmen der // jeweiligen Locale. osbuiltin kennt keine IDs (das OS wählt). var catalog = []Voice{ {"elevenlabs", "de", "21m00Tcm4TlvDq8ikWAM", "Rachel"}, {"elevenlabs", "de", "pNInz6obpgDQGcFmaJgB", "Adam"}, {"elevenlabs", "de", "EXAVITQu4vr4xnSDxMaL", "Bella"}, {"elevenlabs", "de", "ErXwobaYiN019PkySvjV", "Antoni"}, {"elevenlabs", "de", "TxGEqnHWrfWFTfGW9XjX", "Josh"}, {"elevenlabs", "en", "21m00Tcm4TlvDq8ikWAM", "Rachel"}, {"elevenlabs", "en", "pNInz6obpgDQGcFmaJgB", "Adam"}, {"elevenlabs", "en", "EXAVITQu4vr4xnSDxMaL", "Bella"}, {"elevenlabs", "en", "ErXwobaYiN019PkySvjV", "Antoni"}, {"elevenlabs", "en", "TxGEqnHWrfWFTfGW9XjX", "Josh"}, {"openai", "de", "alloy", "Alloy"}, {"openai", "de", "echo", "Echo"}, {"openai", "de", "fable", "Fable"}, {"openai", "de", "onyx", "Onyx"}, {"openai", "de", "nova", "Nova"}, {"openai", "de", "shimmer", "Shimmer"}, {"openai", "en", "alloy", "Alloy"}, {"openai", "en", "echo", "Echo"}, {"openai", "en", "fable", "Fable"}, {"openai", "en", "onyx", "Onyx"}, {"openai", "en", "nova", "Nova"}, {"openai", "en", "shimmer", "Shimmer"}, {"edge", "de", "de-DE-KatjaNeural", "Katja"}, {"edge", "de", "de-DE-ConradNeural", "Conrad"}, {"edge", "de", "de-DE-AmalaNeural", "Amala"}, {"edge", "de", "de-DE-KillianNeural", "Killian"}, {"edge", "de", "de-AT-IngridNeural", "Ingrid (AT)"}, {"edge", "de", "de-CH-LeniNeural", "Leni (CH)"}, {"edge", "en", "en-US-AriaNeural", "Aria"}, {"edge", "en", "en-US-GuyNeural", "Guy"}, {"edge", "en", "en-US-JennyNeural", "Jenny"}, {"edge", "en", "en-US-ChristopherNeural", "Christopher"}, {"edge", "en", "en-GB-SoniaNeural", "Sonia (GB)"}, {"edge", "en", "en-GB-RyanNeural", "Ryan (GB)"}, } // Catalog liefert den Stimmen-Katalog in stabiler Reihenfolge // (Ketten-Reihenfolge der Provider, dann de vor en, dann Katalog-Reihe). func Catalog() []Voice { out := make([]Voice, len(catalog)) copy(out, catalog) rank := map[string]int{} for i, name := range DefaultOrder { rank[name] = i } sort.SliceStable(out, func(i, j int) bool { if rank[out[i].Provider] != rank[out[j].Provider] { return rank[out[i].Provider] < rank[out[j].Provider] } return out[i].Lang < out[j].Lang }) return out } // VoiceName liefert den Katalog-Namen einer Voice-ID; leer, wenn unbekannt. func VoiceName(provider, id string) string { for _, v := range catalog { if v.Provider == provider && v.ID == id { return v.Name } } return "" } // DefaultVoice liefert die effektive Default-Stimme eines Providers für // eine Sprache: config-Mapping voice.. vor dem Repo-Default // (ohne --voice-Pin). Leer bei osbuiltin (das OS wählt). func DefaultVoice(provider, lang string, cfgVoices map[string]map[string]string) string { return resolveVoice(provider, lang, "", cfgVoices[provider]) }