1
0
mirror of https://github.com/home-assistant/core.git synced 2025-05-21 22:37:07 +00:00
Dara Adib e2daffc117
Fix exception handling in Microsoft TTS ()
pycsspeechtts uses the requests library, but Microsoft TTS previously
caught HTTPException from the standard library. This is changed to
catch requests.HTTPError and return `(None, None)` consistent with
other TTS integrations. This will properly raise HomeAssistantError
for display in the frontend.

Follow up to PR  which adds tests for Microsoft TTS.
2023-05-25 11:29:13 +02:00

128 lines
4.0 KiB
Python

"""Support for the Microsoft Cognitive Services text-to-speech service."""
import logging
from pycsspeechtts import pycsspeechtts
from requests.exceptions import HTTPError
import voluptuous as vol
from homeassistant.components.tts import CONF_LANG, PLATFORM_SCHEMA, Provider
from homeassistant.const import CONF_API_KEY, CONF_REGION, CONF_TYPE, PERCENTAGE
from homeassistant.generated.microsoft_tts import SUPPORTED_LANGUAGES
import homeassistant.helpers.config_validation as cv
CONF_GENDER = "gender"
CONF_OUTPUT = "output"
CONF_RATE = "rate"
CONF_VOLUME = "volume"
CONF_PITCH = "pitch"
CONF_CONTOUR = "contour"
_LOGGER = logging.getLogger(__name__)
GENDERS = ["Female", "Male"]
DEFAULT_LANG = "en-us"
DEFAULT_GENDER = "Female"
DEFAULT_TYPE = "JennyNeural"
DEFAULT_OUTPUT = "audio-24khz-96kbitrate-mono-mp3"
DEFAULT_RATE = 0
DEFAULT_VOLUME = 0
DEFAULT_PITCH = "default"
DEFAULT_CONTOUR = ""
DEFAULT_REGION = "eastus"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORTED_LANGUAGES),
vol.Optional(CONF_GENDER, default=DEFAULT_GENDER): vol.In(GENDERS),
vol.Optional(CONF_TYPE, default=DEFAULT_TYPE): cv.string,
vol.Optional(CONF_RATE, default=DEFAULT_RATE): vol.All(
vol.Coerce(int), vol.Range(-100, 100)
),
vol.Optional(CONF_VOLUME, default=DEFAULT_VOLUME): vol.All(
vol.Coerce(int), vol.Range(-100, 100)
),
vol.Optional(CONF_PITCH, default=DEFAULT_PITCH): cv.string,
vol.Optional(CONF_CONTOUR, default=DEFAULT_CONTOUR): cv.string,
vol.Optional(CONF_REGION, default=DEFAULT_REGION): cv.string,
}
)
def get_engine(hass, config, discovery_info=None):
"""Set up Microsoft speech component."""
return MicrosoftProvider(
config[CONF_API_KEY],
config[CONF_LANG],
config[CONF_GENDER],
config[CONF_TYPE],
config[CONF_RATE],
config[CONF_VOLUME],
config[CONF_PITCH],
config[CONF_CONTOUR],
config[CONF_REGION],
)
class MicrosoftProvider(Provider):
"""The Microsoft speech API provider."""
def __init__(
self, apikey, lang, gender, ttype, rate, volume, pitch, contour, region
):
"""Init Microsoft TTS service."""
self._apikey = apikey
self._lang = lang
self._gender = gender
self._type = ttype
self._output = DEFAULT_OUTPUT
self._rate = f"{rate}{PERCENTAGE}"
self._volume = f"{volume}{PERCENTAGE}"
self._pitch = pitch
self._contour = contour
self._region = region
self.name = "Microsoft"
@property
def default_language(self):
"""Return the default language."""
return self._lang
@property
def supported_languages(self):
"""Return list of supported languages."""
return SUPPORTED_LANGUAGES
@property
def supported_options(self):
"""Return list of supported options like voice, emotion."""
return [CONF_GENDER, CONF_TYPE]
@property
def default_options(self):
"""Return a dict include default options."""
return {CONF_GENDER: self._gender, CONF_TYPE: self._type}
def get_tts_audio(self, message, language, options):
"""Load TTS from Microsoft."""
if language is None:
language = self._lang
try:
trans = pycsspeechtts.TTSTranslator(self._apikey, self._region)
data = trans.speak(
language=language,
gender=options[CONF_GENDER],
voiceType=options[CONF_TYPE],
output=self._output,
rate=self._rate,
volume=self._volume,
pitch=self._pitch,
contour=self._contour,
text=message,
)
except HTTPError as ex:
_LOGGER.error("Error occurred for Microsoft TTS: %s", ex)
return (None, None)
return ("mp3", data)