import base64 import json from fastapi import FastAPI, HTTPException, Depends, Header, Request, Body from schemas import AudioInput, DetectionResult from model_service import get_model_service, ModelService app = FastAPI(title="AI Voice Detection API", version="1.0.0") @app.on_event("startup") async def startup_event(): # Fixes 504 Timeout print("API is starting up...") API_KEY = "my_secret_key_123" async def verify_api_key(x_api_key: str = Header(...)): if x_api_key != API_KEY: raise HTTPException(status_code=401, detail="Invalid API Key") return x_api_key @app.post("/detect", response_model=DetectionResult) async def detect_voice( request: Request, payload: dict = Body(..., example={"audioBase64": "PASTE_HERE"}), service: ModelService = Depends(get_model_service), api_key: str = Depends(verify_api_key) ): try: audio_b64 = None # Try JSON first (Portal vs Manual) try: body = await request.json() keys = ["audioBase64", "audio_base_64", "audio", "data", "file"] for k in keys: if k in body and body[k]: audio_b64 = body[k] break if not audio_b64: for v in body.values(): if isinstance(v, str) and len(v) > 100: audio_b64 = v break except Exception: # FALLBACK: Handle if the body is just the raw Base64 string raw_body = await request.body() audio_b64 = raw_body.decode('utf-8') if not audio_b64 or len(str(audio_b64)) < 20: raise HTTPException(status_code=422, detail="No valid audio data.") # CLEANUP: Remove quotes, spaces, and Data URI prefix audio_b64 = str(audio_b64).strip().strip('"').strip("'") if "," in audio_b64: audio_b64 = audio_b64.split(",")[1] audio_bytes = base64.b64decode(audio_b64) except Exception as e: if isinstance(e, HTTPException): raise e raise HTTPException(status_code=400, detail=f"Parsing error: {str(e)}") try: # Inference (HUMAN or AI_GENERATED) label, confidence = service.predict(audio_bytes) return DetectionResult(label=label, confidence=confidence, message="Analysis successful") except Exception as e: raise HTTPException(status_code=500, detail=f"Model error: {str(e)}") @app.get("/") def read_root(): return {"status": "Running"}