Practice HR, technical, and coding interviews against an AI interviewer that transcribes your spoken answers, watches your camera for engagement signals, scores your code, and gives you a full report at the end — clarity, technical correctness, confidence, and engagement, all tracked over time.
- Voice interview — record spoken answers in the browser, transcribed via OpenAI's Whisper (
faster-whisper, runs locally/self-hosted — no audio ever leaves your server) - Camera analysis — periodic webcam frame capture during recording
- Engagement heuristics — face detection, eye-contact estimation, and a lightweight smile/engagement signal, computed with OpenCV Haar cascades (see note below)
- Resume-based questions — upload a resume (PDF/DOCX/TXT); Gemini tailors HR/technical questions to your actual experience
- Coding interview — live Monaco code editor, sandboxed Python execution with timeout + memory limits, correctness scoring
- HR & Technical interview modes — separate question pools and evaluation rubrics
- AI feedback — Gemini scores each answer for clarity/relevance (and correctness for code), then writes a full closing summary with strengths and improvement areas
- Interview report & score dashboard — per-session report plus a running trend chart across all your past sessions
| Layer | Technology |
|---|---|
| Speech-to-text | Whisper via faster-whisper (self-hosted, no external API) |
| Camera analysis | OpenCV (Haar cascades) |
| LLM | Google Gemini (google-genai SDK) — optional, falls back to templates without a key |
| Backend | FastAPI, SQLAlchemy, SQLite, JWT auth |
| Frontend | React 18, Vite, Tailwind CSS, Monaco Editor, Recharts |
| Deployment | Docker + docker-compose, nginx |
ai-mock-interview-platform/
├── backend/
│ ├── app/
│ │ ├── core/ # config, database, security, auth deps
│ │ ├── models/ # SQLAlchemy models
│ │ ├── schemas/ # Pydantic request/response schemas
│ │ ├── routers/ # auth, resume, interview, voice, vision, coding
│ │ ├── services/ # gemini_service, whisper_service, vision_service, scoring_service
│ │ ├── utils/ # resume_parser
│ │ └── main.py
│ ├── requirements.txt
│ ├── Dockerfile
│ └── .env.example
├── frontend/
│ ├── src/
│ │ ├── pages/ # Login, Register, Dashboard, InterviewRoom, Report
│ │ ├── components/ # Navbar, ConfidenceRing, ProtectedRoute
│ │ ├── context/ # AuthContext
│ │ └── services/ # api.js, interviewService.js
│ ├── Dockerfile
│ ├── nginx.conf
│ └── .env.example
├── docker-compose.yml
└── LICENSE
Choose mode (HR / Technical / Coding) + optional resume
│
▼
Gemini generates N tailored questions (falls back to a curated
question bank per mode if no API key is set)
│
▼
Per question:
HR/Technical → record voice (Whisper transcribes) + webcam frames
(OpenCV estimates eye contact / engagement)
Coding → write & run code in Monaco, sandboxed execution
│
▼
Gemini scores the answer (clarity, relevance, correctness) and
gives short per-question feedback
│
▼
After the last question: Gemini writes a closing summary,
scores are aggregated into Communication / Technical / Confidence /
Engagement / Overall — all shown on the report + dashboard trend chart
cd backend
python3 -m venv venv && source venv/bin/activate # optional but recommended
pip install -r requirements.txt
cp .env.example .env
# GEMINI_API_KEY is optional but recommended for real AI-generated
# questions/feedback instead of the offline template fallback.
uvicorn app.main:app --reload --port 8000Backend runs at http://localhost:8000. Interactive API docs at http://localhost:8000/docs.
First run note:
faster-whisperdownloads its model weights the first time it's used (a one-time download, cached afterward). SetWHISPER_MODEL_SIZE=tinyin.envfor the fastest/smallest option during development.
cd frontend
npm install
cp .env.example .env
npm run devFrontend runs at http://localhost:5174 and proxies /api/* to the backend.
cp backend/.env.example backend/.env # fill in GEMINI_API_KEY if you have one
docker compose up --build- Frontend:
http://localhost - Backend API:
http://localhost:8000
| Variable | Required? | Purpose |
|---|---|---|
SECRET_KEY |
Yes | JWT signing secret — generate a real random value for production |
GEMINI_API_KEY |
No | Enables AI-generated questions/feedback/reports; falls back to templates without it |
WHISPER_MODEL_SIZE |
No | tiny/base/small/medium/large-v3 — trade off speed vs. accuracy |
DATABASE_URL |
No | Defaults to local SQLite; point at Postgres for production |
cd backend
pip install -r requirements.txt # includes pytest
pytest tests/ -vThe suite covers auth, the full interview lifecycle (create → answer →
complete → scored report), access control (you can't view someone else's
interview), and the coding sandbox (correct output, error capture, and the
5-second timeout on infinite loops — that test genuinely waits out the
timeout, so the suite takes a few seconds longer than you'd expect). CI runs
this on every push via GitHub Actions (.github/workflows/ci.yml), alongside
a frontend build check.
The engagement/emotion signal is built with OpenCV's bundled Haar cascade classifiers (face, eye, and smile detection) rather than a deep-learning emotion model. This was a deliberate trade-off: it ships fully working with zero external model downloads and no GPU requirement, which matters for a "clone and run" portfolio project — a Tasks-API/MediaPipe or FER2013-CNN approach would need model weight files fetched at runtime, adding a hard external dependency that can silently break in an offline or restricted-network deployment.
If you want to swap in a trained deep-learning emotion classifier for higher
accuracy, app/services/vision_service.py is the only file you need to touch
— analyze_frame() has a clear, self-contained contract (base64 image in,
{face_detected, dominant_emotion, emotion_scores, eye_contact, head_pose} out).
app/routers/coding.py executes submitted Python in a subprocess with a
CPU/wall-clock timeout and a memory limit — reasonable for a personal
portfolio/demo project. If you deploy this publicly, replace it with a
properly isolated per-request container (Docker-in-Docker, gVisor,
Firecracker) or a managed code-execution service (Judge0, Piston) before
allowing untrusted users to submit code.
- More languages in the coding round:
coding.pycurrently only runs Python; add language-specific Docker sandboxes for JS/Java/C++. - Live WebSocket streaming: replace the record→upload→transcribe flow with a streaming Whisper pipeline for real-time transcription as you speak.
- Video review: save short clips per answer so candidates can watch themselves back alongside the transcript.
- Team/interviewer mode: let a real interviewer review AI transcripts and override scores.
MIT — see LICENSE.