Home Assistant Unofficial Reference 2024.12.1
tts.py
Go to the documentation of this file.
1 """Support for the voicerss speech service."""
2 
3 import asyncio
4 from http import HTTPStatus
5 import logging
6 
7 import aiohttp
8 import voluptuous as vol
9 
10 from homeassistant.components.tts import (
11  CONF_LANG,
12  PLATFORM_SCHEMA as TTS_PLATFORM_SCHEMA,
13  Provider,
14 )
15 from homeassistant.const import CONF_API_KEY
16 from homeassistant.helpers.aiohttp_client import async_get_clientsession
18 
19 _LOGGER = logging.getLogger(__name__)
20 
21 VOICERSS_API_URL = "https://api.voicerss.org/"
22 
23 ERROR_MSG = [
24  b"Error description",
25  b"The subscription is expired or requests count limitation is exceeded!",
26  b"The request content length is too large!",
27  b"The language does not support!",
28  b"The language is not specified!",
29  b"The text is not specified!",
30  b"The API key is not available!",
31  b"The API key is not specified!",
32  b"The subscription does not support SSML!",
33 ]
34 
35 SUPPORT_LANGUAGES = [
36  "ar-eg",
37  "ar-sa",
38  "bg-bg",
39  "ca-es",
40  "zh-cn",
41  "zh-hk",
42  "zh-tw",
43  "hr-hr",
44  "cs-cz",
45  "da-dk",
46  "nl-be",
47  "nl-nl",
48  "en-au",
49  "en-ca",
50  "en-gb",
51  "en-in",
52  "en-ie",
53  "en-us",
54  "fi-fi",
55  "fr-ca",
56  "fr-fr",
57  "fr-ch",
58  "de-at",
59  "de-de",
60  "de-ch",
61  "el-gr",
62  "he-il",
63  "hi-in",
64  "hu-hu",
65  "id-id",
66  "it-it",
67  "ja-jp",
68  "ko-kr",
69  "ms-my",
70  "nb-no",
71  "pl-pl",
72  "pt-br",
73  "pt-pt",
74  "ro-ro",
75  "ru-ru",
76  "sk-sk",
77  "sl-si",
78  "es-mx",
79  "es-es",
80  "sv-se",
81  "ta-in",
82  "th-th",
83  "tr-tr",
84  "vi-vn",
85 ]
86 
87 SUPPORT_CODECS = ["mp3", "wav", "aac", "ogg", "caf"] # codespell:ignore caf
88 
89 SUPPORT_FORMATS = [
90  "8khz_8bit_mono",
91  "8khz_8bit_stereo",
92  "8khz_16bit_mono",
93  "8khz_16bit_stereo",
94  "11khz_8bit_mono",
95  "11khz_8bit_stereo",
96  "11khz_16bit_mono",
97  "11khz_16bit_stereo",
98  "12khz_8bit_mono",
99  "12khz_8bit_stereo",
100  "12khz_16bit_mono",
101  "12khz_16bit_stereo",
102  "16khz_8bit_mono",
103  "16khz_8bit_stereo",
104  "16khz_16bit_mono",
105  "16khz_16bit_stereo",
106  "22khz_8bit_mono",
107  "22khz_8bit_stereo",
108  "22khz_16bit_mono",
109  "22khz_16bit_stereo",
110  "24khz_8bit_mono",
111  "24khz_8bit_stereo",
112  "24khz_16bit_mono",
113  "24khz_16bit_stereo",
114  "32khz_8bit_mono",
115  "32khz_8bit_stereo",
116  "32khz_16bit_mono",
117  "32khz_16bit_stereo",
118  "44khz_8bit_mono",
119  "44khz_8bit_stereo",
120  "44khz_16bit_mono",
121  "44khz_16bit_stereo",
122  "48khz_8bit_mono",
123  "48khz_8bit_stereo",
124  "48khz_16bit_mono",
125  "48khz_16bit_stereo",
126  "alaw_8khz_mono",
127  "alaw_8khz_stereo",
128  "alaw_11khz_mono",
129  "alaw_11khz_stereo",
130  "alaw_22khz_mono",
131  "alaw_22khz_stereo",
132  "alaw_44khz_mono",
133  "alaw_44khz_stereo",
134  "ulaw_8khz_mono",
135  "ulaw_8khz_stereo",
136  "ulaw_11khz_mono",
137  "ulaw_11khz_stereo",
138  "ulaw_22khz_mono",
139  "ulaw_22khz_stereo",
140  "ulaw_44khz_mono",
141  "ulaw_44khz_stereo",
142 ]
143 
144 CONF_CODEC = "codec"
145 CONF_FORMAT = "format"
146 
147 DEFAULT_LANG = "en-us"
148 DEFAULT_CODEC = "mp3"
149 DEFAULT_FORMAT = "8khz_8bit_mono"
150 
151 
152 PLATFORM_SCHEMA = TTS_PLATFORM_SCHEMA.extend(
153  {
154  vol.Required(CONF_API_KEY): cv.string,
155  vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES),
156  vol.Optional(CONF_CODEC, default=DEFAULT_CODEC): vol.In(SUPPORT_CODECS),
157  vol.Optional(CONF_FORMAT, default=DEFAULT_FORMAT): vol.In(SUPPORT_FORMATS),
158  }
159 )
160 
161 
162 async def async_get_engine(hass, config, discovery_info=None):
163  """Set up VoiceRSS TTS component."""
164  return VoiceRSSProvider(hass, config)
165 
166 
168  """The VoiceRSS speech API provider."""
169 
170  def __init__(self, hass, conf):
171  """Init VoiceRSS TTS service."""
172  self.hasshass = hass
173  self._extension_extension = conf[CONF_CODEC]
174  self._lang_lang = conf[CONF_LANG]
175  self.namename = "VoiceRSS"
176 
177  self._form_data_form_data = {
178  "key": conf[CONF_API_KEY],
179  "hl": conf[CONF_LANG],
180  "c": (conf[CONF_CODEC]).upper(),
181  "f": conf[CONF_FORMAT],
182  }
183 
184  @property
185  def default_language(self):
186  """Return the default language."""
187  return self._lang_lang
188 
189  @property
191  """Return list of supported languages."""
192  return SUPPORT_LANGUAGES
193 
194  async def async_get_tts_audio(self, message, language, options):
195  """Load TTS from VoiceRSS."""
196  websession = async_get_clientsession(self.hasshass)
197  form_data = self._form_data_form_data.copy()
198 
199  form_data["src"] = message
200  form_data["hl"] = language
201 
202  try:
203  async with asyncio.timeout(10):
204  request = await websession.post(VOICERSS_API_URL, data=form_data)
205 
206  if request.status != HTTPStatus.OK:
207  _LOGGER.error(
208  "Error %d on load url %s", request.status, request.url
209  )
210  return (None, None)
211  data = await request.read()
212 
213  if data in ERROR_MSG:
214  _LOGGER.error("Error receive %s from VoiceRSS", str(data, "utf-8"))
215  return (None, None)
216 
217  except (TimeoutError, aiohttp.ClientError):
218  _LOGGER.error("Timeout for VoiceRSS API")
219  return (None, None)
220 
221  return (self._extension_extension, data)
def async_get_tts_audio(self, message, language, options)
Definition: tts.py:194
def async_get_engine(hass, config, discovery_info=None)
Definition: tts.py:162
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)