The Problem

Teams that record meetings, interviews, or lectures need a way to turn raw audio into searchable, annotated notes that stay on their own infrastructure. Existing cloud services expose sensitive data, while local tools lack an end‑to‑end workflow for capture, transcription, speaker diarization, and knowledge extraction.

What This Does

Speakr stitches together a full pipeline in a single Docker image.

  • Capture: the web UI (templates/index.html, static/js/modules/composables/index.js) streams microphone or system audio to the Flask backend (src/app.py).
  • Transcribe: the /api/v1/transcriptions endpoint (src/api/recordings.py) forwards audio to an ASR connector chosen via environment config (config/env.asr.example).
  • Post‑process: WhisperX‑based diarization happens in src/api/recordings.py and speaker embeddings are stored through src/api/folders.py.
  • Insights: summaries and event extraction are triggered by src/api/inquire.py, which calls the prompt engine defined in src/api/naming_templates.py.

The result is a searchable transcript visualized in the React client (static/js/modules/computed/index.js).

How It Is Wired

Entry Point

src/app.py starts the Flask app.

app = Flask(__name__)
api = Api(app)

It imports the API namespace from src/api/__init__.py, which registers blueprints such as recordings, groups, and inquire.

Control Flow

  1. HTTP request → Flask route in src/api/recordings.py (e.g., @recordings.route('/upload', methods=['POST'])).
  2. File handling → src/api/utils.py writes the incoming FileStorage to the local UPLOADS directory.
  3. ASR dispatch → src/api/asr.py reads os.getenv('ASR_BACKEND') and routes the file to the matching connector (src/api/whisperx.py, src/api/openai.py).
  4. Post‑process → returned JSON is enriched by src/api/recordings.py calling src/api/diarization.py and src/api/embeddings.py.
  5. Database write → src/models.py (SQLAlchemy models) persists Recording, Transcript, and Speaker rows.
  6. Response → Flask sends JSON back to the React client.

External Touches

  • Filesystem: uploads to /data/uploads, temp files in /tmp.
  • Database: SQLite or PostgreSQL depending on SQLALCHEMY_DATABASE_URI.
  • Network: outbound calls to external ASR APIs if configured, otherwise local WhisperX subprocesses.

The core hub is src/app.py; all external side effects originate from the API blueprints, keeping the frame of reference narrow.

How To Use It

Setup

git clone https://github.com/moses-y/speakr
cd speakr
docker build -t speakr .

The image pulls dependencies from requirements.txt and package.json.

Configuration

Create a .env file based on the examples:

cp config/env.asr.example .env
cp config/env.email.example .env

Set:

  • ASR_BACKEND=whisperx
  • DATABASE_URL=sqlite:///data/db.sqlite
  • SECRET_KEY= (random 32‑byte string)

Running

docker run -d -p 5000:5000 --env-file .env speakr

or with Compose:

docker-compose -f config/docker-compose.example.yml up -d

The server is reachable at http://localhost:5000.

Real-World Use

A research lab records interviews, then uploads them to Speakr. The lab’s CI pipeline runs scripts/migrate_docker.sh to move older recordings to S3, while a scheduled job (scripts/backfill_audio_duration_seconds.py) re‑indexes durations. Researchers query the transcript via the /api/v1/inquire endpoint, receiving timestamped answers that link back to the original audio.

Code Health & Issues

  • Low risk – package.json declares dependencies without a lockfile, potentially leading to non‑reproducible builds (package.json line 12).
  • Missing lockfile – no pnpm-lock.yaml or yarn.lock (package.json only).
  • No tests for API validation – only 116 test files, many targeting frontend utilities.
  • Documentation gaps – docs/user-guide/api-reference.md references endpoints that lack implementation comments.

The Bottom Line

Speakr delivers a fully self‑hosted transcription workflow bundled in Docker, suitable for privacy‑conscious teams. Its modular API and clear entry points make it approachable for contributors, though the lack of a JavaScript lockfile and sparse API documentation may slow onboarding. Organizations needing end‑to‑end audio‑to‑knowledge pipelines on premises will find it a solid foundation.