VoiceGuard-API / app /main.py
S-Vetrivel's picture
Fix: Apply compatibility patches before speechbrain import
e53bdb6
import os
import sys
# Add project root to sys.path to allow importing 'src'
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
# CRITICAL: Apply compatibility patches BEFORE any speechbrain imports
import torchaudio
if not hasattr(torchaudio, "list_audio_backends"):
def _list_audio_backends():
return ["soundfile"]
torchaudio.list_audio_backends = _list_audio_backends
import huggingface_hub
_original_hf_hub_download = huggingface_hub.hf_hub_download
def _patched_hf_hub_download(*args, **kwargs):
if "use_auth_token" in kwargs:
token_val = kwargs.pop("use_auth_token")
if "token" not in kwargs:
kwargs["token"] = token_val
return _original_hf_hub_download(*args, **kwargs)
huggingface_hub.hf_hub_download = _patched_hf_hub_download
import time
import base64
import traceback
from fastapi import FastAPI, HTTPException, Header, Body
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from pydantic import BaseModel
from dotenv import load_dotenv
# Import the new pipeline
try:
import src
print(f"DEBUG: src module found at {src.__file__}")
from src.pipeline.detector import VoicePipeline
except ImportError as e:
# Fallback or detailed error logging
root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
print(f"Failed to import src.pipeline.detector.")
print(f"CWD: {os.getcwd()}")
print(f"Path: {sys.path}")
print(f"Root dir: {root_path}")
if os.path.exists(root_path):
print(f"Contents of root: {os.listdir(root_path)}")
src_path = os.path.join(root_path, "src")
if os.path.exists(src_path):
print(f"Contents of src: {os.listdir(src_path)}")
raise e
load_dotenv()
app = FastAPI(title="Voice Detector API (Refactored)")
# Initialize Pipeline (Single instance)
# Config path relative to execution root or use absolute
pipeline = VoicePipeline("config/hparams.yaml")
API_KEY = os.getenv("API_KEY", "your-secret-api-key")
class VoiceDetectionRequest(BaseModel):
language: str = "en"
audioFormat: str = "mp3"
audioBase64: str
@app.on_event("startup")
async def startup_event():
# Warmup if needed
pass
@app.post("/api/voice-detection")
async def detect_voice(
x_api_key: str = Header(None),
request_data: VoiceDetectionRequest = Body(...)
):
# 1. API Key Validation
# Allow fallback key for testing if needed
expected_key = os.getenv("API_KEY", "test_key_123")
if x_api_key and x_api_key != expected_key and x_api_key != API_KEY:
raise HTTPException(status_code=403, detail="Invalid API key")
start_time = time.time()
try:
# 2. Decode Audio
try:
audio_bytes = base64.b64decode(request_data.audioBase64, validate=True)
except Exception:
raise HTTPException(status_code=400, detail="Invalid Base64 string")
# 3. Process via Pipeline
result = pipeline.process(audio_bytes)
if "error" in result:
raise HTTPException(status_code=500, detail=result["error"])
# 4. Construct Response
response_payload = {
"status": "success",
"language": request_data.language,
"classification": result["classification"],
"confidenceScore": result["confidenceScore"],
"explanation": result["explanation"],
"processingTime": f"{time.time() - start_time:.2f}s",
"details": result.get("details", {})
}
return JSONResponse(content=response_payload)
except HTTPException as he:
raise he
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail=f"Internal Error: {str(e)}")
@app.get("/")
def health_check():
return {"status": "ok", "message": "VoiceGuard API Running (Refactored Structure)"}