mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 00:07:10 +00:00
Add default voice for languages in cloud TTS (#137300)
* Add default voice for languages in cloud TTS * Add test * use defined voice * Add test to ensure all default voices are valid
This commit is contained in:
parent
0a32a9d6db
commit
dd1def3c5d
@ -38,6 +38,156 @@ ATTR_GENDER = "gender"
|
||||
DEPRECATED_VOICES = {"XiaoxuanNeural": "XiaozhenNeural"}
|
||||
SUPPORT_LANGUAGES = list(TTS_VOICES)
|
||||
|
||||
DEFAULT_VOICES = {
|
||||
"af-ZA": "AdriNeural",
|
||||
"am-ET": "MekdesNeural",
|
||||
"ar-AE": "FatimaNeural",
|
||||
"ar-BH": "LailaNeural",
|
||||
"ar-DZ": "AminaNeural",
|
||||
"ar-EG": "SalmaNeural",
|
||||
"ar-IQ": "RanaNeural",
|
||||
"ar-JO": "SanaNeural",
|
||||
"ar-KW": "NouraNeural",
|
||||
"ar-LB": "LaylaNeural",
|
||||
"ar-LY": "ImanNeural",
|
||||
"ar-MA": "MounaNeural",
|
||||
"ar-OM": "AbdullahNeural",
|
||||
"ar-QA": "AmalNeural",
|
||||
"ar-SA": "ZariyahNeural",
|
||||
"ar-SY": "AmanyNeural",
|
||||
"ar-TN": "ReemNeural",
|
||||
"ar-YE": "MaryamNeural",
|
||||
"az-AZ": "BabekNeural",
|
||||
"bg-BG": "KalinaNeural",
|
||||
"bn-BD": "NabanitaNeural",
|
||||
"bn-IN": "TanishaaNeural",
|
||||
"bs-BA": "GoranNeural",
|
||||
"ca-ES": "JoanaNeural",
|
||||
"cs-CZ": "VlastaNeural",
|
||||
"cy-GB": "NiaNeural",
|
||||
"da-DK": "ChristelNeural",
|
||||
"de-AT": "IngridNeural",
|
||||
"de-CH": "LeniNeural",
|
||||
"de-DE": "KatjaNeural",
|
||||
"el-GR": "AthinaNeural",
|
||||
"en-AU": "NatashaNeural",
|
||||
"en-CA": "ClaraNeural",
|
||||
"en-GB": "LibbyNeural",
|
||||
"en-HK": "YanNeural",
|
||||
"en-IE": "EmilyNeural",
|
||||
"en-IN": "NeerjaNeural",
|
||||
"en-KE": "AsiliaNeural",
|
||||
"en-NG": "EzinneNeural",
|
||||
"en-NZ": "MollyNeural",
|
||||
"en-PH": "RosaNeural",
|
||||
"en-SG": "LunaNeural",
|
||||
"en-TZ": "ImaniNeural",
|
||||
"en-US": "JennyNeural",
|
||||
"en-ZA": "LeahNeural",
|
||||
"es-AR": "ElenaNeural",
|
||||
"es-BO": "SofiaNeural",
|
||||
"es-CL": "CatalinaNeural",
|
||||
"es-CO": "SalomeNeural",
|
||||
"es-CR": "MariaNeural",
|
||||
"es-CU": "BelkysNeural",
|
||||
"es-DO": "RamonaNeural",
|
||||
"es-EC": "AndreaNeural",
|
||||
"es-ES": "ElviraNeural",
|
||||
"es-GQ": "TeresaNeural",
|
||||
"es-GT": "MartaNeural",
|
||||
"es-HN": "KarlaNeural",
|
||||
"es-MX": "DaliaNeural",
|
||||
"es-NI": "YolandaNeural",
|
||||
"es-PA": "MargaritaNeural",
|
||||
"es-PE": "CamilaNeural",
|
||||
"es-PR": "KarinaNeural",
|
||||
"es-PY": "TaniaNeural",
|
||||
"es-SV": "LorenaNeural",
|
||||
"es-US": "PalomaNeural",
|
||||
"es-UY": "ValentinaNeural",
|
||||
"es-VE": "PaolaNeural",
|
||||
"et-EE": "AnuNeural",
|
||||
"eu-ES": "AinhoaNeural",
|
||||
"fa-IR": "DilaraNeural",
|
||||
"fi-FI": "SelmaNeural",
|
||||
"fil-PH": "BlessicaNeural",
|
||||
"fr-BE": "CharlineNeural",
|
||||
"fr-CA": "SylvieNeural",
|
||||
"fr-CH": "ArianeNeural",
|
||||
"fr-FR": "DeniseNeural",
|
||||
"ga-IE": "OrlaNeural",
|
||||
"gl-ES": "SabelaNeural",
|
||||
"gu-IN": "DhwaniNeural",
|
||||
"he-IL": "HilaNeural",
|
||||
"hi-IN": "SwaraNeural",
|
||||
"hr-HR": "GabrijelaNeural",
|
||||
"hu-HU": "NoemiNeural",
|
||||
"hy-AM": "AnahitNeural",
|
||||
"id-ID": "GadisNeural",
|
||||
"is-IS": "GudrunNeural",
|
||||
"it-IT": "ElsaNeural",
|
||||
"ja-JP": "NanamiNeural",
|
||||
"jv-ID": "SitiNeural",
|
||||
"ka-GE": "EkaNeural",
|
||||
"kk-KZ": "AigulNeural",
|
||||
"km-KH": "SreymomNeural",
|
||||
"kn-IN": "SapnaNeural",
|
||||
"ko-KR": "SunHiNeural",
|
||||
"lo-LA": "KeomanyNeural",
|
||||
"lt-LT": "OnaNeural",
|
||||
"lv-LV": "EveritaNeural",
|
||||
"mk-MK": "MarijaNeural",
|
||||
"ml-IN": "SobhanaNeural",
|
||||
"mn-MN": "BataaNeural",
|
||||
"mr-IN": "AarohiNeural",
|
||||
"ms-MY": "YasminNeural",
|
||||
"mt-MT": "GraceNeural",
|
||||
"my-MM": "NilarNeural",
|
||||
"nb-NO": "IselinNeural",
|
||||
"ne-NP": "HemkalaNeural",
|
||||
"nl-BE": "DenaNeural",
|
||||
"nl-NL": "ColetteNeural",
|
||||
"pl-PL": "AgnieszkaNeural",
|
||||
"ps-AF": "LatifaNeural",
|
||||
"pt-BR": "FranciscaNeural",
|
||||
"pt-PT": "RaquelNeural",
|
||||
"ro-RO": "AlinaNeural",
|
||||
"ru-RU": "SvetlanaNeural",
|
||||
"si-LK": "ThiliniNeural",
|
||||
"sk-SK": "ViktoriaNeural",
|
||||
"sl-SI": "PetraNeural",
|
||||
"so-SO": "UbaxNeural",
|
||||
"sq-AL": "AnilaNeural",
|
||||
"sr-RS": "SophieNeural",
|
||||
"su-ID": "TutiNeural",
|
||||
"sv-SE": "SofieNeural",
|
||||
"sw-KE": "ZuriNeural",
|
||||
"sw-TZ": "RehemaNeural",
|
||||
"ta-IN": "PallaviNeural",
|
||||
"ta-LK": "SaranyaNeural",
|
||||
"ta-MY": "KaniNeural",
|
||||
"ta-SG": "VenbaNeural",
|
||||
"te-IN": "ShrutiNeural",
|
||||
"th-TH": "AcharaNeural",
|
||||
"tr-TR": "EmelNeural",
|
||||
"uk-UA": "PolinaNeural",
|
||||
"ur-IN": "GulNeural",
|
||||
"ur-PK": "UzmaNeural",
|
||||
"uz-UZ": "MadinaNeural",
|
||||
"vi-VN": "HoaiMyNeural",
|
||||
"wuu-CN": "XiaotongNeural",
|
||||
"yue-CN": "XiaoMinNeural",
|
||||
"zh-CN": "XiaoxiaoNeural",
|
||||
"zh-CN-henan": "YundengNeural",
|
||||
"zh-CN-liaoning": "XiaobeiNeural",
|
||||
"zh-CN-shaanxi": "XiaoniNeural",
|
||||
"zh-CN-shandong": "YunxiangNeural",
|
||||
"zh-CN-sichuan": "YunxiNeural",
|
||||
"zh-HK": "HiuMaanNeural",
|
||||
"zh-TW": "HsiaoChenNeural",
|
||||
"zu-ZA": "ThandoNeural",
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -186,12 +336,13 @@ class CloudTTSEntity(TextToSpeechEntity):
|
||||
"""Load TTS from Home Assistant Cloud."""
|
||||
gender: Gender | str | None = options.get(ATTR_GENDER)
|
||||
gender = handle_deprecated_gender(self.hass, gender)
|
||||
original_voice: str | None = options.get(ATTR_VOICE)
|
||||
if original_voice is None and language == self._language:
|
||||
original_voice = self._voice
|
||||
original_voice: str = options.get(
|
||||
ATTR_VOICE,
|
||||
self._voice if language == self._language else DEFAULT_VOICES[language],
|
||||
)
|
||||
voice = handle_deprecated_voice(self.hass, original_voice)
|
||||
if voice not in TTS_VOICES[language]:
|
||||
default_voice = TTS_VOICES[language][0]
|
||||
default_voice = DEFAULT_VOICES[language]
|
||||
_LOGGER.debug(
|
||||
"Unsupported voice %s detected, falling back to default %s for %s",
|
||||
voice,
|
||||
@ -266,12 +417,13 @@ class CloudProvider(Provider):
|
||||
assert self.hass is not None
|
||||
gender: Gender | str | None = options.get(ATTR_GENDER)
|
||||
gender = handle_deprecated_gender(self.hass, gender)
|
||||
original_voice: str | None = options.get(ATTR_VOICE)
|
||||
if original_voice is None and language == self._language:
|
||||
original_voice = self._voice
|
||||
original_voice: str = options.get(
|
||||
ATTR_VOICE,
|
||||
self._voice if language == self._language else DEFAULT_VOICES[language],
|
||||
)
|
||||
voice = handle_deprecated_voice(self.hass, original_voice)
|
||||
if voice not in TTS_VOICES[language]:
|
||||
default_voice = TTS_VOICES[language][0]
|
||||
default_voice = DEFAULT_VOICES[language]
|
||||
_LOGGER.debug(
|
||||
"Unsupported voice %s detected, falling back to default %s for %s",
|
||||
voice,
|
||||
|
@ -12,7 +12,12 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.components.assist_pipeline.pipeline import STORAGE_KEY
|
||||
from homeassistant.components.cloud.const import DEFAULT_TTS_DEFAULT_VOICE, DOMAIN
|
||||
from homeassistant.components.cloud.tts import PLATFORM_SCHEMA, SUPPORT_LANGUAGES, Voice
|
||||
from homeassistant.components.cloud.tts import (
|
||||
DEFAULT_VOICES,
|
||||
PLATFORM_SCHEMA,
|
||||
SUPPORT_LANGUAGES,
|
||||
Voice,
|
||||
)
|
||||
from homeassistant.components.media_player import (
|
||||
ATTR_MEDIA_CONTENT_ID,
|
||||
DOMAIN as DOMAIN_MP,
|
||||
@ -61,6 +66,19 @@ def test_default_exists() -> None:
|
||||
assert DEFAULT_TTS_DEFAULT_VOICE[1] in TTS_VOICES[DEFAULT_TTS_DEFAULT_VOICE[0]]
|
||||
|
||||
|
||||
def test_all_languages_have_default() -> None:
|
||||
"""Test all languages have a default voice."""
|
||||
assert set(SUPPORT_LANGUAGES).difference(DEFAULT_VOICES) == set()
|
||||
assert set(DEFAULT_VOICES).difference(SUPPORT_LANGUAGES) == set()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("language", "voice"), DEFAULT_VOICES.items())
|
||||
def test_default_voice_is_valid(language: str, voice: str) -> None:
|
||||
"""Test that the default voice is valid."""
|
||||
assert language in TTS_VOICES
|
||||
assert voice in TTS_VOICES[language]
|
||||
|
||||
|
||||
def test_schema() -> None:
|
||||
"""Test schema."""
|
||||
assert "nl-NL" in SUPPORT_LANGUAGES
|
||||
|
Loading…
x
Reference in New Issue
Block a user