mirror of
https://github.com/chliny/hass-tencentcloud-asr.git
synced 2026-07-21 22:53:58 +08:00
feat: add ASR filtering options
This commit is contained in:
@@ -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={})
|
||||||
|
|||||||
@@ -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 - 中文电话通用",
|
||||||
|
|||||||
Reference in New Issue
Block a user