feat: add ASR filtering options

This commit is contained in:
chliny
2026-07-19 22:50:02 +08:00
parent 667a735fe4
commit 1a05335b3c
6 changed files with 128 additions and 12 deletions
@@ -13,6 +13,10 @@ _LOGGER = logging.getLogger(__name__)
SecretIdKey = "secretid" SecretIdKey = "secretid"
SecretKeyKey = "secretkey" SecretKeyKey = "secretkey"
ModelKey = "model" ModelKey = "model"
FilterDirtyKey = "filter_dirty"
FilterModalKey = "filter_modal"
FilterPuncKey = "filter_punc"
ConvertNumModeKey = "convert_num_mode"
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry): async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):
@@ -3,11 +3,24 @@ import voluptuous as vol
from typing import Any, Dict from typing import Any, Dict
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow, ConfigEntry from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow, ConfigEntry
from homeassistant.helpers.selector import SelectSelector, SelectSelectorConfig, SelectOptionDict from homeassistant.helpers.selector import (
BooleanSelector,
SelectOptionDict,
SelectSelector,
SelectSelectorConfig,
)
from .tencentcloud_api import ModuleSupportLanguage, DefaultModel from .tencentcloud_api import ModuleSupportLanguage, DefaultModel
from .tencentcloud_api import TencentCloudAsrAPi from .tencentcloud_api import TencentCloudAsrAPi
from . import SecretIdKey, SecretKeyKey, ModelKey from . import (
ConvertNumModeKey,
FilterDirtyKey,
FilterModalKey,
FilterPuncKey,
ModelKey,
SecretIdKey,
SecretKeyKey,
)
from . import DOMAIN from . import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -22,6 +35,17 @@ modelSelector = SelectSelector(
) )
) )
filterDirtySelector = SelectSelector(
SelectSelectorConfig(
options=[
SelectOptionDict(value="0", label="0"),
SelectOptionDict(value="1", label="1"),
SelectOptionDict(value="2", label="2"),
],
translation_key="filter_dirty_descriptions",
)
)
class ConfigFlowHandler(ConfigFlow, domain=DOMAIN): class ConfigFlowHandler(ConfigFlow, domain=DOMAIN):
async def async_step_user(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult: async def async_step_user(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
@@ -43,6 +67,10 @@ class ConfigFlowHandler(ConfigFlow, domain=DOMAIN):
vol.Required(SecretIdKey): str, vol.Required(SecretIdKey): str,
vol.Required(SecretKeyKey): str, vol.Required(SecretKeyKey): str,
vol.Required(ModelKey, default=DefaultModel): modelSelector, vol.Required(ModelKey, default=DefaultModel): modelSelector,
vol.Required(FilterDirtyKey, default="0"): filterDirtySelector,
vol.Required(FilterModalKey, default=False): BooleanSelector(),
vol.Required(FilterPuncKey, default=False): BooleanSelector(),
vol.Required(ConvertNumModeKey, default=True): BooleanSelector(),
}) })
return self.async_show_form(step_id="user", data_schema=config_schema, errors=errors) return self.async_show_form(step_id="user", data_schema=config_schema, errors=errors)
@@ -68,5 +96,21 @@ class TencentCloudAsrOptionFlow(OptionsFlow):
model = user_input.get(ModelKey, DefaultModel) model = user_input.get(ModelKey, DefaultModel)
config_schema = vol.Schema({ config_schema = vol.Schema({
vol.Optional(ModelKey, default=model): modelSelector, vol.Optional(ModelKey, default=model): modelSelector,
vol.Required(
FilterDirtyKey,
default=user_input.get(FilterDirtyKey, "0"),
): filterDirtySelector,
vol.Required(
FilterModalKey,
default=user_input.get(FilterModalKey, False),
): BooleanSelector(),
vol.Required(
FilterPuncKey,
default=user_input.get(FilterPuncKey, False),
): BooleanSelector(),
vol.Required(
ConvertNumModeKey,
default=user_input.get(ConvertNumModeKey, True),
): BooleanSelector(),
}) })
return self.async_show_form(step_id="user", data_schema=config_schema, errors={}) return self.async_show_form(step_id="user", data_schema=config_schema, errors={})
+29 -4
View File
@@ -10,7 +10,15 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .tencentcloud_api import TencentCloudAsrAPi from .tencentcloud_api import TencentCloudAsrAPi
from .tencentcloud_api import ModuleSupportLanguage from .tencentcloud_api import ModuleSupportLanguage
from .tencentcloud_api import DefaultModel from .tencentcloud_api import DefaultModel
from . import SecretIdKey, SecretKeyKey, ModelKey from . import (
ConvertNumModeKey,
FilterDirtyKey,
FilterModalKey,
FilterPuncKey,
ModelKey,
SecretIdKey,
SecretKeyKey,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -32,6 +40,7 @@ class ASRSTT(stt.SpeechToTextEntity):
self._attr_unique_id = f"tencentcloud_asr_stt" self._attr_unique_id = f"tencentcloud_asr_stt"
self._attr_name = f"TencentCloud Asr STT" self._attr_name = f"TencentCloud Asr STT"
self.hass = hass self.hass = hass
self.config_entry = config_entry
@property @property
def supported_languages(self) -> list[str]: def supported_languages(self) -> list[str]:
@@ -71,9 +80,25 @@ class ASRSTT(stt.SpeechToTextEntity):
audio += chunk audio += chunk
data = base64.b64encode(audio).decode("utf8", "ignore").strip() data = base64.b64encode(audio).decode("utf8", "ignore").strip()
model: str = self.hass.data.get(ModelKey, DefaultModel) config = {**self.config_entry.data, **self.config_entry.options}
_LOGGER.debug(f"process_audio_stream transcribe: {data} {model}") model: str = config.get(ModelKey, DefaultModel)
ret, result = await self.hass.async_add_executor_job(partial(self.tencentCloudApi.SentenceRecognition, model, data)) _LOGGER.debug(
"process_audio_stream transcribe: audio_bytes=%s model=%s",
len(audio),
model,
)
ret, result = await self.hass.async_add_executor_job(
partial(
self.tencentCloudApi.SentenceRecognition,
model,
data,
len(audio),
config.get(FilterDirtyKey, "0"),
config.get(FilterModalKey, False),
config.get(FilterPuncKey, False),
config.get(ConvertNumModeKey, True),
)
)
if not ret: if not ret:
return stt.SpeechResult(result, stt.SpeechResultState.ERROR) return stt.SpeechResult(result, stt.SpeechResultState.ERROR)
if not result: if not result:
@@ -43,7 +43,16 @@ class TencentCloudAsrAPi(object):
region = "" region = ""
self.asrClient = AsrClient(cred, region) self.asrClient = AsrClient(cred, region)
def SentenceRecognition(self, engSerViceType, data: str) -> (tuple[bool, str | None]): def SentenceRecognition(
self,
engSerViceType,
data: str,
data_len: int,
filter_dirty: str,
filter_modal: bool,
filter_punc: bool,
convert_num_mode: bool,
) -> tuple[bool, str | None]:
req = SentenceRecognitionRequest() req = SentenceRecognitionRequest()
req.EngSerViceType = engSerViceType req.EngSerViceType = engSerViceType
req.SourceType = SentenceRecognitionSourceTypePost req.SourceType = SentenceRecognitionSourceTypePost
@@ -52,7 +61,11 @@ class TencentCloudAsrAPi(object):
req.SubServiceType = 2 req.SubServiceType = 2
req.UsrAudioKey = "" req.UsrAudioKey = ""
req.Data = data req.Data = data
req.DataLen = len(data) req.DataLen = data_len
req.FilterDirty = int(filter_dirty)
req.FilterModal = int(filter_modal)
req.FilterPunc = int(filter_punc)
req.ConvertNumMode = int(convert_num_mode)
try: try:
res: SentenceRecognitionResponse = self.asrClient.SentenceRecognition(req) res: SentenceRecognitionResponse = self.asrClient.SentenceRecognition(req)
return True, res.Result return True, res.Result
@@ -7,7 +7,11 @@
"data": { "data": {
"secretid": "tencentcloud asr secretid", "secretid": "tencentcloud asr secretid",
"secretkey": "tencnetcloud asr secretkey", "secretkey": "tencnetcloud asr secretkey",
"model": "model" "model": "model",
"filter_dirty": "Dirty word handling",
"filter_modal": "Filter filler words such as um and uh",
"filter_punc": "Filter sentence-ending punctuation",
"convert_num_mode": "Smart Arabic numeral conversion"
}, },
"description": "The integration is based on [Tencent Cloud API](https://cloud.tencent.com/document/product/1093/35646)." "description": "The integration is based on [Tencent Cloud API](https://cloud.tencent.com/document/product/1093/35646)."
} }
@@ -17,12 +21,23 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"model": "model" "model": "model",
"filter_dirty": "Dirty word handling",
"filter_modal": "Filter filler words such as um and uh",
"filter_punc": "Filter sentence-ending punctuation",
"convert_num_mode": "Smart Arabic numeral conversion"
} }
} }
} }
}, },
"selector": { "selector": {
"filter_dirty_descriptions": {
"options": {
"0": "Do not filter dirty words",
"1": "Filter dirty words",
"2": "Replace dirty words with *"
}
},
"model_descriptions": { "model_descriptions": {
"options": { "options": {
"8k_zh": "8k_zh - Chinese telephone audio", "8k_zh": "8k_zh - Chinese telephone audio",
@@ -7,7 +7,11 @@
"data": { "data": {
"secretid": "请输入腾讯云ASR服务secretid", "secretid": "请输入腾讯云ASR服务secretid",
"secretkey": "请输入腾讯云ASR服务secretkey", "secretkey": "请输入腾讯云ASR服务secretkey",
"model": "模型" "model": "模型",
"filter_dirty": "脏词处理方式",
"filter_modal": "过滤“嗯、啊”等语气词",
"filter_punc": "过滤句末标点",
"convert_num_mode": "阿拉伯数字智能转换"
}, },
"description": "此集成基于腾讯云API, 具体见[腾讯云文档](https://cloud.tencent.com/document/product/1093/35646)" "description": "此集成基于腾讯云API, 具体见[腾讯云文档](https://cloud.tencent.com/document/product/1093/35646)"
} }
@@ -17,12 +21,23 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"model": "模型" "model": "模型",
"filter_dirty": "脏词处理方式",
"filter_modal": "过滤“嗯、啊”等语气词",
"filter_punc": "过滤句末标点",
"convert_num_mode": "阿拉伯数字智能转换"
} }
} }
} }
}, },
"selector": { "selector": {
"filter_dirty_descriptions": {
"options": {
"0": "不过滤脏词",
"1": "过滤脏词",
"2": "将脏词替换为 *"
}
},
"model_descriptions": { "model_descriptions": {
"options": { "options": {
"8k_zh": "8k_zh - 中文电话通用", "8k_zh": "8k_zh - 中文电话通用",