import os import glob import json import time import librosa import torch from transformers import AutoModelForAudioClassification, AutoFeatureExtractor from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score def get_audio_files(): # Load all class_0 (Real/Human) and class_1 (Fake/AI) from the data directory # class_0 -> label 0 # class_1 -> label 1 files = [] # Path is relative to the backend folder when running this script, so ../data data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "data")) class_0_files = glob.glob(os.path.join(data_dir, "class_0", "*.wav")) + glob.glob(os.path.join(data_dir, "class_0", "*.mp3")) for f in class_0_files: files.append((f, 0)) class_1_files = glob.glob(os.path.join(data_dir, "class_1", "*.wav")) + glob.glob(os.path.join(data_dir, "class_1", "*.mp3")) for f in class_1_files: files.append((f, 1)) return files def get_fake_label_index(id2label): # Dynamically find which index corresponds to "fake", "spoof", "ai" # and which is "real", "human", "bonafide" fake_idx = 1 # default for idx, label in id2label.items(): l_lower = label.lower() if "fake" in l_lower or "spoof" in l_lower or "ai" in l_lower: fake_idx = idx break return fake_idx def benchmark(): models_to_test = [ "garystafford/wav2vec2-deepfake-voice-detector", "Bisher/wav2vec2_ASV_deepfake_audio_detection" ] audio_files = get_audio_files() if not audio_files: print("No audio files found in ../../data/class_0 or ../../data/class_1") return print(f"Found {len(audio_files)} total audio files for benchmarking.") results = {} for model_name in models_to_test: print(f"\n======================================") print(f"Loading Model: {model_name}") try: feature_extractor = AutoFeatureExtractor.from_pretrained(model_name) model = AutoModelForAudioClassification.from_pretrained(model_name) fake_idx = get_fake_label_index(model.config.id2label) print(f"Dynamic Label Mapping -> Fake/AI is index {fake_idx}") y_true = [] y_pred = [] start_time = time.time() for file_path, true_label in audio_files: # Target sample rate is typically 16000 for wav2vec2 models target_sr = feature_extractor.sampling_rate if hasattr(feature_extractor, "sampling_rate") else 16000 y, sr = librosa.load(file_path, sr=target_sr, mono=True) inputs = feature_extractor(y, sampling_rate=target_sr, return_tensors="pt", padding=True) with torch.no_grad(): logits = model(**inputs).logits probabilities = torch.nn.functional.softmax(logits, dim=-1) probs = probabilities[0].tolist() predicted_idx = 0 if probs[0] > probs[1] else 1 # If predicted_idx matches fake_idx, the model predicted Fake (1). Else Real (0). predicted_label = 1 if predicted_idx == fake_idx else 0 y_true.append(true_label) y_pred.append(predicted_label) elapsed = time.time() - start_time # Calculate metrics accuracy = accuracy_score(y_true, y_pred) # Use zero_division=0 to handle cases where it predicts all one class precision = precision_score(y_true, y_pred, zero_division=0) recall = recall_score(y_true, y_pred, zero_division=0) f1 = f1_score(y_true, y_pred, zero_division=0) print(f"Metrics for {model_name}:") print(f" Accuracy: {accuracy:.4f}") print(f" Precision: {precision:.4f}") print(f" Recall: {recall:.4f}") print(f" F1 Score: {f1:.4f}") print(f" Time: {elapsed:.2f}s") results[model_name] = { "accuracy": round(accuracy, 4), "precision": round(precision, 4), "recall": round(recall, 4), "f1_score": round(f1, 4), "total_time_seconds": round(elapsed, 2) } except Exception as e: print(f"Error benchmarking {model_name}: {e}") results[model_name] = { "error": str(e) } # Save results output_file = os.path.join(os.path.dirname(__file__), "..", "..", "benchmark_results.json") with open(output_file, "w") as f: json.dump(results, f, indent=4) print(f"\nBenchmark complete. Results saved to {output_file}") if __name__ == "__main__": benchmark()