根据官网代码规范优化结构,精简代码。使用reconfigure模式支持重设参数。增加多实例支持。去掉debug信息。

This commit is contained in:
Howell Jiang
2025-04-18 15:42:59 +08:00
parent c8415edaeb
commit 2d3f8cd3b0
12 changed files with 129 additions and 200 deletions
+4 -5
View File
@@ -20,18 +20,17 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""设置百度语音配置项.""" """设置百度语音配置项."""
# 存储配置数据
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN] = entry.data.copy() # 保存所有配置数据
# 加载平台 hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN] = entry.data.copy()
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""卸载百度语音配置项.""" """卸载百度语音配置项."""
# 卸载平台
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok: if unload_ok:
+40 -94
View File
@@ -1,4 +1,4 @@
"""Config flow for Baidu TTS integration.""" """Config flow for Baidu Voice integration."""
from __future__ import annotations from __future__ import annotations
@@ -7,13 +7,12 @@ from typing import Any
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ( from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
ConfigEntry, from homeassistant.helpers.selector import (
ConfigFlow, SelectSelector,
ConfigFlowResult, SelectSelectorConfig,
OptionsFlow, SelectSelectorMode,
) )
from homeassistant.core import callback
from .const import ( from .const import (
CONF_API_KEY, CONF_API_KEY,
@@ -62,6 +61,9 @@ STEP_USER_DATA_SCHEMA = vol.Schema(
vol.Optional(TTS_CONF_VOICE, default=TTS_DEFAULT_VOICE): vol.In( vol.Optional(TTS_CONF_VOICE, default=TTS_DEFAULT_VOICE): vol.In(
TTS_SUPPORTED_VOICES TTS_SUPPORTED_VOICES
), ),
vol.Optional(TTS_CONF_FILEFORMAT, default=TTS_DEFAULT_FILEFORMAT): vol.In(
TTS_FILEFORMAT_MAP
),
vol.Optional(STT_CONF_LANGUAGE, default=STT_DEFAULT_LANGUAGE): vol.In( vol.Optional(STT_CONF_LANGUAGE, default=STT_DEFAULT_LANGUAGE): vol.In(
STT_LANGUAGES STT_LANGUAGES
), ),
@@ -69,102 +71,46 @@ STEP_USER_DATA_SCHEMA = vol.Schema(
) )
class BaiduTTSConfigFlow(ConfigFlow, domain=DOMAIN): class BaiduVoiceConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Baidu TTS.""" """Handle a config flow for Baidu Voice."""
VERSION = 1 VERSION = 1
async def async_step_reconfigure(self, user_input: dict[str, Any] | None = None):
"""Handle reconfiguration of the integration."""
if user_input is not None:
return self.async_update_reload_and_abort(
self._get_reconfigure_entry(),
data_updates=user_input,
)
schema = self.add_suggested_values_to_schema(
STEP_USER_DATA_SCHEMA, self._get_reconfigure_entry().data
)
schema = schema.extend(
{
vol.Required(CONF_APP_ID): SelectSelector(
SelectSelectorConfig(
options=[self._get_reconfigure_entry().data[CONF_APP_ID]],
mode=SelectSelectorMode.DROPDOWN,
)
)
}
)
return self.async_show_form(
step_id="reconfigure",
data_schema=schema,
)
async def async_step_user( async def async_step_user(
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult: ) -> ConfigFlowResult:
"""Handle the initial step.""" """Handle the initial step."""
if user_input is not None: if user_input is not None:
# Provide unique ID to prevent duplicate entries
app_id = user_input[CONF_APP_ID] app_id = user_input[CONF_APP_ID]
await self.async_set_unique_id(f"baidu_tts_{app_id}") await self.async_set_unique_id(f"baidu_voice_{app_id}")
self._abort_if_unique_id_configured() self._abort_if_unique_id_configured()
return self.async_create_entry(title="Baidu Voice", data=user_input)
return self.async_create_entry(title="百度语音合成", data=user_input)
return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA) return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA)
@classmethod
@callback
def async_get_options_flow(cls, config_entry: ConfigEntry) -> BaiduTTSOptionsFlow:
"""Get the options flow for this handler."""
return BaiduTTSOptionsFlow()
class BaiduTTSOptionsFlow(OptionsFlow):
"""Baidu TTS integration options handler."""
async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Manage the options."""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)
options = self.config_entry.options
data = self.config_entry.data
schema = {
vol.Required(
CONF_APP_ID,
default=options.get(CONF_APP_ID, data.get(CONF_APP_ID)),
): str,
vol.Required(
CONF_API_KEY,
default=options.get(CONF_API_KEY, data.get(CONF_API_KEY)),
): str,
vol.Required(
CONF_SECRET_KEY,
default=options.get(CONF_SECRET_KEY, data.get(CONF_SECRET_KEY)),
): str,
vol.Required(
TTS_CONF_LANGUAGE,
default=options.get(TTS_CONF_LANGUAGE, data.get(TTS_CONF_LANGUAGE)),
): vol.In(TTS_LANGUAGES),
vol.Optional(
TTS_CONF_SPEED,
default=options.get(
TTS_CONF_SPEED, data.get(TTS_CONF_SPEED, TTS_DEFAULT_SPEED)
),
): vol.All(vol.Coerce(int), vol.Range(min=0, max=9)),
vol.Optional(
TTS_CONF_PITCH,
default=options.get(
TTS_CONF_PITCH, data.get(TTS_CONF_PITCH, TTS_DEFAULT_PITCH)
),
): vol.All(vol.Coerce(int), vol.Range(min=0, max=9)),
vol.Optional(
TTS_CONF_VOLUME,
default=options.get(
TTS_CONF_VOLUME, data.get(TTS_CONF_VOLUME, TTS_DEFAULT_VOLUME)
),
): vol.All(vol.Coerce(int), vol.Range(min=0, max=15)),
vol.Optional(
TTS_CONF_VOICE,
default=options.get(
TTS_CONF_VOICE, data.get(TTS_CONF_VOICE, TTS_DEFAULT_VOICE)
),
): vol.In(TTS_SUPPORTED_VOICES),
vol.Optional(
TTS_CONF_FILEFORMAT,
default=options.get(
TTS_CONF_FILEFORMAT,
data.get(TTS_CONF_FILEFORMAT, TTS_DEFAULT_FILEFORMAT),
),
): vol.In(TTS_FILEFORMAT_MAP),
vol.Optional(
STT_CONF_LANGUAGE,
default=options.get(
STT_CONF_LANGUAGE, data.get(STT_CONF_LANGUAGE, STT_DEFAULT_LANGUAGE)
),
): vol.In(STT_LANGUAGES),
}
return self.async_show_form(
step_id="init",
data_schema=vol.Schema(schema),
)
+1 -1
View File
@@ -3,7 +3,7 @@
from typing import Final from typing import Final
DOMAIN: Final = "baidu_voice" DOMAIN: Final = "baidu_voice"
ENDPOINT: Final = "http://vop.baidu.com/server_api"
# 配置项 # 配置项
CONF_APP_ID: Final = "app_id" CONF_APP_ID: Final = "app_id"
CONF_API_KEY: Final = "api_key" CONF_API_KEY: Final = "api_key"
-6
View File
@@ -1,6 +0,0 @@
{
"name": "Baidu Voice",
"domains": ["tts", "stt"],
"homeassistant": "2023.1.0",
"render_readme": true
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

+1 -2
View File
@@ -12,6 +12,5 @@
"requirements": [ "requirements": [
"baidu-aip == 4.16.10", "chardet==5.2.0" "baidu-aip == 4.16.10", "chardet==5.2.0"
], ],
"version": "0.0.1", "version": "0.0.1"
"issue_tracker": "https://github.com/howelljiang/baidu-voice/issues"
} }
+41 -4
View File
@@ -2,20 +2,57 @@
"config": { "config": {
"step": { "step": {
"user": { "user": {
"title": "[%key:common::config_flow::title::setup%] Baidu Voice",
"description": "[%key:common::config_flow::description::enter_credentials%]",
"data": { "data": {
"host": "[%key:common::config_flow::data::host%]", "app_id": "[%key:common::config_flow::data::app_id%]",
"username": "[%key:common::config_flow::data::username%]", "api_key": "[%key:common::config_flow::data::api_key%]",
"password": "[%key:common::config_flow::data::password%]" "secret_key": "[%key:common::config_flow::data::secret_key%]",
"language": "[%key:common::config_flow::data::language%]",
"stt_language": "[%key:common::config_flow::data::stt_language%]",
"volume": "[%key:common::config_flow::data::volume%]",
"speed": "[%key:common::config_flow::data::speed%]",
"pitch": "[%key:common::config_flow::data::pitch%]",
"voice": "[%key:common::config_flow::data::voice%]",
"fileformat": "[%key:common::config_flow::data::fileformat%]",
"test_connection": "[%key:common::config_flow::data::test_connection%]"
} }
} }
}, },
"error": { "error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"unknown": "[%key:common::config_flow::error::unknown%]" "unknown": "[%key:common::config_flow::error::unknown%]",
"auth": "[%key:common::config_flow::error::auth%]",
"test_success": "[%key:common::config_flow::error::test_success%]"
}, },
"abort": { "abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]" "already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
} }
},
"options": {
"step": {
"init": {
"title": "[%key:common::config_flow::options::title%]",
"description": "[%key:common::config_flow::options::description%]",
"data": {
"app_id": "[%key:common::config_flow::data::app_id%]",
"api_key": "[%key:common::config_flow::data::api_key%]",
"secret_key": "[%key:common::config_flow::data::secret_key%]",
"language": "[%key:common::config_flow::data::language%]",
"stt_language": "[%key:common::config_flow::data::stt_language%]",
"volume": "[%key:common::config_flow::data::volume%]",
"speed": "[%key:common::config_flow::data::speed%]",
"pitch": "[%key:common::config_flow::data::pitch%]",
"voice": "[%key:common::config_flow::data::voice%]",
"fileformat": "[%key:common::config_flow::data::fileformat%]",
"test_connection": "[%key:common::config_flow::data::test_connection%]"
}
}
},
"error": {
"auth": "[%key:common::config_flow::error::auth%]",
"test_success": "[%key:common::config_flow::error::test_success%]"
}
} }
} }
+3 -4
View File
@@ -48,7 +48,6 @@ class BaiduSTTEntity(stt.SpeechToTextEntity):
def __init__(self, hass: HomeAssistant, config: dict[str, Any]) -> None: def __init__(self, hass: HomeAssistant, config: dict[str, Any]) -> None:
"""Initialize Baidu speech-to-text entity.""" """Initialize Baidu speech-to-text entity."""
super().__init__()
self.hass = hass self.hass = hass
self._config = config self._config = config
self._client = AipSpeech( self._client = AipSpeech(
@@ -62,7 +61,7 @@ class BaiduSTTEntity(stt.SpeechToTextEntity):
@property @property
def supported_languages(self) -> list[str]: def supported_languages(self) -> list[str]:
"""Return list of supported languages.""" """Return list of supported languages."""
return ["zh-CN", "en-US", "yue-CN", "sichuan-CN"] return ["zh-CN", "en-US", "zh-HK", "zh-TW"]
@property @property
def supported_formats(self) -> list[str]: def supported_formats(self) -> list[str]:
@@ -118,7 +117,7 @@ class BaiduSTTEntity(stt.SpeechToTextEntity):
) )
if "err_no" in result and result["err_no"] != 0: if "err_no" in result and result["err_no"] != 0:
_LOGGER.debug( _LOGGER.error(
"Error from Baidu API: %s - %s", "Error from Baidu API: %s - %s",
result.get("err_msg", "Unknown error"), result.get("err_msg", "Unknown error"),
result.get("err_detail", "No details"), result.get("err_detail", "No details"),
@@ -139,7 +138,7 @@ class BaiduSTTEntity(stt.SpeechToTextEntity):
result=stt.SpeechResultState.SUCCESS, result=stt.SpeechResultState.SUCCESS,
) )
except Exception: # pylint: disable=broad-except except Exception:
_LOGGER.exception("Error processing Baidu STT") _LOGGER.exception("Error processing Baidu STT")
return stt.SpeechResult( return stt.SpeechResult(
text=None, text=None,
@@ -0,0 +1,30 @@
"""Provide info to system health."""
from typing import Any
from homeassistant.components import system_health
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from .const import DOMAIN, ENDPOINT
@callback
def async_register(
hass: HomeAssistant, register: system_health.SystemHealthRegistration
) -> None:
"""Register system health callbacks."""
register.async_register_info(system_health_info)
async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
"""Get info for the info page."""
config_entry: ConfigEntry = hass.config_entries.async_entries(DOMAIN)[0]
quota_info = await config_entry.runtime_data.async_get_quota_info()
return {
"consumed_requests": quota_info.consumed_requests,
"remaining_requests": quota_info.requests_remaining,
# checking the url can take a while, so set the coroutine in the info dict
"can_reach_server": system_health.async_check_can_reach_url(hass, ENDPOINT),
}
@@ -27,12 +27,8 @@
"fileformat": "Audio Format", "fileformat": "Audio Format",
"test_connection": "Test Connection" "test_connection": "Test Connection"
} }
} },
} "reconfigure": {
},
"options": {
"step": {
"init": {
"title": "Update Baidu Voice Settings", "title": "Update Baidu Voice Settings",
"description": "Modify Baidu Voice settings", "description": "Modify Baidu Voice settings",
"data": { "data": {
@@ -49,10 +45,6 @@
"test_connection": "Test Connection" "test_connection": "Test Connection"
} }
} }
},
"error": {
"auth": "Authentication failed",
"test_success": "Connection test successful"
} }
} }
} }
@@ -27,12 +27,8 @@
"fileformat": "音频格式", "fileformat": "音频格式",
"test_connection": "测试连接" "test_connection": "测试连接"
} }
} },
} "reconfigure": {
},
"options": {
"step": {
"init": {
"title": "更新百度语音设置", "title": "更新百度语音设置",
"description": "修改百度语音设置", "description": "修改百度语音设置",
"data": { "data": {
@@ -49,10 +45,6 @@
"test_connection": "测试连接" "test_connection": "测试连接"
} }
} }
},
"error": {
"auth": "认证失败",
"test_success": "连接测试成功"
} }
} }
} }
+5 -64
View File
@@ -16,13 +16,11 @@ from homeassistant.components.tts import (
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from .const import ( from .const import (
CONF_API_KEY, CONF_API_KEY,
CONF_APP_ID, CONF_APP_ID,
CONF_SECRET_KEY, CONF_SECRET_KEY,
DOMAIN,
TTS_DEFAULT_FILEFORMAT, TTS_DEFAULT_FILEFORMAT,
TTS_DEFAULT_LANGUAGE, TTS_DEFAULT_LANGUAGE,
TTS_DEFAULT_PITCH, TTS_DEFAULT_PITCH,
@@ -53,29 +51,11 @@ class BaiduTTSEntity(TextToSpeechEntity):
def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None: def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
"""Initialize the Baidu TTS entity.""" """Initialize the Baidu TTS entity."""
self.hass = hass
self._config_entry = config_entry
# Generate unique ID and set name # Generate unique ID and set name
app_id = config_entry.data[CONF_APP_ID] app_id = config_entry.data[CONF_APP_ID]
self._attr_unique_id = f"baidu_tts_{app_id}" self._attr_unique_id = f"baidu_tts_{app_id}"
self._attr_name = "百度语音合成" self._attr_name = "Baidu TTS"
# Add device info
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, app_id)},
name="百度语音",
manufacturer="百度",
model="语音合成服务",
entry_type=DeviceEntryType.SERVICE,
)
_LOGGER.debug(
"Initializing Baidu TTS entity with app_id: %s, unique_id: %s, name: %s",
app_id,
self._attr_unique_id,
self._attr_name,
)
# Initialize the TTS client # Initialize the TTS client
self._client = AipSpeech( self._client = AipSpeech(
@@ -87,28 +67,23 @@ class BaiduTTSEntity(TextToSpeechEntity):
@property @property
def default_language(self) -> str: def default_language(self) -> str:
"""Return the default language.""" """Return the default language."""
_LOGGER.debug("Getting default language: %s", TTS_DEFAULT_LANGUAGE)
return TTS_DEFAULT_LANGUAGE return TTS_DEFAULT_LANGUAGE
@property @property
def supported_languages(self) -> list[str]: def supported_languages(self) -> list[str]:
"""Return a list of supported languages.""" """Return a list of supported languages."""
languages = list(TTS_LANGUAGES.keys()) return list(TTS_LANGUAGES.keys())
_LOGGER.debug("Getting supported languages: %s", languages)
return languages
@property @property
def supported_options(self) -> list[str]: def supported_options(self) -> list[str]:
"""Return list of supported options.""" """Return list of supported options."""
options = ["speed", "pitch", "volume", "voice", "fileformat"] return ["speed", "pitch", "volume", "voice", "fileformat"]
_LOGGER.debug("Getting supported options: %s", options)
return options
@property @property
def default_options(self) -> dict[str, Any]: def default_options(self) -> dict[str, Any]:
"""Return a dict of default options.""" """Return a dict of default options."""
# Get current values from config_entry.options first, then data, then fall back to defaults # Get current values from config_entry.options first, then data, then fall back to defaults
options = { return {
"speed": self._config_entry.options.get( "speed": self._config_entry.options.get(
"speed", self._config_entry.data.get("speed", TTS_DEFAULT_SPEED) "speed", self._config_entry.data.get("speed", TTS_DEFAULT_SPEED)
), ),
@@ -126,8 +101,6 @@ class BaiduTTSEntity(TextToSpeechEntity):
self._config_entry.data.get("fileformat", TTS_DEFAULT_FILEFORMAT), self._config_entry.data.get("fileformat", TTS_DEFAULT_FILEFORMAT),
), ),
} }
_LOGGER.debug("Getting default options: %s", options)
return options
@callback @callback
def async_get_supported_voices(self, language: str) -> list[Voice] | None: def async_get_supported_voices(self, language: str) -> list[Voice] | None:
@@ -135,77 +108,48 @@ class BaiduTTSEntity(TextToSpeechEntity):
voices = [] voices = []
for voice_id, voice_name in TTS_SUPPORTED_VOICES.items(): for voice_id, voice_name in TTS_SUPPORTED_VOICES.items():
voices.append(Voice(str(voice_id), voice_name)) voices.append(Voice(str(voice_id), voice_name))
_LOGGER.debug("Getting supported voices for language %s: %s", language, voices)
return voices return voices
def get_tts_audio( def get_tts_audio(
self, message: str, language: str, options: dict[str, Any] self, message: str, language: str, options: dict[str, Any]
) -> TtsAudioType: ) -> TtsAudioType:
"""Get TTS audio from Baidu.""" """Get TTS audio from Baidu."""
_LOGGER.debug("=================== TTS Debug Info Start ===================")
_LOGGER.debug("Message: %s", message)
_LOGGER.debug("Language: %s", language)
_LOGGER.debug("Raw options dict: %s", options)
_LOGGER.debug("Config entry data: %s", self._config_entry.data)
_LOGGER.debug("Config entry options: %s", self._config_entry.options)
# 获取配置值,优先级:options > config_entry.options > config_entry.data > 默认值 # options > config_entry.data > default
try: try:
speed = int( speed = int(
options.get("speed") options.get("speed")
or self._config_entry.options.get("speed")
or self._config_entry.data.get("speed") or self._config_entry.data.get("speed")
or TTS_DEFAULT_SPEED or TTS_DEFAULT_SPEED
) )
pitch = int( pitch = int(
options.get("pitch") options.get("pitch")
or self._config_entry.options.get("pitch")
or self._config_entry.data.get("pitch") or self._config_entry.data.get("pitch")
or TTS_DEFAULT_PITCH or TTS_DEFAULT_PITCH
) )
volume = int( volume = int(
options.get("volume") options.get("volume")
or self._config_entry.options.get("volume")
or self._config_entry.data.get("volume") or self._config_entry.data.get("volume")
or TTS_DEFAULT_VOLUME or TTS_DEFAULT_VOLUME
) )
voice = int( voice = int(
options.get("voice") options.get("voice")
or self._config_entry.options.get("voice")
or self._config_entry.data.get("voice") or self._config_entry.data.get("voice")
or TTS_DEFAULT_VOICE or TTS_DEFAULT_VOICE
) )
fileformat = int( fileformat = int(
options.get("fileformat") options.get("fileformat")
or self._config_entry.options.get("fileformat")
or self._config_entry.data.get("fileformat") or self._config_entry.data.get("fileformat")
or TTS_DEFAULT_FILEFORMAT or TTS_DEFAULT_FILEFORMAT
) )
_LOGGER.debug(
"Parsed values - speed: %s(%s), pitch: %s(%s), volume: %s(%s), "
"voice: %s(%s), fileformat: %s(%s)",
speed,
type(speed),
pitch,
type(pitch),
volume,
type(volume),
voice,
type(voice),
fileformat,
type(fileformat),
)
except ValueError as ex: except ValueError as ex:
_LOGGER.error("Error parsing options: %s", ex) _LOGGER.error("Error parsing options: %s", ex)
raise HomeAssistantError(f"Invalid option value: {ex}") from ex raise HomeAssistantError(f"Invalid option value: {ex}") from ex
# 获取音频格式
format_config = TTS_FILEFORMAT_MAP.get(fileformat, TTS_FILEFORMAT_MAP[6]) format_config = TTS_FILEFORMAT_MAP.get(fileformat, TTS_FILEFORMAT_MAP[6])
_LOGGER.debug("Using audio format: %s", format_config) _LOGGER.debug("Using audio format: %s", format_config)
# 准备API参数
api_params = { api_params = {
"spd": speed, "spd": speed,
"pit": pitch, "pit": pitch,
@@ -216,7 +160,6 @@ class BaiduTTSEntity(TextToSpeechEntity):
_LOGGER.debug("API parameters: %s", api_params) _LOGGER.debug("API parameters: %s", api_params)
try: try:
_LOGGER.debug("Calling Baidu TTS API")
result = self._client.synthesis( result = self._client.synthesis(
message, message,
language, language,
@@ -244,6 +187,4 @@ class BaiduTTSEntity(TextToSpeechEntity):
type(ex).__name__, type(ex).__name__,
) )
raise HomeAssistantError("Failed to generate TTS audio") from ex raise HomeAssistantError("Failed to generate TTS audio") from ex
_LOGGER.debug("=================== TTS Debug Info End ===================")
return format_config, result return format_config, result