A complete voice biometric authentication system β neural speaker verification, deepfake detection, challenge-response, and a full React dashboard.
Vocalyx is a production-ready voice authentication platform that verifies speakers reliably across real-world conditions β different devices, languages, accents, and vocal states β while defending against modern AI voice cloning and various replay attacks.
| Capability | How |
|---|---|
| Speaker verification | ECAPA-TDNN embeddings (SpeechBrain) β cosine similarity against enrolled voice profile |
| Neural anti-spoof | Wav2Vec2 deepfake classifier (HuggingFace) β trained to detect TTS synthesis |
| Replay attack detection | Handcrafted spectral features: reverb tail, sub-band energy ratio, noise floor, spectral flux |
| Challenge-response | 4 random words per session β Whisper transcription + fuzzy matching ensures liveness |
| Adaptive session logic | Retry escalation, threshold tightening on retries, lockout after 4 non-accepts |
| Rate limiting | 10 session starts per IP per 60 seconds β HTTP 429 on breach |
| Probe quality gate | Rejects recordings with < 2s of speech after VAD trim, before any ML inference |
| Session persistence | Completed sessions written to SQLite β survives server restarts |
| Audit logging | Every enroll, delete, and role change recorded with actor, target, and timestamp |
| Role-based access | admin / ops / user roles enforced on all endpoints and UI routes |
A React 18 + Vite dashboard ships alongside the API.
| Page | Access | What it shows |
|---|---|---|
| Dashboard | All | Stat cards (enrolled users, sessions, accept rate, locked accounts), recent sessions, system status, quick actions |
| Authenticate | All | Live recording with challenge phrase + countdown timer, per-attempt decision card |
| Enroll | All / Admin | Upload voice samples; shows enrollment status badge (new or overwrite) |
| Sessions | Admin, Ops | Full session history, auto-refreshes every 30s; expandable rows show challenge phrase and per-attempt scores |
| Voice Users | Admin | List and delete enrolled voice profiles |
| App Users | Admin | Manage dashboard accounts and roles with inline confirmation |
| Audit Log | Admin | Chronological table of all admin actions |
Audio Upload (WAV Β· FLAC Β· OGG Β· M4A Β· MP3)
β
βββββββββββββββββββββββββββββββββββββββββββββ
β Preprocessing β
β Decode β Mono β Resample (16kHz) β
β RMS Normalize β Energy VAD trim β
β Probe quality gate (β₯ 2s of speech) β
βββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββ
β Challenge Verification β
β Whisper base transcribes probe audio β
β Fuzzy-matches all 4 challenge words β
β Fail β 401 before speaker check runs β
βββββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββ¬βββββββββββββββββββββββββ
β Speaker Verif. β Anti-Spoofing β
β ECAPA-TDNN β Wav2Vec2 deepfake β
β cosine similarityβ classifier (HuggingFaceβ
β vs. enrollment β label 0=fake, 1=real) β
β β β
β Channel mismatch β Replay detector β
β detection β (spectral heuristics) β
ββββββββββββββββββββ΄βββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββ
β Decision Fusion β
β SV score (0.60) + spoof score (0.40) β
β β ACCEPT / RETRY / REJECT / STEP_UP β
βββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββ
β Session Manager β
β Multi-attempt Β· threshold tightening β
β Lockout after 4 non-accepts β
β Terminal sessions logged to SQLite β
βββββββββββββββββββββββββββββββββββββββββββββ
β
FastAPI REST API + React Dashboard
Backend
- Python 3.10, PyTorch, torchaudio
- SpeechBrain β ECAPA-TDNN speaker embeddings (
spkrec-ecapa-voxceleb) - Hugging Face Transformers β Wav2Vec2 deepfake classifier, Whisper transcription
- FastAPI + Uvicorn β REST API
- SQLite β session history, audit log, dashboard accounts
- imageio-ffmpeg β self-contained audio decoder for M4A/MP3 (no system FFmpeg needed)
- python-jose β JWT authentication
Frontend
- React 18 + Vite 5
- React Router v6
- Web Audio API (MediaRecorder β WAV via AudioContext)
| Component | Model |
|---|---|
| Speaker embeddings | speechbrain/spkrec-ecapa-voxceleb |
| Deepfake / anti-spoof | motheecreator/Deepfake-audio-detection (Wav2Vec2) |
| Challenge transcription | openai/whisper-base |
Model weights are downloaded once and cached in ~/.cache/huggingface/ and ~/speechbrain/.
- Anaconda or Miniconda
- Python 3.10
- Node.js 18+
git clone https://github.com/SNMiguel/Vocalyx.git
cd Vocalyx
conda create -n voice-biometrics python=3.10 -y
conda activate voice-biometrics
pip install -r requirements.txt
cd ui && npm install && cd ..conda activate voice-biometrics
python -m uvicorn src.api.server:app --host 0.0.0.0 --port 8000First start takes ~30β60 seconds β Wav2Vec2 and Whisper model weights are downloaded and cached on first run.
Verify it's ready:
curl http://localhost:8000/healthcd ui && npm run dev
# Dashboard at http://localhost:5173| Username | Password | Role |
|---|---|---|
admin |
admin123 |
admin |
Change these in configs/api.yaml before deploying.
- Start a session β
POST /sessionsreturns asession_idand a 4-wordchallengephrase with a 10-second countdown. - Record audio β user speaks the challenge phrase into the microphone.
- Submit probe β
POST /authenticatewith the audio file and session ID. - Pipeline runs β challenge verified β speaker score computed β anti-spoof score computed β decision fused.
- Decision returned β
ACCEPT,RETRY,REJECT, orSTEP_UP.
Sessions lock after 4 non-accept attempts. Threshold tightens by 0.02 per retry.
| Method | Endpoint | Access | Description |
|---|---|---|---|
POST |
/auth/login |
Public | Exchange credentials for a JWT |
POST |
/auth/register |
Public | Create a new account (role: user) |
GET |
/auth/me |
Authenticated | Current user info |
GET |
/auth/users |
Admin | List all dashboard accounts |
PATCH |
/auth/users/{username} |
Admin | Change a user's role |
DELETE |
/auth/users/{username} |
Admin | Delete a dashboard account |
| Method | Endpoint | Access | Description |
|---|---|---|---|
POST |
/enroll |
Authenticated | Enroll a user with one or more audio files |
GET |
/users |
Authenticated | List all enrolled voice users |
GET |
/users/{user_id} |
Public | Check if a voice user is enrolled |
DELETE |
/users/{user_id} |
Admin | Delete a voice enrollment |
POST |
/sessions |
Authenticated | Start an authentication session |
GET |
/sessions |
Admin, Ops | List all sessions (history + active) |
GET |
/sessions/{id} |
Authenticated | Session status and attempt history |
POST |
/authenticate |
Authenticated | Submit a probe audio for a session |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/audit |
Admin | Retrieve the audit log |
GET |
/health |
Public | Service liveness and enrolled user count |
GET |
/version |
Public | Pipeline version and component list |
Interactive API docs at http://localhost:8000/docs.
| Role | Capabilities |
|---|---|
admin |
Full access β enroll anyone, delete profiles, manage accounts, change roles, view audit log |
ops |
Read-only β view sessions and session history |
user |
Self-service β enroll and authenticate as themselves only |
| Attack vector | Mitigation |
|---|---|
| Digital replay (same file re-submitted) | Upload removed from auth β live microphone recording only |
| Acoustic replay (phone playing pre-recorded audio) | Challenge-response: pre-recorded audio won't contain the session's 4 words |
| Wrong speaker | ECAPA-TDNN embedding distance β genuine users score 0.70+, impostors fall below 0.25 threshold |
| AI voice cloning (ElevenLabs, etc.) | Wav2Vec2 deepfake classifier + replay detector; neural TTS remains the hardest attack vector |
| Brute-force | Session lockout after 4 non-accepts; rate limit of 10 sessions/IP/min |
| Short/silent recordings | Probe quality gate rejects < 2s of speech after VAD |
vocalyx/
βββ configs/
β βββ api.yaml # Server config: JWT secret, admin credentials, thresholds
βββ src/
β βββ preprocessing/
β β βββ audio_loader.py # Load and resample to 16kHz
β β βββ normalization.py # RMS normalization
β β βββ vad.py # Energy-based VAD trim
β β βββ denoiser.py # noisereduce wrapper (disabled β conda DLL conflict)
β βββ enrollment/
β β βββ embedder.py # ECAPA-TDNN via SpeechBrain
β β βββ enrollment_db.py # .pt embedding store
β βββ antispoofing/
β β βββ deepfake_detector.py # Wav2Vec2 neural deepfake classifier
β β βββ replay_detector.py # Spectral replay heuristics
β β βββ channel_mismatch.py # Device-switch detection
β β βββ fusion.py # Deepfake + replay score fusion (0.60/0.40)
β βββ decision/
β β βββ fusion_layer.py # SV + spoof β ACCEPT/RETRY/REJECT/STEP_UP
β β βββ session.py # Session state, challenge generation, lockout
β βββ api/
β βββ server.py # FastAPI app, all endpoints, lifespan startup
β βββ auth_router.py # JWT login, register, user management
β βββ app_db.py # SQLite: dashboard accounts, sessions, audit log
β βββ models.py # Pydantic request/response models
βββ ui/
β βββ src/
β βββ pages/
β β βββ Dashboard.jsx # Stat cards, recent sessions, system status
β β βββ Authenticate.jsx# Live recording, challenge countdown, DecisionCard
β β βββ Enroll.jsx # Audio upload with enrollment status badge
β β βββ Sessions.jsx # Session history with auto-refresh
β β βββ Users.jsx # Voice profile management (admin)
β β βββ AppUsers.jsx # Dashboard account management (admin)
β β βββ AuditLog.jsx # Admin action history (admin)
β βββ components/
β β βββ Layout.jsx # Sidebar, nav, role-aware links
β β βββ ProtectedRoute.jsx
β βββ contexts/
β β βββ AuthContext.jsx # JWT auth state
β βββ hooks/
β β βββ useAudioRecorder.js # MediaRecorder β WAV blob
β βββ api.js # Typed fetch wrappers for all endpoints
βββ data/
β βββ app.db # SQLite database (auto-created)
β βββ embeddings/ # Enrolled voice profiles (.pt files)
βββ requirements.txt
Edit configs/api.yaml:
auth:
secret_key: "change-me-in-production"
token_expire_minutes: 60
admin_username: admin
admin_password: admin123Decision thresholds (in src/decision/fusion_layer.py):
| Parameter | Default | Meaning |
|---|---|---|
sv_accept_threshold |
0.25 | Cosine similarity above this β speaker verified |
sv_retry_threshold |
0.15 | Between 0.15β0.25 β retry |
spoof_reject_threshold |
0.50 | Spoof score above this β reject |
spoof_retry_threshold |
0.35 | Between 0.35β0.50 β retry |
Genuine speaker scores 0.70+ in testing. Do not lower thresholds without new calibration data.
- AI voice cloning β modern neural TTS (ElevenLabs, RVC) could potentially pass both speaker verification and Wav2Vec2. A PIN or TOTP second factor would close this gap.
- Rate limit not persisted β in-memory buckets reset on server restart.
- Noisereduce disabled β a conda DLL conflict (
gdk_pixbuf) crashes scipy on this environment. Re-enable after fixing the env and re-enroll all users (processing must match enrollment). - Single-process enrollment DB β the
.ptembedding store is not safe for concurrent writes across multiple Uvicorn workers. Use--workers 1or migrate to a proper DB for multi-worker deployments.
MIT License β see LICENSE for details.
Miguel β github.com/SNMiguel