Spaces:
Running
Running
| """ | |
| Pure FastAPI β no Gradio dependency at all. | |
| HuggingFace Spaces serves FastAPI apps directly. | |
| GET /health β {"status":"ok"} | |
| POST /detect β multipart file=<audio> β {"label":"fake","fake":0.97,"real":0.03} | |
| """ | |
| import io | |
| import numpy as np | |
| import soundfile as sf | |
| from fastapi import FastAPI, File, UploadFile, HTTPException | |
| from fastapi.responses import HTMLResponse | |
| from transformers import pipeline | |
| import torch | |
| MODEL = "mo-thecreator/Deepfake-audio-detection" | |
| print(f"Loading {MODEL} ...") | |
| classifier = pipeline( | |
| "audio-classification", | |
| model=MODEL, | |
| device=0 if torch.cuda.is_available() else -1, | |
| ) | |
| print("Model ready.") | |
| app = FastAPI(title="Deepfake Audio Detection") | |
| def classify(raw_bytes: bytes) -> dict: | |
| buf = io.BytesIO(raw_bytes) | |
| try: | |
| data, sr = sf.read(buf, dtype="float32", always_2d=False) | |
| except Exception: | |
| import librosa | |
| buf.seek(0) | |
| data, sr = librosa.load(buf, sr=16000, mono=True) | |
| sr = 16000 | |
| if data.ndim > 1: | |
| data = data.mean(axis=1) | |
| peak = np.abs(data).max() | |
| if peak > 1.0: | |
| data /= peak | |
| if sr != 16000: | |
| import librosa | |
| data = librosa.resample(data, orig_sr=sr, target_sr=16000) | |
| out = io.BytesIO() | |
| sf.write(out, data, 16000, format="WAV", subtype="PCM_16") | |
| out.seek(0) | |
| results = classifier(out.read()) | |
| print(f"Results: {results}") | |
| scores = {r["label"]: float(r["score"]) for r in results} | |
| return {"label": max(scores, key=scores.get), **scores} | |
| def root(): | |
| return """ | |
| <html><body style="font-family:sans-serif;max-width:600px;margin:40px auto;padding:20px"> | |
| <h2>ποΈ Deepfake Audio Detection API</h2> | |
| <p>Model: <code>mo-thecreator/Deepfake-audio-detection</code> (Wav2Vec2, 98.82% accuracy)</p> | |
| <h3>Endpoints</h3> | |
| <code>GET /health</code> β health check<br><br> | |
| <code>POST /detect</code> β multipart <code>file=<audio></code><br> | |
| <pre>{"label": "fake", "fake": 0.97, "real": 0.03}</pre> | |
| <h3>Test</h3> | |
| <form action="/detect" method="post" enctype="multipart/form-data"> | |
| <input type="file" name="file" accept="audio/*"> | |
| <button type="submit">Detect</button> | |
| </form> | |
| </body></html> | |
| """ | |
| def health(): | |
| return {"status": "ok", "model": MODEL} | |
| async def detect(file: UploadFile = File(...)): | |
| try: | |
| raw = await file.read() | |
| print(f"/detect: {len(raw)} bytes filename={file.filename}") | |
| return classify(raw) | |
| except Exception as e: | |
| import traceback; traceback.print_exc() | |
| raise HTTPException(status_code=500, detail=str(e)) | |