asr — 语音识别
接私有云端或本地识别引擎。当前引擎互斥:同一时间只有一个 ASR 生效。
声明
json
{
"id": "myteam.asr.deeplx",
"name": "My ASR",
"version": "1.0.0",
"target_app_version": "0.2",
"type": "asr",
"entrypoint": "my_asr.py:MyASRProvider",
"tags": ["cloud"],
"requires_hf": false,
"config_schema": [
{ "key": "api_key", "label": "API Key", "type": "password", "is_secret": true }
]
}启用后到 设置 → 语音识别 选为当前引擎。
tags 决定宿主行为:
- 含
cloud→ 云端 API(不挂本地模型卡;建议同时"requires_hf": false跳过 transformers 预热) - 含
local/offline→ 本地离线(配合model_artifacts自动挂上下载卡与硬件评级)
最小实现
python
import numpy as np
from transbox.plugins.base import BaseASRProvider, ASRCapabilities
from transbox.asr.engine import Transcript
class CustomASRProvider(BaseASRProvider):
@property
def capabilities(self) -> ASRCapabilities:
return ASRCapabilities(has_native_vad=False, supports_streaming=False)
def transcribe(self, audio: np.ndarray, sample_rate: int = 16000,
language: str = "auto", stream_id: str = "default",
with_alignment: bool = False, on_token=None) -> Transcript:
# audio: float32 单声道,16 kHz,范围 [-1, 1]
return Transcript(text="识别文字", language=language)签名硬约束(见 Provider 签名):
with_alignment必须出现在签名里,默认False。没有词级对齐器就忽略它,Transcript.words留None。 不要把这个参数透传给参数更少的底层客户端。on_token是流式增量回调,不支持就忽略。
能力与流式
python
@dataclass
class ASRCapabilities:
has_native_vad: bool = False # 引擎自带断句/端点检测,无需外部强制切句
supports_streaming: bool = False # 是否支持实时长连接流式识别
supports_word_timestamps: bool = False # 是否支持词级时间戳
supports_language_detection: bool = True # 是否支持自动语言检测流式接口(可选,全部有默认实现):
python
def stream_open(self, stream_id: str, language: str = "auto") -> Any
def stream_feed(self, stream_id: str, pcm_chunk: np.ndarray) -> Any
def stream_reopen(self, stream_id: str, language: str = "auto") -> Any
def stream_events(self, stream_id: str) -> Iterator[Tuple[str, bool]] # (文本, 是否定稿)
def stream_close(self, stream_id: str) -> str
def has_active_stream(self, stream_id: str) -> bool
def close_all_streams(self) -> None
@property
def is_streaming_capable(self) -> bool # 默认 False
@property
def supports_concurrent_streams(self) -> bool # 默认 True- 双轨(上轨
peer/ 下轨self)同时走流式时,两条会话必须能并存(各自独立句柄、权重可共享)。 底层是单活句柄就返回supports_concurrent_streams = False,宿主会自动降级另一轨。 - 不支持流式也没关系:宿主会按 VAD 切句后调
transcribe。
本地离线 ASR(重要)
本地识别插件宿主会自动接管模型下载、硬件评级与存储管理——前提是你在 mod.json 声明 model_artifacts + tags: ["local"]:
- 自动挂
HardwareRatingBanner(算力评级)与LocalModelStorageCard(镜像/代理/进度/清缓存) config_schema里只放推理超参(device / port / 采样参数…), 严禁再手写「模型下载路径 / 国内镜像开关 / 下载按钮」
json
{
"tags": ["asr", "local", "offline", "cpu-friendly"],
"requires_cuda": false,
"model_artifacts": [
{
"id": "custom-asr-weights",
"name": "Custom-ASR-0.6B",
"category": "asr",
"repo": "org/Custom-ASR-0.6B-GGUF",
"est_bytes": 1018000000,
"sources": ["huggingface", "modelscope"],
"ready_globs": ["Custom-ASR-Q8_0.gguf", "mmproj*.gguf"],
"allow_patterns": ["Custom-ASR-Q8_0.gguf", "mmproj*.gguf"]
}
]
}字段全表见 模型工件。取文件用:
python
info = self.host.inspect_model_artifact(self.manifest.id, "custom-asr-weights")
root = info["target_dir"] # 恒有值(未下载也能用)
real = info["model_dir"] # 实际命中权重的目录;未就绪时是 ""若你的插件自己起本地推理服务(llama-server / 自研 HTTP),必须读 本地服务型引擎强制契约(惰性启动 / 端口顺延 / shutdown 杀子进程)。
参考实现
| 目录 | 类型 |
|---|---|
extensions/community_cloud_mimo_asr/ | 云端 API |
extensions/community_cloud_dashscope_asr/ | 云端 API(含自定义设置页) |
extensions/community_qwen3_asr/ | 本地服务型(llama.cpp,完整契约范例) |
