diff --git a/CODEOWNERS b/CODEOWNERS index 4293f3dad47..88d4278b691 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -86,7 +86,7 @@ homeassistant/components/gearbest/* @HerrHofrat homeassistant/components/gitter/* @fabaff homeassistant/components/glances/* @fabaff homeassistant/components/gntp/* @robbiet480 -homeassistant/components/google_cloud_tts/* @lufton +homeassistant/components/google_cloud/* @lufton homeassistant/components/google_translate/* @awarecan homeassistant/components/google_travel_time/* @robbiet480 homeassistant/components/googlehome/* @ludeeus diff --git a/homeassistant/components/google_cloud/__init__.py b/homeassistant/components/google_cloud/__init__.py new file mode 100644 index 00000000000..97b669245d2 --- /dev/null +++ b/homeassistant/components/google_cloud/__init__.py @@ -0,0 +1 @@ +"""The google_cloud component.""" diff --git a/homeassistant/components/google_cloud_tts/manifest.json b/homeassistant/components/google_cloud/manifest.json similarity index 82% rename from homeassistant/components/google_cloud_tts/manifest.json rename to homeassistant/components/google_cloud/manifest.json index 88ee433802b..dd8e19dde03 100644 --- a/homeassistant/components/google_cloud_tts/manifest.json +++ b/homeassistant/components/google_cloud/manifest.json @@ -1,7 +1,7 @@ { - "domain": "google_cloud_tts", + "domain": "google_cloud", "name": "Google Cloud TTS", - "documentation": "https://www.home-assistant.io/components/google_cloud_tts", + "documentation": "https://www.home-assistant.io/components/google_cloud", "requirements": [ "google-cloud-texttospeech==0.4.0" ], diff --git a/homeassistant/components/google_cloud_tts/tts.py b/homeassistant/components/google_cloud/tts.py similarity index 55% rename from homeassistant/components/google_cloud_tts/tts.py rename to homeassistant/components/google_cloud/tts.py index 9817e26fa8e..6fe3e385cb4 100644 --- a/homeassistant/components/google_cloud_tts/tts.py +++ b/homeassistant/components/google_cloud/tts.py @@ -10,68 +10,86 @@ import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -GENDERS = [ - 'Neutral', 'Female', 'Male', -] -DEFAULT_GENDER = GENDERS[0] - -SUPPORT_LANGUAGES = [ +SUPPORTED_LANGUAGES = [ 'en', 'da', 'nl', 'fr', 'de', 'it', 'ja', 'ko', 'nb', 'pl', 'pt', 'ru', 'sk', 'es', 'sv', 'tr', 'uk', ] -DEFAULT_LANG = SUPPORT_LANGUAGES[0] +DEFAULT_LANG = SUPPORTED_LANGUAGES[0] + +SUPPORTED_GENDERS = [ + 'Neutral', 'Female', 'Male', +] +DEFAULT_GENDER = SUPPORTED_GENDERS[0] +GENDERS_DICT = { + 'Neutral': texttospeech.enums.SsmlVoiceGender.NEUTRAL, + 'Female': texttospeech.enums.SsmlVoiceGender.FEMALE, + 'Male': texttospeech.enums.SsmlVoiceGender.MALE, +} + +SUPPORTED_ENCODINGS = [ + 'ogg', 'mp3', 'wav', +] +DEFAULT_ENCODING = SUPPORTED_ENCODINGS[0] +ENCODINGS_DICT = { + 'ogg': texttospeech.enums.AudioEncoding.OGG_OPUS, + 'mp3': texttospeech.enums.AudioEncoding.MP3, + 'wav': texttospeech.enums.AudioEncoding.LINEAR16, +} CONF_GENDER = 'gender' CONF_VOICE = 'voice' +CONF_ENCODING = 'encoding' CONF_KEY_FILE = 'key_file' SUPPORTED_OPTIONS = [ - CONF_VOICE, CONF_GENDER + CONF_VOICE, CONF_GENDER, CONF_ENCODING, ] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES), - vol.Optional(CONF_GENDER, default=DEFAULT_GENDER): vol.In(GENDERS), + vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORTED_LANGUAGES), + vol.Optional(CONF_GENDER, default=DEFAULT_GENDER): vol.In(SUPPORTED_GENDERS), vol.Optional(CONF_VOICE, default=''): cv.string, + vol.Optional(CONF_ENCODING, default=DEFAULT_ENCODING): cv.string, vol.Optional(CONF_KEY_FILE, default=''): cv.string, }) async def async_get_engine(hass, config): """Set up Google Cloud TTS component.""" + key_file = config[CONF_KEY_FILE] + if key_file: + key_file = hass.config.path(key_file) + if not os.path.isfile(key_file): + _LOGGER.error("API key file doesn't exist!") + return None + return GoogleCloudTTSProvider( hass, - config[CONF_KEY_FILE], + key_file, config[CONF_LANG], config[CONF_GENDER], - config[CONF_VOICE] + config[CONF_VOICE], + config[CONF_ENCODING] ) class GoogleCloudTTSProvider(Provider): """The Google Cloud TTS API provider.""" - def __init__(self, hass, key_file, lang, gender, voice): + def __init__(self, hass, key_file, lang, gender, voice, encoding): """Init Google Cloud TTS service.""" self.hass = hass + self.name = 'Google Cloud TTS' self._lang = lang self._gender = gender self._voice = voice - self.name = 'Google Cloud TTS' - path = hass.config.path(key_file) + self._encoding = encoding + if key_file: - if os.path.isfile(path): - self._client = texttospeech \ - .TextToSpeechClient.from_service_account_json(path) - else: - _LOGGER.error( - "GOOGLE_APPLICATION_CREDENTIALS file doesn't exist!" - ) + self._client = texttospeech \ + .TextToSpeechClient.from_service_account_json(key_file) else: self._client = texttospeech.TextToSpeechClient() - self.audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3 - ) @property def default_language(self): @@ -81,7 +99,7 @@ class GoogleCloudTTSProvider(Provider): @property def supported_languages(self): """Return list of supported languages.""" - return SUPPORT_LANGUAGES + return SUPPORTED_LANGUAGES @property def supported_options(self): @@ -95,33 +113,46 @@ class GoogleCloudTTSProvider(Provider): _language = language or self._lang _gender = self._gender _voice = self._voice + _encoding = self._encoding + if options: if CONF_GENDER in options: _gender = options[CONF_GENDER].lower().capitalize() if CONF_VOICE in options: _voice = options[CONF_VOICE] - voice = texttospeech.types.VoiceSelectionParams( - language_code=_language, - ssml_gender={ - 'Neutral': texttospeech.enums.SsmlVoiceGender.NEUTRAL, - 'Female': texttospeech.enums.SsmlVoiceGender.FEMALE, - 'Male': texttospeech.enums.SsmlVoiceGender.MALE, - }.get(_gender, DEFAULT_GENDER), - name=_voice - ) + if CONF_ENCODING in options: + _encoding = options[CONF_ENCODING].lower() + synthesis_input = texttospeech.types.SynthesisInput( text=message - ) + ) # pylint: disable=no-member + + voice = texttospeech.types.VoiceSelectionParams( + language_code=_language, + ssml_gender=GENDERS_DICT.get( + _gender, + DEFAULT_GENDER + ), + name=_voice + ) # pylint: disable=no-member + + audio_config = texttospeech.types.AudioConfig( + audio_encoding=ENCODINGS_DICT.get( + _encoding, + DEFAULT_ENCODING + ) + ) # pylint: disable=no-member + response = self._client.synthesize_speech( synthesis_input, voice, - self.audio_config + audio_config ) - return "mp3", response.audio_content + return _encoding, response.audio_content except asyncio.TimeoutError as ex: _LOGGER.error("Timeout for Google Cloud TTS call: %s", ex) - except Exception as ex: + except Exception as ex: # pylint: disable=broad-except _LOGGER.error("Error occured during Google Cloud TTS call: %s", ex) return None, None diff --git a/homeassistant/components/google_cloud_tts/__init__.py b/homeassistant/components/google_cloud_tts/__init__.py deleted file mode 100644 index 229189f087d..00000000000 --- a/homeassistant/components/google_cloud_tts/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""The google_cloud_tts component."""