[实时转写]:完成录音期间转写显示,包含partial事件、本地streaming STT和终端实时反馈
This commit is contained in:
@@ -3,10 +3,12 @@ from __future__ import annotations
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from owner_voice_pet.models import AudioFrame, AudioSegment, ErrorCode, ProviderError
|
||||
from owner_voice_pet.config import AppConfig
|
||||
from owner_voice_pet.stt import CloudAsrSttProvider, MetadataSttProvider, SherpaOnnxSttProvider, is_valid_transcript_text
|
||||
from owner_voice_pet.speech_models import stt_model_paths
|
||||
from owner_voice_pet.vad import EnergyVadProvider, HybridVadProvider, PrimarySpeakerVadRecorder, VadRecorder
|
||||
from owner_voice_pet.wakeword import (
|
||||
KeywordWakeWordProvider,
|
||||
@@ -246,6 +248,60 @@ class WakeVadSttTests(unittest.TestCase):
|
||||
provider.load()
|
||||
self.assertEqual(raised.exception.code, ErrorCode.STT_MODEL_MISSING)
|
||||
|
||||
def test_sherpa_stt_streaming_session_emits_partial_text(self) -> None:
|
||||
class FakeResult:
|
||||
def __init__(self, text: str) -> None:
|
||||
self.text = text
|
||||
|
||||
class FakeStream:
|
||||
def __init__(self) -> None:
|
||||
self.ready = False
|
||||
self.text = ""
|
||||
|
||||
def accept_waveform(self, sample_rate, samples) -> None:
|
||||
self.ready = True
|
||||
self.text = "你" if not self.text else "你好"
|
||||
|
||||
class FakeRecognizer:
|
||||
def create_stream(self):
|
||||
return FakeStream()
|
||||
|
||||
def is_ready(self, stream) -> bool:
|
||||
return stream.ready
|
||||
|
||||
def decode_stream(self, stream) -> None:
|
||||
stream.ready = False
|
||||
|
||||
def get_result(self, stream):
|
||||
return FakeResult(stream.text)
|
||||
|
||||
class FakeOnlineRecognizer:
|
||||
@staticmethod
|
||||
def from_transducer(**kwargs):
|
||||
return FakeRecognizer()
|
||||
|
||||
class FakeSherpa:
|
||||
OnlineRecognizer = FakeOnlineRecognizer
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
paths = stt_model_paths(Path(tmp))
|
||||
for name, path in paths.items():
|
||||
if name == "model_dir":
|
||||
continue
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text("fake", encoding="utf-8")
|
||||
provider = SherpaOnnxSttProvider(tmp, sherpa_module=FakeSherpa)
|
||||
provider.load()
|
||||
session = provider.start_stream()
|
||||
first = session.accept_frame(make_frame(1, 0, speech=True))
|
||||
second = session.accept_frame(make_frame(2, 20, speech=True))
|
||||
|
||||
self.assertIsNotNone(first)
|
||||
self.assertIsNotNone(second)
|
||||
assert first is not None and second is not None
|
||||
self.assertEqual(first.text, "你")
|
||||
self.assertEqual(second.text, "你好")
|
||||
|
||||
def test_cloud_asr_posts_audio_transcription_request(self) -> None:
|
||||
class FakeResponse:
|
||||
def __enter__(self):
|
||||
|
||||
Reference in New Issue
Block a user