[Wake/VAD/STT]:完成本地唤醒、人声端点检测与转写入口,包含小杰小杰唤醒、VAD 录音切分、Metadata STT 和 sherpa-onnx 错误边界

This commit is contained in:
mkbk
2026-06-17 18:18:37 +08:00
parent 90ba2bf3b0
commit 4d6232ed29
6 changed files with 389 additions and 5 deletions
+93
View File
@@ -0,0 +1,93 @@
from __future__ import annotations
import re
from pathlib import Path
from .models import AudioSegment, ErrorCode, ProviderError, Transcript
_MEANINGFUL_TEXT = re.compile(r"[\w\u4e00-\u9fff]", re.UNICODE)
def is_valid_transcript_text(text: str) -> bool:
return bool(_MEANINGFUL_TEXT.search(text.strip()))
class MetadataSttProvider:
def __init__(self, language: str = "zh") -> None:
self.language = language
self.loaded = False
def load(self) -> None:
self.loaded = True
def transcribe(self, segment: AudioSegment) -> Transcript:
if not self.loaded:
raise ProviderError(
ErrorCode.STT_TRANSCRIBE_FAILED,
"STT provider is not loaded",
False,
"metadata-stt",
"stt",
)
text = str(segment.metadata.get("transcript", "")).strip()
if not is_valid_transcript_text(text):
raise ProviderError(
ErrorCode.STT_EMPTY_TRANSCRIPT,
"STT produced no meaningful text",
True,
"metadata-stt",
"stt",
)
return Transcript(
text=text,
language=str(segment.metadata.get("language", self.language)),
confidence=float(segment.metadata.get("stt_confidence", 1.0)),
duration_ms=segment.duration_ms,
provider="metadata-stt",
raw_metadata=dict(segment.metadata),
)
class SherpaOnnxSttProvider:
def __init__(self, model_path: str, language: str = "zh") -> None:
self.model_path = Path(model_path)
self.language = language
self.loaded = False
def load(self) -> None:
if not self.model_path.exists():
raise ProviderError(
ErrorCode.STT_MODEL_MISSING,
f"sherpa-onnx STT model path does not exist: {self.model_path}",
False,
"sherpa-onnx-stt",
"stt",
)
try:
import sherpa_onnx # type: ignore[import-not-found] # noqa: F401
except Exception as exc:
raise ProviderError(
ErrorCode.STT_TRANSCRIBE_FAILED,
f"sherpa_onnx is not available: {exc}",
False,
"sherpa-onnx-stt",
"stt",
) from exc
self.loaded = True
def transcribe(self, segment: AudioSegment) -> Transcript:
if not self.loaded:
raise ProviderError(
ErrorCode.STT_TRANSCRIBE_FAILED,
"sherpa-onnx STT provider is not loaded",
False,
"sherpa-onnx-stt",
"stt",
)
raise ProviderError(
ErrorCode.STT_TRANSCRIBE_FAILED,
"sherpa-onnx runtime transcription adapter requires a concrete model profile",
False,
"sherpa-onnx-stt",
"stt",
)