189 lines
5.1 KiB
Python
189 lines
5.1 KiB
Python
"""Support for IBM Watson TTS integration."""
|
|
|
|
import logging
|
|
|
|
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
|
|
from ibm_watson import TextToSpeechV1
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components.tts import PLATFORM_SCHEMA, Provider
|
|
import homeassistant.helpers.config_validation as cv
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
CONF_URL = "watson_url"
|
|
CONF_APIKEY = "watson_apikey"
|
|
|
|
DEFAULT_URL = "https://api.us-south.text-to-speech.watson.cloud.ibm.com"
|
|
|
|
CONF_VOICE = "voice"
|
|
CONF_OUTPUT_FORMAT = "output_format"
|
|
CONF_TEXT_TYPE = "text"
|
|
|
|
# List from https://tinyurl.com/watson-tts-docs
|
|
SUPPORTED_VOICES = [
|
|
"de-DE_BirgitV2Voice",
|
|
"de-DE_BirgitV3Voice",
|
|
"de-DE_BirgitVoice",
|
|
"de-DE_DieterV2Voice",
|
|
"de-DE_DieterV3Voice",
|
|
"de-DE_DieterVoice",
|
|
"de-DE_ErikaV3Voice",
|
|
"en-AU_HeidiExpressive",
|
|
"en-AU_JackExpressive",
|
|
"en-GB_CharlotteV3Voice",
|
|
"en-GB_JamesV3Voice",
|
|
"en-GB_KateV3Voice",
|
|
"en-GB_KateVoice",
|
|
"en-US_AllisonExpressive",
|
|
"en-US_AllisonV2Voice",
|
|
"en-US_AllisonV3Voice",
|
|
"en-US_AllisonVoice",
|
|
"en-US_EmilyV3Voice",
|
|
"en-US_EmmaExpressive",
|
|
"en-US_HenryV3Voice",
|
|
"en-US_KevinV3Voice",
|
|
"en-US_LisaExpressive",
|
|
"en-US_LisaV2Voice",
|
|
"en-US_LisaV3Voice",
|
|
"en-US_LisaVoice",
|
|
"en-US_MichaelExpressive",
|
|
"en-US_MichaelV2Voice",
|
|
"en-US_MichaelV3Voice",
|
|
"en-US_MichaelVoice",
|
|
"en-US_OliviaV3Voice",
|
|
"es-ES_EnriqueV3Voice",
|
|
"es-ES_EnriqueVoice",
|
|
"es-ES_LauraV3Voice",
|
|
"es-ES_LauraVoice",
|
|
"es-LA_SofiaV3Voice",
|
|
"es-LA_SofiaVoice",
|
|
"es-US_SofiaV3Voice",
|
|
"es-US_SofiaVoice",
|
|
"fr-CA_LouiseV3Voice",
|
|
"fr-FR_NicolasV3Voice",
|
|
"fr-FR_ReneeV3Voice",
|
|
"fr-FR_ReneeVoice",
|
|
"it-IT_FrancescaV2Voice",
|
|
"it-IT_FrancescaV3Voice",
|
|
"it-IT_FrancescaVoice",
|
|
"ja-JP_EmiV3Voice",
|
|
"ja-JP_EmiVoice",
|
|
"ko-KR_JinV3Voice",
|
|
"nl-NL_MerelV3Voice",
|
|
"pt-BR_IsabelaV3Voice",
|
|
"pt-BR_IsabelaVoice",
|
|
]
|
|
|
|
DEPRECATED_VOICES = [
|
|
"de-DE_BirgitVoice",
|
|
"de-DE_DieterVoice",
|
|
"en-US_AllisonVoice",
|
|
"en-US_LisaVoice",
|
|
"en-US_MichaelVoice",
|
|
"es-ES_EnriqueVoice",
|
|
"es-ES_LauraVoice",
|
|
"es-LA_SofiaVoice",
|
|
"es-US_SofiaVoice",
|
|
"fr-FR_ReneeVoice",
|
|
"it-IT_FrancescaVoice",
|
|
"ja-JP_EmiVoice",
|
|
"pt-BR_IsabelaVoice",
|
|
]
|
|
|
|
SUPPORTED_OUTPUT_FORMATS = [
|
|
"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",
|
|
}
|
|
|
|
DEFAULT_VOICE = "en-US_AllisonV3Voice"
|
|
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
|
|
),
|
|
}
|
|
)
|
|
|
|
|
|
def get_engine(hass, config, discovery_info=None):
|
|
"""Set up IBM Watson TTS component."""
|
|
|
|
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]
|
|
service.set_default_headers({"x-watson-learning-opt-out": "true"})
|
|
|
|
if default_voice in DEPRECATED_VOICES:
|
|
_LOGGER.warning(
|
|
"Watson TTS voice %s is deprecated, it may be removed in the future",
|
|
default_voice,
|
|
)
|
|
|
|
return WatsonTTSProvider(service, supported_languages, default_voice, output_format)
|
|
|
|
|
|
class WatsonTTSProvider(Provider):
|
|
"""IBM Watson TTS api provider."""
|
|
|
|
def __init__(self, service, supported_languages, default_voice, output_format):
|
|
"""Initialize Watson TTS provider."""
|
|
self.service = service
|
|
self.supported_langs = supported_languages
|
|
self.default_lang = default_voice[:5]
|
|
self.default_voice = default_voice
|
|
self.output_format = output_format
|
|
self.name = "Watson TTS"
|
|
|
|
@property
|
|
def supported_languages(self):
|
|
"""Return a list of supported languages."""
|
|
return self.supported_langs
|
|
|
|
@property
|
|
def default_language(self):
|
|
"""Return the default language."""
|
|
return self.default_lang
|
|
|
|
@property
|
|
def default_options(self):
|
|
"""Return dict include default options."""
|
|
return {CONF_VOICE: self.default_voice}
|
|
|
|
@property
|
|
def supported_options(self):
|
|
"""Return a list of supported options."""
|
|
return [CONF_VOICE]
|
|
|
|
def get_tts_audio(self, message, language, options):
|
|
"""Request TTS file from Watson TTS."""
|
|
response = self.service.synthesize(
|
|
text=message, accept=self.output_format, voice=options[CONF_VOICE]
|
|
).get_result()
|
|
|
|
return (CONTENT_TYPE_EXTENSIONS[self.output_format], response.content)
|