Changed options validation
This commit is contained in:
parent
e0274df41c
commit
b3e66ad42f
1 changed files with 59 additions and 42 deletions
|
@ -1,11 +1,12 @@
|
||||||
"""Support for the Google Cloud TTS service."""
|
"""Support for the Google Cloud TTS service."""
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from google.cloud import texttospeech
|
from google.cloud import texttospeech
|
||||||
|
|
||||||
from homeassistant.components.tts import CONF_LANG, PLATFORM_SCHEMA, Provider
|
from homeassistant.components.tts import CONF_LANG, PLATFORM_SCHEMA, Provider
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
@ -67,28 +68,42 @@ SUPPORTED_OPTIONS = [
|
||||||
CONF_PROFILES,
|
CONF_PROFILES,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
GENDER_SCHEMA = vol.All(
|
||||||
|
vol.Upper,
|
||||||
|
vol.In(texttospeech.enums.SsmlVoiceGender.__members__)
|
||||||
|
)
|
||||||
|
VOICE_SCHEMA = cv.matches_regex(VOICE_REGEX)
|
||||||
|
SCHEMA_ENCODING = vol.All(
|
||||||
|
vol.Upper,
|
||||||
|
vol.In(texttospeech.enums.AudioEncoding.__members__)
|
||||||
|
)
|
||||||
|
SPEED_SCHEMA = vol.All(
|
||||||
|
vol.Coerce(float),
|
||||||
|
vol.Clamp(min=MIN_SPEED, max=MAX_SPEED)
|
||||||
|
)
|
||||||
|
PITCH_SCHEMA = vol.All(
|
||||||
|
vol.Coerce(float),
|
||||||
|
vol.Clamp(min=MIN_PITCH, max=MAX_PITCH)
|
||||||
|
)
|
||||||
|
GAIN_SCHEMA = vol.All(
|
||||||
|
vol.Coerce(float),
|
||||||
|
vol.Clamp(min=MIN_GAIN, max=MAX_GAIN)
|
||||||
|
)
|
||||||
|
PROFILES_SCHEMA = vol.All(
|
||||||
|
cv.ensure_list,
|
||||||
|
[vol.In(SUPPORTED_PROFILES)]
|
||||||
|
)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Optional(CONF_KEY_FILE): cv.string,
|
vol.Optional(CONF_KEY_FILE): cv.string,
|
||||||
vol.Optional(CONF_LANG, default=DEFAULT_LANG):
|
vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORTED_LANGUAGES),
|
||||||
vol.In(SUPPORTED_LANGUAGES),
|
vol.Optional(CONF_GENDER, default=DEFAULT_GENDER): GENDER_SCHEMA,
|
||||||
vol.Optional(CONF_GENDER, default=DEFAULT_GENDER):
|
vol.Optional(CONF_VOICE, default=DEFAULT_VOICE): VOICE_SCHEMA,
|
||||||
vol.All(vol.Upper, vol.In(
|
vol.Optional(CONF_ENCODING, default=DEFAULT_ENCODING): SCHEMA_ENCODING,
|
||||||
texttospeech.enums.SsmlVoiceGender.__members__
|
vol.Optional(CONF_SPEED, default=DEFAULT_SPEED): SPEED_SCHEMA,
|
||||||
)),
|
vol.Optional(CONF_PITCH, default=DEFAULT_PITCH): PITCH_SCHEMA,
|
||||||
vol.Optional(CONF_VOICE, default=DEFAULT_VOICE):
|
vol.Optional(CONF_GAIN, default=DEFAULT_GAIN): GAIN_SCHEMA,
|
||||||
cv.matches_regex(VOICE_REGEX),
|
vol.Optional(CONF_PROFILES, default=[]): PROFILES_SCHEMA,
|
||||||
vol.Optional(CONF_ENCODING, default=DEFAULT_ENCODING):
|
|
||||||
vol.All(vol.Upper, vol.In(
|
|
||||||
texttospeech.enums.AudioEncoding.__members__
|
|
||||||
)),
|
|
||||||
vol.Optional(CONF_SPEED, default=DEFAULT_SPEED):
|
|
||||||
vol.All(vol.Coerce(float), vol.Clamp(min=MIN_SPEED, max=MAX_SPEED)),
|
|
||||||
vol.Optional(CONF_PITCH, default=DEFAULT_PITCH):
|
|
||||||
vol.All(vol.Coerce(float), vol.Clamp(min=MIN_PITCH, max=MAX_PITCH)),
|
|
||||||
vol.Optional(CONF_GAIN, default=DEFAULT_GAIN):
|
|
||||||
vol.All(vol.Coerce(float), vol.Clamp(min=MIN_GAIN, max=MAX_GAIN)),
|
|
||||||
vol.Optional(CONF_PROFILES, default=[]):
|
|
||||||
vol.All(cv.ensure_list, [vol.In(SUPPORTED_PROFILES)]),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,25 +194,23 @@ class GoogleCloudTTSProvider(Provider):
|
||||||
|
|
||||||
async def async_get_tts_audio(self, message, language, options=None):
|
async def async_get_tts_audio(self, message, language, options=None):
|
||||||
"""Load TTS from google."""
|
"""Load TTS from google."""
|
||||||
_gender = options.get(CONF_GENDER).upper()
|
options_schema = vol.Schema({
|
||||||
if _gender not in texttospeech.enums.SsmlVoiceGender.__members__:
|
vol.Optional(CONF_GENDER, default=self._gender): GENDER_SCHEMA,
|
||||||
_gender = self._gender
|
vol.Optional(CONF_VOICE, default=self._voice): VOICE_SCHEMA,
|
||||||
|
vol.Optional(CONF_ENCODING, default=DEFAULT_ENCODING):
|
||||||
|
SCHEMA_ENCODING,
|
||||||
|
vol.Optional(CONF_SPEED, default=self._speed): SPEED_SCHEMA,
|
||||||
|
vol.Optional(CONF_PITCH, default=self._speed): SPEED_SCHEMA,
|
||||||
|
vol.Optional(CONF_GAIN, default=DEFAULT_GAIN): GAIN_SCHEMA,
|
||||||
|
vol.Optional(CONF_PROFILES, default=[]): PROFILES_SCHEMA,
|
||||||
|
})
|
||||||
|
options = options_schema(options)
|
||||||
|
|
||||||
_voice = options.get(CONF_VOICE) or self._voice
|
_encoding = options[CONF_ENCODING]
|
||||||
if not re.match(VOICE_REGEX, _voice):
|
_voice = options[CONF_VOICE]
|
||||||
_voice = self._voice
|
|
||||||
if _voice and not _voice.startswith(language):
|
if _voice and not _voice.startswith(language):
|
||||||
language = _voice[:5]
|
language = _voice[:5]
|
||||||
|
|
||||||
_encoding = options.get(CONF_ENCODING).upper()
|
|
||||||
if _encoding not in texttospeech.enums.AudioEncoding.__members__:
|
|
||||||
_encoding = self._encoding
|
|
||||||
|
|
||||||
_speed = options.get(CONF_SPEED)
|
|
||||||
_pitch = options.get(CONF_PITCH)
|
|
||||||
_gain = options.get(CONF_GAIN)
|
|
||||||
_profiles = options.get(CONF_PROFILES)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
synthesis_input = texttospeech.types.SynthesisInput(
|
synthesis_input = texttospeech.types.SynthesisInput(
|
||||||
|
@ -206,16 +219,18 @@ class GoogleCloudTTSProvider(Provider):
|
||||||
|
|
||||||
voice = texttospeech.types.VoiceSelectionParams(
|
voice = texttospeech.types.VoiceSelectionParams(
|
||||||
language_code=language,
|
language_code=language,
|
||||||
ssml_gender=texttospeech.enums.SsmlVoiceGender[_gender],
|
ssml_gender=texttospeech.enums.SsmlVoiceGender[
|
||||||
|
options[CONF_GENDER]
|
||||||
|
],
|
||||||
name=_voice
|
name=_voice
|
||||||
)
|
)
|
||||||
|
|
||||||
audio_config = texttospeech.types.AudioConfig(
|
audio_config = texttospeech.types.AudioConfig(
|
||||||
audio_encoding=texttospeech.enums.AudioEncoding[_encoding],
|
audio_encoding=texttospeech.enums.AudioEncoding[_encoding],
|
||||||
speaking_rate=max(min(_speed, MAX_SPEED), MIN_SPEED),
|
speaking_rate=options.get(CONF_SPEED),
|
||||||
pitch=max(min(_pitch, MAX_PITCH), MIN_PITCH),
|
pitch=options.get(CONF_PITCH),
|
||||||
volume_gain_db=max(min(_gain, MAX_GAIN), MIN_GAIN),
|
volume_gain_db=options.get(CONF_GAIN),
|
||||||
effects_profile_id=_profiles or [],
|
effects_profile_id=options.get(CONF_PROFILES),
|
||||||
)
|
)
|
||||||
# pylint: enable=no-member
|
# pylint: enable=no-member
|
||||||
|
|
||||||
|
@ -231,6 +246,8 @@ class GoogleCloudTTSProvider(Provider):
|
||||||
except asyncio.TimeoutError as ex:
|
except asyncio.TimeoutError as ex:
|
||||||
_LOGGER.error("Timeout for Google Cloud TTS call: %s", ex)
|
_LOGGER.error("Timeout for Google Cloud TTS call: %s", ex)
|
||||||
except Exception as ex: # pylint: disable=broad-except
|
except Exception as ex: # pylint: disable=broad-except
|
||||||
_LOGGER.error("Error occured during Google Cloud TTS call: %s", ex)
|
_LOGGER.exception(
|
||||||
|
"Error occured during Google Cloud TTS call: %s", ex
|
||||||
|
)
|
||||||
|
|
||||||
return None, None
|
return None, None
|
||||||
|
|
Loading…
Add table
Reference in a new issue