from __future__ import annotations import logging from typing import Optional import numpy as np logger = logging.getLogger(__name__) class ASRService: def __init__(self) -> None: self._model = None self._post = None self._ready = False self._attempted = False self._init_error: Optional[str] = None def _ensure_loaded(self) -> None: if self._ready or self._attempted: return self._attempted = True try: from funasr import AutoModel from funasr.utils.postprocess_utils import rich_transcription_postprocess self._model = AutoModel( model="FunAudioLLM/SenseVoiceSmall", device="cuda:0", hub="hf", ) self._post = rich_transcription_postprocess self._ready = True except Exception as exc: # pragma: no cover self._init_error = str(exc) logger.warning("ASR fallback mode: %s", exc) async def transcribe(self, audio_16k: np.ndarray) -> str: self._ensure_loaded() if self._ready and self._model is not None and self._post is not None: res = self._model.generate( input=audio_16k, cache={}, language="zh", use_itn=True, ) return self._post(res[0]["text"]) # Fallback for initial bring-up return "(ASR降级)语音已接收" @property def health(self) -> dict: return {"ready": self._ready, "attempted": self._attempted, "error": self._init_error}