RGriya commited on
Commit
2df6447
·
verified ·
1 Parent(s): dd49b9c

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +16 -0
  2. README.md +29 -0
  3. app.py +89 -0
  4. requirements.txt +8 -0
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apt-get update && apt-get install -y \
6
+ libsndfile1 ffmpeg \
7
+ && rm -rf /var/lib/apt/lists/*
8
+
9
+ COPY requirements.txt .
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ COPY app.py .
13
+
14
+ EXPOSE 7860
15
+
16
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Deepfake Audio Detection API
3
+ emoji: 🎙️
4
+ colorFrom: purple
5
+ colorTo: blue
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ ---
10
+
11
+ # Deepfake Audio Detection API
12
+
13
+ REST API for detecting AI-generated / deepfake audio using Wav2Vec2 (98.82% accuracy).
14
+
15
+ ## Endpoints
16
+
17
+ **GET /health**
18
+ ```json
19
+ {"status": "ok"}
20
+ ```
21
+
22
+ **POST /detect** — send audio file as multipart form
23
+ ```bash
24
+ curl -X POST https://rgriya-deepfake-audio-api.hf.space/detect \
25
+ -F "file=@your_audio.wav"
26
+ ```
27
+ ```json
28
+ {"label": "fake", "fake": 0.97, "real": 0.03}
29
+ ```
app.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pure FastAPI — no Gradio dependency at all.
3
+ HuggingFace Spaces serves FastAPI apps directly.
4
+
5
+ GET /health → {"status":"ok"}
6
+ POST /detect → multipart file=<audio> → {"label":"fake","fake":0.97,"real":0.03}
7
+ """
8
+ import io
9
+ import numpy as np
10
+ import soundfile as sf
11
+ from fastapi import FastAPI, File, UploadFile, HTTPException
12
+ from fastapi.responses import HTMLResponse
13
+ from transformers import pipeline
14
+ import torch
15
+
16
+ MODEL = "mo-thecreator/Deepfake-audio-detection"
17
+ print(f"Loading {MODEL} ...")
18
+ classifier = pipeline(
19
+ "audio-classification",
20
+ model=MODEL,
21
+ device=0 if torch.cuda.is_available() else -1,
22
+ )
23
+ print("Model ready.")
24
+
25
+ app = FastAPI(title="Deepfake Audio Detection")
26
+
27
+
28
+ def classify(raw_bytes: bytes) -> dict:
29
+ buf = io.BytesIO(raw_bytes)
30
+ try:
31
+ data, sr = sf.read(buf, dtype="float32", always_2d=False)
32
+ except Exception:
33
+ import librosa
34
+ buf.seek(0)
35
+ data, sr = librosa.load(buf, sr=16000, mono=True)
36
+ sr = 16000
37
+
38
+ if data.ndim > 1:
39
+ data = data.mean(axis=1)
40
+ peak = np.abs(data).max()
41
+ if peak > 1.0:
42
+ data /= peak
43
+ if sr != 16000:
44
+ import librosa
45
+ data = librosa.resample(data, orig_sr=sr, target_sr=16000)
46
+
47
+ out = io.BytesIO()
48
+ sf.write(out, data, 16000, format="WAV", subtype="PCM_16")
49
+ out.seek(0)
50
+
51
+ results = classifier(out.read())
52
+ print(f"Results: {results}")
53
+ scores = {r["label"]: float(r["score"]) for r in results}
54
+ return {"label": max(scores, key=scores.get), **scores}
55
+
56
+
57
+ @app.get("/", response_class=HTMLResponse)
58
+ def root():
59
+ return """
60
+ <html><body style="font-family:sans-serif;max-width:600px;margin:40px auto;padding:20px">
61
+ <h2>🎙️ Deepfake Audio Detection API</h2>
62
+ <p>Model: <code>mo-thecreator/Deepfake-audio-detection</code> (Wav2Vec2, 98.82% accuracy)</p>
63
+ <h3>Endpoints</h3>
64
+ <code>GET /health</code> — health check<br><br>
65
+ <code>POST /detect</code> — multipart <code>file=&lt;audio&gt;</code><br>
66
+ <pre>{"label": "fake", "fake": 0.97, "real": 0.03}</pre>
67
+ <h3>Test</h3>
68
+ <form action="/detect" method="post" enctype="multipart/form-data">
69
+ <input type="file" name="file" accept="audio/*">
70
+ <button type="submit">Detect</button>
71
+ </form>
72
+ </body></html>
73
+ """
74
+
75
+
76
+ @app.get("/health")
77
+ def health():
78
+ return {"status": "ok", "model": MODEL}
79
+
80
+
81
+ @app.post("/detect")
82
+ async def detect(file: UploadFile = File(...)):
83
+ try:
84
+ raw = await file.read()
85
+ print(f"/detect: {len(raw)} bytes filename={file.filename}")
86
+ return classify(raw)
87
+ except Exception as e:
88
+ import traceback; traceback.print_exc()
89
+ raise HTTPException(status_code=500, detail=str(e))
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi>=0.110.0
2
+ uvicorn>=0.29.0
3
+ transformers>=4.39.0
4
+ torch>=2.0.0
5
+ torchaudio>=2.0.0
6
+ librosa>=0.10.0
7
+ soundfile>=0.12.0
8
+ python-multipart>=0.0.9