CallVault — self-hosted call-recording archive: Next.js server (playback, AI transcript/summary via any OpenAI-compatible endpoint) + Expo Android sync client. Postgres on CNPG.
  • TypeScript 96.7%
  • CSS 1.7%
  • Dockerfile 0.6%
  • Python 0.5%
  • JavaScript 0.5%
Find a file
gitops fadf0d8090 backends: spread whisper + diarizer replicas across nodes
- whisper: add topologySpreadConstraints (maxSkew 1, ScheduleAnyway) — RWX
  whisper-models already allows multi-node; now 1/1/1 on hpe232/233/234.
- diarizer: remove nodeSelector pin to hpe232 + switch the model cache from the
  RWO diarizer-models PVC to a new shared RWX diarizer-models-rwx PVC (model
  data copied over, 32M). Added the same spread constraint so its 2 replicas
  land on separate nodes. Old RWO PVC left in place (unused) for now.
2026-09-26 13:19:45 +00:00
deploy backends: spread whisper + diarizer replicas across nodes 2026-09-26 13:19:45 +00:00
docs
examples
mobile
server
.gitignore
README.md

CallVault

Self-hosted "Immich for phone call recordings" — an Android sync client + a Next.js web app that archives your call recordings and adds AI transcripts & summaries via any OpenAI-compatible endpoint (your LLM router, vLLM, Ollama, LM Studio, or OpenAI itself).

┌──────────────┐   upload (multipart)   ┌────────────────────────────┐
│  Android app │ ─────────────────────▶ │  Next.js server (web UI)   │
│  (Expo/RN)   │   device bearer token  │  device auth · playback ·   │
│              │                        │  transcript · summary       │
│  scans the   │                        └─────────────┬──────────────┘
│  OS call      │                        POST /v1/audio/transcriptions
│  recordings    │                        POST /v1/chat/completions
│  (MediaStore) │                        ┌────────────▼──────────────┐
└──────────────┘                        │  OpenAI-compatible endpoint │
                                        └────────────────────────────┘
                       PostgreSQL on your existing CNPG pg-cluster-ha

Repo layout

  • server/ — Next.js (App Router) REST API + web UI. TypeScript, Drizzle ORM, pg.
  • mobile/ — Expo (React Native + TypeScript) sync client.
  • deploy/ — k3s manifests + Secret template.
  • docs/ — architecture & set-up notes.

Why this shape

  • The phone already records calls. So the app is a sync client, not a recorder: it scans MediaStore.Audio.Media (Android 10+ exposes call recordings there), uploads new ones, and can auto-delete local copies once they're uploaded and older than N days (£0 disables).
  • Expo/React Native because the web stack is Next/React/TS — shared types & DTOs, mature background upload (expo-background-task → Android WorkManager).
  • OpenAI-compatible AI means your transcript/summary models come from infra you already run.
  • PostgreSQL on your existing CNPG cluster (reused, not duplicated).

Status

  • Server: implemented + verified end-to-end against the live CNPG DB (login, device auth, upload, list, byte-range audio streaming, AI-config admin — API key never leaked).
  • Mobile: implemented, typechecks, JS bundle builds, and a signed APK (releases/CallVault-0.2.0.apk, versionCode 11) is built on the Android build host. Includes a native foreground-service background uploader (persistent notification + keeps the upload alive when the app is backgrounded) alongside the WorkManager periodic upload.
  • Deploy: manifests ready; not applied — pending NetBox IP reservation, image build, and a namespace.

See docs/SETUP.md for run/deploy instructions.