feat(audio): add pluggable audio preprocessing and denoising layer before STT
- Add audio_enhancer module with 60s timeout, zero-transcoding default, and fail-soft fallback - Persist enhanced audio in daily folders with _enhanced suffix and emit audio.enhance.result event - Connect audio enhancer to transcribe_multi and transcribe in stt.py - Forward message_id and trace_id from handlers - Ensure consensus_text fallback persistence and remove scenario leakage in nlu.py - Add test_enhancer.py unit suite and update smoke_test.py
This commit is contained in:
+13
-3
@@ -76,7 +76,8 @@ async def _call_single_stt(client: httpx.AsyncClient, provider: dict, converted_
|
||||
|
||||
|
||||
async def transcribe_multi(settings: Settings, audio: bytes, mime_type: str | None = None,
|
||||
filename: str | None = None, trace_id: str | None = None) -> list[dict]:
|
||||
filename: str | None = None, trace_id: str | None = None,
|
||||
message_id: int | None = None) -> list[dict]:
|
||||
"""Transcribe audio with all configured STT providers in parallel.
|
||||
|
||||
Returns a list of candidate dicts: [{"name": str, "text": str, "model": str}, ...]
|
||||
@@ -87,6 +88,13 @@ async def transcribe_multi(settings: Settings, audio: bytes, mime_type: str | No
|
||||
if not providers:
|
||||
raise RuntimeError("No STT providers are configured (PROCUREMENT_BOT_STT_*)")
|
||||
|
||||
# Audio enhancement / denoising step (pluggable, fail-soft, zero-transcode by default)
|
||||
from app.audio_enhancer import enhance_voice
|
||||
audio, _ = await enhance_voice(
|
||||
settings, audio, mime_type=mime_type, filename=filename,
|
||||
trace_id=trace_id, message_id=message_id,
|
||||
)
|
||||
|
||||
suffix = Path(filename or "").suffix
|
||||
if not suffix and mime_type:
|
||||
suffix = {"audio/ogg": ".ogg", "audio/opus": ".ogg", "audio/mpeg": ".mp3",
|
||||
@@ -117,8 +125,10 @@ async def transcribe_multi(settings: Settings, audio: bytes, mime_type: str | No
|
||||
|
||||
|
||||
async def transcribe(settings: Settings, audio: bytes, mime_type: str | None = None,
|
||||
filename: str | None = None, trace_id: str | None = None) -> str:
|
||||
filename: str | None = None, trace_id: str | None = None,
|
||||
message_id: int | None = None) -> str:
|
||||
"""Return the Persian transcript for a voice note (empty string on silence)."""
|
||||
transcripts = await transcribe_multi(settings, audio, mime_type=mime_type,
|
||||
filename=filename, trace_id=trace_id)
|
||||
filename=filename, trace_id=trace_id,
|
||||
message_id=message_id)
|
||||
return transcripts[0]["text"] if transcripts else ""
|
||||
|
||||
Reference in New Issue
Block a user