"""Voice Activity Detection (VAD) utilities for VoIdeaAI. Server-side VAD analysis and parameter processing. Actual VAD is performed client-side via Web Audio API (getUserMedia). """ VAD_DEFAULTS = { "enabled": True, "noise_threshold": 0.3, "silence_timeout_ms": 1500, "min_audio_duration_ms": 300, } def validate_vad_params(params: dict | None = None) -> dict: """Validate and return VAD parameters with defaults.""" if not params: return dict(VAD_DEFAULTS) result = dict(VAD_DEFAULTS) if isinstance(params.get("noise_threshold"), (int, float)): result["noise_threshold"] = max(0.0, min(1.0, float(params["noise_threshold"]))) if isinstance(params.get("silence_timeout_ms"), (int, float)): result["silence_timeout_ms"] = max(100, int(params["silence_timeout_ms"])) if isinstance(params.get("min_audio_duration_ms"), (int, float)): result["min_audio_duration_ms"] = max(50, int(params["min_audio_duration_ms"])) if isinstance(params.get("enabled"), bool): result["enabled"] = params["enabled"] return result def should_process_audio( duration_ms: int | None = None, vad_params: dict | None = None, ) -> tuple[bool, str | None]: """Check if audio should be processed based on VAD parameters. Returns (should_process, reason_if_skipped). """ params = validate_vad_params(vad_params) if not params["enabled"]: return True, None if duration_ms is not None and duration_ms < params["min_audio_duration_ms"]: return False, f"Audio too short: {duration_ms}ms < {params['min_audio_duration_ms']}ms" return True, None