CoolFace
Apppublic

soHARSH/AASIST

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
app.py165 linesDownload Raw Back to root
1# =========================2# IMPORTS3# =========================4import gradio as gr5import torch6import torch.nn as nn7import torch.nn.functional as F8import numpy as np9import librosa10 11# =========================12# ATTENTION (REQUIRED ✅)13# =========================14class SelfAttention(nn.Module):15    def __init__(self, in_dim):16        super().__init__()17        self.query = nn.Conv1d(in_dim, in_dim // 8, 1)18        self.key = nn.Conv1d(in_dim, in_dim // 8, 1)19        self.value = nn.Conv1d(in_dim, in_dim, 1)20        self.gamma = nn.Parameter(torch.zeros(1))21 22    def forward(self, x):23        Q = self.query(x)24        K = self.key(x)25        V = self.value(x)26 27        attention = torch.bmm(Q.permute(0, 2, 1), K)28        attention = F.softmax(attention, dim=-1)29 30        out = torch.bmm(V, attention.permute(0, 2, 1))31        return self.gamma * out + x32 33 34# =========================35# MODEL (MATCH TRAINED)36# =========================37class SpoofModel(nn.Module):38    def __init__(self):39        super().__init__()40 41        # ✅ SAME NAME: cnn42        self.cnn = nn.Sequential(43            nn.Conv2d(1, 32, 3, padding=1),44            nn.BatchNorm2d(32),45            nn.ReLU(),46            nn.MaxPool2d(2),47 48            nn.Conv2d(32, 64, 3, padding=1),49            nn.BatchNorm2d(64),50            nn.ReLU(),51            nn.MaxPool2d(2),52 53            nn.Conv2d(64, 128, 3, padding=1),54            nn.BatchNorm2d(128),55            nn.ReLU(),56            nn.MaxPool2d(2),57        )58 59        # ✅ ATTENTION PRESENT60        self.attention = SelfAttention(128)61 62        # ✅ FC SIZE = 6400 (FROM ERROR)63        self.fc = nn.Sequential(64            nn.Linear(6400, 256),65            nn.ReLU(),66            nn.Dropout(0.5),67            nn.Linear(256, 2)68        )69 70    def forward(self, x):71        x = self.cnn(x)72 73        # collapse frequency74        x = torch.mean(x, dim=2)75 76        # attention77        x = self.attention(x)78 79        x = x.view(x.size(0), -1)80        return self.fc(x)81 82 83# =========================84# LOAD MODEL85# =========================86device = torch.device("cpu")87 88model = SpoofModel()89 90state_dict = torch.load("model.pth", map_location=device)91model.load_state_dict(state_dict)92 93model.to(device)94model.eval()95 96print("✅ Model loaded successfully")97 98 99# =========================100# PREPROCESS (IMPORTANT ⚠️)101# =========================102def preprocess(audio):103    sr, y = audio104 105    y = y.astype(np.float32)106 107    # stereo → mono108    if len(y.shape) > 1:109        y = np.mean(y, axis=1)110 111    # ⚠️ SAME AS TRAINING112    mel = librosa.feature.melspectrogram(113        y=y,114        sr=sr,115        n_mels=64116    )117 118    feat = librosa.power_to_db(mel)119 120    feat = (feat - np.mean(feat)) / (np.std(feat) + 1e-6)121 122    # ⚠️ LENGTH MUST MATCH TRAINING123    max_len = 400124    if feat.shape[1] < max_len:125        feat = np.pad(feat, ((0, 0), (0, max_len - feat.shape[1])))126    else:127        feat = feat[:, :max_len]128 129    feat = torch.tensor(feat).unsqueeze(0).unsqueeze(0).float()130 131    return feat132 133 134# =========================135# PREDICT136# =========================137def predict(audio):138    if audio is None:139        return {"Error": 1.0}140 141    X = preprocess(audio).to(device)142 143    with torch.no_grad():144        output = model(X)145        probs = F.softmax(output, dim=1)146 147    return {148        "Bonafide (Real)": float(probs[0][1]),149        "Spoof (Fake)": float(probs[0][0])150    }151 152 153# =========================154# UI155# =========================156demo = gr.Interface(157    fn=predict,158    inputs=gr.Audio(type="numpy", label="🎤 Upload or Record Audio"),159    outputs=gr.Label(label="🧠 Prediction"),160    title="🎙️ Voice Deepfake Detection",161    description="Detect whether audio is REAL or FAKE",162    theme="soft"163)164 165demo.launch()