Skip to main content

Drop-in CLI transcription. Groq by default, local Whisper opt-in.

Project description

transcribe

Drop-in CLI transcription. Point it at an audio/video file (or a folder), get a transcript next to it. Groq by default, local Whisper opt-in (planned).

transcribe podcast.mp3                              # -> podcast.txt
transcribe ./voice-notes/                           # -> .txt next to every clip
transcribe meeting.mp4 -t srt                       # -> meeting.srt
transcribe lecture.m4a -t md --timestamps           # -> lecture.md with [mm:ss]
transcribe ./media/ -r -t json -o ./transcripts/    # recursive, JSON, one output dir
transcribe interview.mp3 --diarize                  # label speakers: "Speaker 1: ..."

Install

pipx install aria-transcribe
# or
uv tool install aria-transcribe

From source (dev): pipx install -e . · uv tool install -e .

Optional extras:

  • [local] — adds faster-whisper for offline transcription (Phase 3, not built yet)
  • [keyring] — opt-in system keyring for API key storage
  • [diarize] — adds pyannote.audio + torch for speaker labels (--diarize); ~2 GB, see Speaker diarization
  • [all] — everything

Prerequisites

  • Python 3.11+
  • ffmpeg + ffprobe on PATH
    • Windows: winget install Gyan.FFmpeg · scoop install ffmpeg · choco install ffmpeg
    • macOS: brew install ffmpeg
    • Linux: pacman -S ffmpeg · apt install ffmpeg · dnf install ffmpeg
  • GROQ_API_KEY for cloud transcription — grab one from console.groq.com/keys

Setup

Set the API key one of three ways (precedence: CLI > env > config):

# 1. env var (recommended — survives across sessions)
export GROQ_API_KEY="gsk_..."                   # bash/zsh
$env:GROQ_API_KEY = "gsk_..."                   # PowerShell

# 2. one-off
transcribe clip.mp3 --api-key gsk_...

# 3. config file (see below) — handy on machines you fully control

Config file

First run writes a commented template to:

  • $XDG_CONFIG_HOME/transcribe/config.toml if set
  • otherwise ~/.config/transcribe/config.toml (works on Windows too)

Edit the values you want; everything is optional. CLI flags and env vars always win.

[defaults]
backend = "groq"
file_type = "txt"
timestamps = false
# output_dir = "~/transcripts"
# prompt_file = "~/path/to/custom-glossary.txt"

[groq]
# api_key = "gsk_..."          # prefer GROQ_API_KEY env var
model = "whisper-large-v3-turbo"
upload_limit_mb = 24

[diarize]
enabled = false                # default for --diarize
engine = "pyannote"
model = "pyannote/speaker-diarization-3.1"
device = "auto"                # auto | cpu | cuda
# hf_token = "hf_..."          # prefer HF_TOKEN env var; license must be accepted

[ui]
accent_color = "#ff2e88"

Glossary trick (proper-noun accuracy)

Drop a ~/.config/transcribe/glossary.txt with your proper nouns:

Nvikelo Nyathi, AriaCode Tech, Ableton, OpenClaw, Zellij,
vanity arias, Bulawayo, Ndebele, Shaka Zulu, Whisper, Groq

It auto-loads as the default --prompt so Whisper spells your names right across every job. Trimmed to the trailing ~224 tokens (Whisper's prompt budget) if longer. Override per-job with --prompt "..." or --initial-prompt-file path.

Speaker diarization

Label who said what. Whisper only transcribes — diarization is a separate local pass (pyannote.audio) joined onto the transcript by timestamp, so every output format gains Speaker N labels.

uv tool install -e '.[diarize]'                 # one-time: adds pyannote + torch (~2 GB)
export HF_TOKEN="hf_..."                         # accept the model license first (link below)
transcribe interview.mp3 --diarize               # -> "Speaker 1: ...", "Speaker 2: ..."
transcribe call.m4a --diarize --speakers 2       # exact speaker-count hint
transcribe panel.mp4 --diarize --min-speakers 3 --max-speakers 5
transcribe chat.wav --diarize --speaker-names "Alice,Bob"   # rename Speaker 1,2

One-time setup:

  1. Install the extra: uv tool install -e '.[diarize]'.
  2. Create a Hugging Face token and accept the license for BOTH gated models the pipeline pulls: pyannote/speaker-diarization-3.1 and pyannote/segmentation-3.0. (Accepting only the first gives a 403 on the second at model-load time.)
  3. Provide the token via HF_TOKEN, --hf-token, or [diarize] hf_token in config.

Notes:

  • Word-level assignment. A Whisper segment spanning a speaker change is split, so turn boundaries land in the right place instead of mislabeling the whole line.
  • Fail-hard by default. If diarization errors at runtime, the run fails (exit 6) rather than silently writing an unlabeled transcript. Pass --diarize-best-effort to warn-and-write the transcript without labels instead.
  • GPU strongly preferred for long files (device = "cuda"; ROCm works on the RX 6800).
  • Missing extra → exit 3; missing/unauthorized token → exit 4 (caught as a preflight before any file is processed).

All flags

Flag Short Default Notes
PATH (required) File or directory. Directory → batch.
--file-type -t txt txt · md · srt · json
--output -o next to source Existing dir → auto-named inside; else verbatim path.
--backend -b groq groq · local (local TBD)
--model -m per-backend default e.g. whisper-large-v3-turbo
--language -l auto-detect ISO code; skips detection → slightly faster.
--translate off Whisper translate-to-English mode.
--timestamps / --no-timestamps from config mm:ss markers in txt/md only. srt/json always timestamped.
--prompt -p none Initial prompt to bias vocabulary.
--initial-prompt-file none Load prompt text from file.
--vad / --no-vad on Silero VAD silence stripping (local backend only).
--diarize / --no-diarize from config Label speakers (needs [diarize] extra + HF_TOKEN).
--diarize-best-effort off On diarizer runtime failure, write transcript unlabeled + warn instead of failing.
--speakers auto Exact speaker-count hint. Exclusive with --min/--max-speakers.
--min-speakers auto Lower bound on speaker count.
--max-speakers auto Upper bound on speaker count.
--speaker-names none Comma-separated names mapped to Speaker 1,2,....
--hf-token env / config Hugging Face token for pyannote (highest precedence).
--recursive -r off Recurse into subdirectories in batch mode.
--api-key env / config Groq key override (highest precedence).
--quiet -q off Errors + final path only. Pipe-friendly.
--verbose -v off Sizes, timings, language detection, segment count.
--version Print version, exit.

Exit codes

Code Meaning
0 Success (batch: every file succeeded)
1 Generic / batch had failures
2 Bad usage (mutually exclusive flags, etc.)
3 Missing dependency (ffmpeg/ffprobe, or pyannote.audio when --diarize)
4 Missing or invalid Groq API key (or Hugging Face token when --diarize)
5 Input not found / unsupported file type
6 Backend, transcription, or diarization error after retries

Output formats

  • txt — plain text, paragraph-wrapped at 88 cols. With --timestamps, [mm:ss] per segment.
  • md — header (title, language, duration, model, backend) + body. With --timestamps, `[mm:ss]` markers per segment.
  • srt — standard SubRip subtitles; opens in any video editor.
  • json — lossless dump of every segment + per-word timestamps + probabilities (+ speaker when --diarize). Round-trips back via TranscriptionResult.from_dict.

With --diarize, every format gains speaker labels: txt Speaker 1: ... blocks, md **Speaker 1:** headings, srt [Speaker 1] cue prefixes, json per-segment/word speaker.

Status

  • Phase 0 — skeleton (CLI parses, version, help)
  • Phase 1 — Groq happy path (single short file)
  • Phase 2 — all four formats + collision-safe writes + output-path resolution
  • Phase 5 — batch (folder + recursive + continue-on-error)
  • Phase 6 — glossary auto-load + prompt trim + README polish
  • Diarization — optional --diarize speaker labels (pyannote, word-level, all formats)
  • Phase 3 — local backend (faster-whisper)
  • Phase 4 — long-file silence chunking + timestamp stitching (only needed for files >24 MB transcoded, ~7+ hrs)

See transcribe-cli-plan.md for the full spec.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aria_transcribe-0.1.0.tar.gz (266.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aria_transcribe-0.1.0-py3-none-any.whl (32.3 kB view details)

Uploaded Python 3

File details

Details for the file aria_transcribe-0.1.0.tar.gz.

File metadata

  • Download URL: aria_transcribe-0.1.0.tar.gz
  • Upload date:
  • Size: 266.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for aria_transcribe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f02389b03b7eb9edbb47702bb4e4035e36e2859c8574d5c42b97260b7c2896c0
MD5 ec288a97700d6394775cc7f1135d98e8
BLAKE2b-256 4f3efa9538c71c3fc58d945d5de3c1412fe93c43ac7edc7f6f4a4b7bee25a087

See more details on using hashes here.

File details

Details for the file aria_transcribe-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: aria_transcribe-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 32.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for aria_transcribe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4f962adc35755c0e51873007bb8e2d5c8319d5ca0ca8c7ad2fa1526503066147
MD5 38c00c49d009c70bfd54d70724d77c32
BLAKE2b-256 23606f0ac7329f731921036c050f7b4f4e58bb0d35a55ec32f7b798e0dd22adb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page