diff --git a/custom_components/watson_tts/manifest.json b/custom_components/watson_tts/manifest.json index d40baac..b2a19ec 100644 --- a/custom_components/watson_tts/manifest.json +++ b/custom_components/watson_tts/manifest.json @@ -3,7 +3,7 @@ "name": "IBM Watson TTS", "documentation": "https://www.home-assistant.io/components/watson_tts", "requirements": [ - "ibm-watson==3.0.3" + "ibm-watson==4.0.1" ], "dependencies": [], "codeowners": [ diff --git a/custom_components/watson_tts/tts.py b/custom_components/watson_tts/tts.py index f34c094..8a910d1 100644 --- a/custom_components/watson_tts/tts.py +++ b/custom_components/watson_tts/tts.py @@ -1,6 +1,8 @@ """Support for IBM Watson TTS integration.""" import logging +from ibm_watson import TextToSpeechV1 +from ibm_cloud_sdk_core.authenticators import IAMAuthenticator import voluptuous as vol from homeassistant.components.tts import PLATFORM_SCHEMA, Provider @@ -8,103 +10,111 @@ import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -CONF_URL = 'watson_url' -CONF_APIKEY = 'watson_apikey' -ATTR_CREDENTIALS = 'credentials' +CONF_URL = "watson_url" +CONF_APIKEY = "watson_apikey" +ATTR_CREDENTIALS = "credentials" -DEFAULT_URL = 'https://stream.watsonplatform.net/text-to-speech/api' +DEFAULT_URL = "https://stream.watsonplatform.net/text-to-speech/api" -CONF_VOICE = 'voice' -CONF_OUTPUT_FORMAT = 'output_format' +CONF_VOICE = "voice" +CONF_OUTPUT_FORMAT = "output_format" CONF_OUTPUT_AUDIO_RATE = 'output_audio_rate' -CONF_TEXT_TYPE = 'text' +CONF_TEXT_TYPE = "text" # List from https://tinyurl.com/watson-tts-docs SUPPORTED_VOICES = [ "de-DE_BirgitVoice", "de-DE_BirgitV2Voice", + "de-DE_BirgitV3Voice", "de-DE_DieterVoice", "de-DE_DieterV2Voice", + "de-DE_DieterV3Voice", "en-GB_KateVoice", + "en-GB_KateV3Voice", "en-US_AllisonVoice", "en-US_AllisonV2Voice", + "en-US_AllisonV3Voice", "en-US_LisaVoice", "en-US_LisaV2Voice", + "en-US_LisaV3Voice", "en-US_MichaelVoice", "en-US_MichaelV2Voice", + "en-US_MichaelV3Voice", "es-ES_EnriqueVoice", + "es-ES_EnriqueV3Voice", "es-ES_LauraVoice", + "es-ES_LauraV3Voice", "es-LA_SofiaVoice", + "es-LA_SofiaV3Voice", "es-US_SofiaVoice", + "es-US_SofiaV3Voice", "fr-FR_ReneeVoice", + "fr-FR_ReneeV3Voice", "it-IT_FrancescaVoice", "it-IT_FrancescaV2Voice", + "it-IT_FrancescaV3Voice", "ja-JP_EmiVoice", - "pt-BR_IsabelaVoice" + "pt-BR_IsabelaVoice", + "pt-BR_IsabelaV3Voice", ] SUPPORTED_OUTPUT_FORMATS = [ - 'audio/flac', - 'audio/mp3', - 'audio/mpeg', - 'audio/ogg', - 'audio/ogg;codecs=opus', - 'audio/ogg;codecs=vorbis', - 'audio/wav' + "audio/flac", + "audio/mp3", + "audio/mpeg", + "audio/ogg", + "audio/ogg;codecs=opus", + "audio/ogg;codecs=vorbis", + "audio/wav", ] CONTENT_TYPE_EXTENSIONS = { - 'audio/flac': 'flac', - 'audio/mp3': 'mp3', - 'audio/mpeg': 'mp3', - 'audio/ogg': 'ogg', - 'audio/ogg;codecs=opus': 'ogg', - 'audio/ogg;codecs=vorbis': 'ogg', - 'audio/wav': 'wav', + "audio/flac": "flac", + "audio/mp3": "mp3", + "audio/mpeg": "mp3", + "audio/ogg": "ogg", + "audio/ogg;codecs=opus": "ogg", + "audio/ogg;codecs=vorbis": "ogg", + "audio/wav": "wav", } -DEFAULT_VOICE = 'en-US_AllisonVoice' -DEFAULT_OUTPUT_FORMAT = 'audio/mp3' +DEFAULT_VOICE = "en-US_AllisonVoice" +DEFAULT_OUTPUT_FORMAT = "audio/mp3" + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( + { + vol.Optional(CONF_URL, default=DEFAULT_URL): cv.string, + vol.Required(CONF_APIKEY): cv.string, + vol.Optional(CONF_VOICE, default=DEFAULT_VOICE): vol.In(SUPPORTED_VOICES), + vol.Optional(CONF_OUTPUT_FORMAT, default=DEFAULT_OUTPUT_FORMAT): vol.In( + SUPPORTED_OUTPUT_FORMATS + ), + vol.Optional(CONF_OUTPUT_AUDIO_RATE): cv.positive_int, + } +) -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_URL, default=DEFAULT_URL): cv.string, - vol.Required(CONF_APIKEY): cv.string, - vol.Optional(CONF_VOICE, default=DEFAULT_VOICE): vol.In(SUPPORTED_VOICES), - vol.Optional(CONF_OUTPUT_FORMAT, default=DEFAULT_OUTPUT_FORMAT): - vol.In(SUPPORTED_OUTPUT_FORMATS), - vol.Optional(CONF_OUTPUT_AUDIO_RATE): cv.positive_int, -}) - - -def get_engine(hass, config): +def get_engine(hass, config, discovery_info=None): """Set up IBM Watson TTS component.""" - from ibm_watson import TextToSpeechV1 - service = TextToSpeechV1( - url=config[CONF_URL], - iam_apikey=config[CONF_APIKEY] - ) + authenticator = IAMAuthenticator(config[CONF_APIKEY]) + service = TextToSpeechV1(authenticator) + service.set_service_url(config[CONF_URL]) supported_languages = list({s[:5] for s in SUPPORTED_VOICES}) default_voice = config[CONF_VOICE] output_format = config[CONF_OUTPUT_FORMAT] output_audio_rate = config.get(CONF_OUTPUT_AUDIO_RATE, None) - return WatsonTTSProvider( - service, supported_languages, default_voice, - output_format, output_audio_rate) + service.set_default_headers({"x-watson-learning-opt-out": "true"}) + + return WatsonTTSProvider(service, supported_languages, default_voice, output_format, output_audio_rate) class WatsonTTSProvider(Provider): """IBM Watson TTS api provider.""" - def __init__(self, - service, - supported_languages, - default_voice, - output_format, - output_audio_rate): + def __init__(self, service, supported_languages, default_voice, output_format, output_audio_rate): """Initialize Watson TTS provider.""" self.service = service self.supported_langs = supported_languages @@ -112,7 +122,7 @@ class WatsonTTSProvider(Provider): self.default_voice = default_voice self.output_format = output_format self.output_audio_rate = output_audio_rate - self.name = 'Watson TTS' + self.name = "Watson TTS" @property def supported_languages(self): @@ -141,8 +151,7 @@ class WatsonTTSProvider(Provider): output_format += f";rate={self.output_audio_rate}" response = self.service.synthesize( - message, accept=output_format, - voice=self.default_voice).get_result() + message, accept=output_format, voice=self.default_voice + ).get_result() - return (CONTENT_TYPE_EXTENSIONS[self.output_format], - response.content) + return (CONTENT_TYPE_EXTENSIONS[self.output_format], response.content)