[Wake/VAD/STT]:完成本地唤醒、人声端点检测与转写入口,包含小杰小杰唤醒、VAD 录音切分、Metadata STT 和 sherpa-onnx 错误边界
This commit is contained in:
@@ -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",
|
||||
)
|
||||
Reference in New Issue
Block a user