Jarvis2345's picture
Squash history — remove all prior commits (secret hygiene, S4)
a31f556
Raw
History Blame
1.9 kB
# backend/voice/vad.py
# Real Voice Activity Detection using Silero VAD
import numpy as np
class SileroVAD:
def __init__(self):
import torch
# Monkey patch torch.load for Silero VAD (moved from main.py to enforce lazy-loading)
if not hasattr(torch, '_jarvis_patched'):
_orig_load = torch.load
def _safe_load(*args, **kwargs):
kwargs["weights_only"] = False
return _orig_load(*args, **kwargs)
torch.load = _safe_load
torch._jarvis_patched = True
try:
# Download real Silero VAD model on first run
self.model, utils = torch.hub.load(
repo_or_dir='snakers4/silero-vad',
model='silero_vad',
force_reload=False,
trust_repo=True
)
(self.get_speech_timestamps, _, self.read_audio,
self.VADIterator, self.collect_chunks) = utils
self.iterator = self.VADIterator(self.model, sampling_rate=16000)
self.available = True
except Exception as e:
import logging
logging.error(f"SileroVAD failed to load from torch.hub: {e}")
self.available = False
self.iterator = None
def process_chunk(self, audio_chunk: np.ndarray) -> dict:
if not getattr(self, 'available', False) or not self.iterator:
return {}
import logging
try:
# Returns {"start": int, "end": int} if speech boundaries found, else {}
return self.iterator(audio_chunk, return_seconds=False) or {}
except Exception as e:
logging.warning(
"SileroVAD dropped corrupt audio chunk",
extra={"service": "silerovad", "error": str(e), "chunk_size": len(audio_chunk)}
)
return {}