Views
No views yet
| Language | Accuracy | Female Recall | Male Recall |
|---|---|---|---|
| English | 99.5% | 99.5% | 99.5% |
| Hindi | 99.2% | 100.0% | 98.4% |
| Tamil | 99.2% | 100.0% | 98.3% |
| Overall | 99.3% | 99.8% | 99.1% |
pip install speechbrain torchaudio soundfile scikit-learn joblib huggingface_hub1import json
2import numpy as np
3import soundfile as sf
4import torch
5import joblib
6from huggingface_hub import hf_hub_download
7from speechbrain.inference.speaker import EncoderClassifier
8
9REPO = "moorlee/gender-voice-classifier-ecapa"
10
11# Download the 3 lightweight head files (total < 10 KB)
12scaler = joblib.load(hf_hub_download(REPO, "scaler.pkl"))
13clf = joblib.load(hf_hub_download(REPO, "logreg.pkl"))
14threshold = json.load(open(hf_hub_download(REPO, "thresholds.json")))["female_optimized"]
15
16# Load frozen ECAPA backbone — downloads ~100 MB once, cached after that
17encoder = EncoderClassifier.from_hparams(
18 source="speechbrain/spkrec-ecapa-voxceleb",
19 run_opts={"device": "cpu"},
20)
21encoder.eval()
22
23def predict_gender(path: str) -> str:
24 arr, sr = sf.read(path, dtype="float32")
25 if arr.ndim > 1:
26 arr = arr.mean(axis=1) # stereo → mono
27 if sr != 16000:
28 import torchaudio
29 arr = torchaudio.transforms.Resample(sr, 16000)(
30 torch.tensor(arr).unsqueeze(0)
31 ).squeeze(0).numpy()
32 with torch.no_grad():
33 emb = encoder.encode_batch(torch.tensor(arr).unsqueeze(0)).squeeze().numpy()
34 p_female = float(clf.predict_proba(scaler.transform(emb.reshape(1, -1)))[0, 1])
35 return "female" if p_female >= threshold else "male"
36
37print(predict_gender("your_voice.wav")) # → "female" or "male"Audio (any format / sample rate)
→ resample to 16 kHz, mono
→ ECAPA-TDNN (frozen, speechbrain/spkrec-ecapa-voxceleb)
→ 192-dim speaker embedding
→ StandardScaler (fit on training set)
→ LogisticRegression (193 parameters: 192 weights + 1 bias)
→ P(female) vs calibrated threshold
→ "female" / "male"| Dataset | Languages | Clips used | Gender balance |
|---|---|---|---|
| Google FLEURS | en_us, hi_in, ta_in | 4,878 | 50 / 50 per language |
audeering/wav2vec2-large-robust-24-ft-age-gender is 1.2 GB and uses a 3-class gender head (child / female / male). High-F0 female voices are frequently absorbed into the child class, causing poor female recall. This model uses a binary head only, eliminating that confusion, at a fraction of the size.1@inproceedings{desplanques2020ecapa,
2 title = {ECAPA-TDNN: Emphasized Channel Attention, Propagation and Aggregation in TDNN Based Speaker Verification},
3 author = {Desplanques, Brecht and Thienpondt, Jenthe and Demuynck, Kris},
4 booktitle = {Interspeech},
5 year = {2020}
6}