Skip to content

Repository files navigation

Transcriber

Local-first meeting transcription for phone recordings and exported audio/video files.

This app is intentionally small: drop an .m4a, .mp3, .mp4, .wav, etc. into a local web UI or run the CLI, then get a Markdown transcript with speaker labels that is easy to paste into AI agents.

What it is good at

  • Private batch transcription of iPhone Voice Memos / meeting recordings.
  • Speaker diarization with pyannote.audio.
  • Apple Silicon inference with mlx-whisper.
  • NVIDIA/CUDA inference with faster-whisper for machines such as an RTX 5090.
  • Language hints for multilingual calls, especially English, Turkish, and Hungarian.
  • Exact speaker-count hints when you know the call had 1, 2, or 3 speakers.

Recommended Quality Stack

For best multilingual meeting quality:

  • ASR: Whisper large-v3 full for important calls.
  • Fast ASR: Whisper large-v3-turbo for quick drafts.
  • Apple Silicon runtime: mlx-whisper.
  • NVIDIA runtime: faster-whisper / CTranslate2 with float16.
  • Diarization: pyannote/speaker-diarization-3.1.
  • Best practical setting: set the language mode and exact speaker count when known. For code-switched calls, use tr-en or hu-en instead of forcing only one language.

For English-only benchmarking on NVIDIA GPUs, also test NVIDIA Parakeet/Canary outside this app. They are promising, but Whisper large-v3 remains the safest baseline for multilingual meeting notes.

Setup: Apple Silicon

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env

Edit .env and set HF_TOKEN. You must accept the Hugging Face terms for:

  • pyannote/speaker-diarization-3.1
  • pyannote/segmentation-3.0

Start the local UI:

./run.sh

Open http://127.0.0.1:8765. The server only binds to localhost.

To expose the UI only on a trusted private interface such as Tailscale, set the host explicitly:

TRANSCRIBER_HOST=100.x.y.z ./run.sh

For remote use, also set TRANSCRIBER_ACCESS_TOKEN in .env. The browser will ask for HTTP Basic Auth with username transcriber and that token as password.

Setup: NVIDIA / CUDA

On Linux with a recent NVIDIA driver:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-cuda.txt
cp .env.example .env

Set:

WHISPER_ENGINE=faster-whisper
FASTER_WHISPER_DEVICE=cuda
FASTER_WHISPER_COMPUTE_TYPE=float16

For RTX 5090 / Blackwell, requirements-cuda.txt pins PyTorch 2.11.0+cu128 from the official PyTorch cu128 wheel index so torch recognizes sm_120.

For RTX 4090 / Ada, use the pyannote-compatible CUDA stack:

pip install -r requirements-cuda-rtx40.txt

CLI example for a two-person investor call:

./cli.sh --engine faster-whisper --quality full --lang tr-en --speakers 2 call.m4a

Use

Web UI:

./run.sh

Tailscale/LAN UI:

TRANSCRIBER_HOST=100.x.y.z ./run.sh

Set TRANSCRIBER_ACCESS_TOKEN first when binding to anything other than 127.0.0.1.

CLI:

./cli.sh --lang en --quality turbo meeting.m4a
./cli.sh --lang tr-en --quality full --speakers 2 investor-call.m4a
./cli.sh --engine faster-whisper --quality full --speakers 2 meeting.m4a

Outputs are saved under ./transcripts/.

Prefetch Models

The first use of a model downloads weights into the Hugging Face cache. That cache survives app restarts, but a first full-v3 run may spend several minutes downloading about 3 GB before transcription starts.

Download the quality-first MLX model ahead of time:

./prefetch.sh --quality full

Download both MLX models:

./prefetch.sh --quality all

Model Notes

  • turbo maps to mlx-community/whisper-large-v3-turbo on MLX and large-v3-turbo on faster-whisper.
  • full maps to mlx-community/whisper-large-v3-mlx on MLX and large-v3 on faster-whisper.
  • Turkish/Hungarian important calls should usually use --quality full plus --lang tr or --lang hu.
  • Mixed Turkish/English or Hungarian/English calls should use --lang tr-en or --lang hu-en; this avoids over-forcing one language while still giving Whisper meeting context.
  • Speaker labels improve when you pass --speakers 2 for two-person calls.
  • MLX disables condition_on_previous_text by default because it can cause long repetition loops on difficult audio. Set MLX_CONDITION_ON_PREVIOUS_TEXT=1 only if you specifically want to experiment.
  • Obvious Whisper repetition loops are rejected instead of being saved as finished transcripts.

What This Is Not

This is not a Fireflies/Otter/Vexa-style meeting bot that joins Zoom, Google Meet, or Teams. It is the local, high-quality file transcription core. Projects like Vexa solve live meeting bot infrastructure; this project focuses on local files from your phone and high-quality transcripts for AI context.

Files

  • app/main.py - FastAPI server.
  • app/transcribe.py - ffmpeg, diarization, ASR, speaker assignment, Markdown output.
  • static/index.html - local drag-and-drop UI.
  • cli.py / cli.sh - one-shot transcription without the web server.
  • requirements.txt - Apple Silicon default.
  • requirements-cuda.txt - NVIDIA/CUDA default for RTX 50-series.
  • requirements-cuda-rtx40.txt - NVIDIA/CUDA default for RTX 40-series.

Public Repo Hygiene

The repo ignores:

  • .env
  • .venv/
  • uploads/
  • transcripts/
  • caches and bytecode

Do not commit real recordings, transcripts, or Hugging Face tokens.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages