| | import base64 |
| | import os |
| | import contextlib |
| | import logging |
| | from typing import Optional |
| |
|
| | import uvicorn |
| | from fastapi import FastAPI, Header, HTTPException, Request, BackgroundTasks |
| | from fastapi.responses import JSONResponse |
| | from fastapi.concurrency import run_in_threadpool |
| | from pydantic import BaseModel, Field |
| |
|
| | |
| | logging.basicConfig(level=logging.INFO, format='%(asctime)s - [AudioShield] - %(levelname)s - %(message)s') |
| | logger = logging.getLogger(__name__) |
| |
|
| | |
| | from detect import detector |
| |
|
| | |
| |
|
| | |
| | @contextlib.asynccontextmanager |
| | async def lifespan(app: FastAPI): |
| | |
| | logger.info("--- Warming up the AI engine... ---") |
| | try: |
| | |
| | |
| | |
| | dummy_audio = b'\x00' * 16000 |
| | await run_in_threadpool(detector.analyze_audio, dummy_audio, "English") |
| | logger.info("--- AI Engine Ready & Warmed Up! ---") |
| | except Exception as e: |
| | logger.error(f"Warmup failed: {e}") |
| | |
| | yield |
| | |
| | |
| | logger.info("--- Shutting down AudioShield ---") |
| |
|
| | app = FastAPI( |
| | title="AudioShield AI: Voice Fraud Detector", |
| | version="2.0", |
| | docs_url="/docs", |
| | lifespan=lifespan |
| | ) |
| |
|
| | |
| | |
| | VALID_API_KEY = os.getenv("API_KEY", "sk_test_123456789") |
| |
|
| | |
| | class VoiceDetectionRequest(BaseModel): |
| | language: str = Field(..., description="Language: Tamil, English, Hindi, Malayalam, Telugu") |
| | audioFormat: str = Field(..., pattern="^(?i)mp3$", description="Must be 'mp3'") |
| | audioBase64: str = Field(..., description="Base64 encoded MP3 audio") |
| |
|
| | class VoiceDetectionResponse(BaseModel): |
| | status: str |
| | language: str |
| | classification: str |
| | confidenceScore: float |
| | explanation: str |
| |
|
| | |
| | @app.post("/api/voice-detection", response_model=VoiceDetectionResponse) |
| | async def detect_voice( |
| | request: VoiceDetectionRequest |
| | ): |
| | |
| | |
| |
|
| | try: |
| | |
| | if request.audioFormat.lower() != "mp3": |
| | |
| | raise ValueError("Only MP3 format is supported.") |
| |
|
| | |
| | try: |
| | audio_data = base64.b64decode(request.audioBase64) |
| | except Exception: |
| | raise ValueError("Invalid Base64 encoding.") |
| | |
| | if not audio_data: |
| | raise ValueError("Empty audio data.") |
| |
|
| | |
| | |
| | |
| | logger.info(f"Processing request for language: {request.language}") |
| | |
| | result = await run_in_threadpool(detector.analyze_audio, audio_data, request.language) |
| |
|
| | if "error" in result: |
| | |
| | |
| | raise ValueError(result["error"]) |
| |
|
| | |
| | return VoiceDetectionResponse( |
| | status="success", |
| | language=request.language, |
| | classification=result["classification"], |
| | confidenceScore=result["confidenceScore"], |
| | explanation=result["explanation"] |
| | ) |
| |
|
| | except ValueError as ve: |
| | logger.error(f"Validation Error: {ve}") |
| | return JSONResponse( |
| | status_code=400, |
| | content={"status": "error", "message": str(ve)} |
| | ) |
| | except Exception as e: |
| | logger.error(f"Internal Error: {e}") |
| | return JSONResponse( |
| | status_code=500, |
| | content={"status": "error", "message": "Internal server error processing audio."} |
| | ) |
| |
|
| | @app.get("/") |
| | def health_check(): |
| | return { |
| | "status": "online", |
| | "service": "AudioShield AI (Hackathon Edition)", |
| | "models_loaded": len(detector.pipelines) if hasattr(detector, 'pipelines') else 0 |
| | } |
| |
|
| | |
| |
|