transcribe
Fast, diarized, timestamped, cleaned-up transcripts from audio/video files. Give it an
.mp3, .mp4, or .mov (any format ffmpeg reads, really) and get a .txt transcript
next to the input.
transcribe episode.mp4
transcribe -c "Interesting Times, an NYT podcast hosted by Ross Douthat" episode.mp4
transcribe https://www.youtube.com/watch?v=jNQXAC9IVRw # URLs fetched server-side
transcribe --srt *.mp3 # parallel, with subtitles
Example output:
[00:14] Ross Douthat: So it seems like the bright, shining, glorious future of the
Democratic Party might just be socialism?
[00:21] Bhaskar Sunkara: Well, I think as long as there is inequality in a society...
Install
git clone https://github.com/emlazzarin/transcribe.git && cd transcribe
./install.sh # or: bash install.sh
The installer checks for Go and ffmpeg (offering to brew install them), prompts for
your ElevenLabs API key (verified
against the API, saved to a gitignored .env with mode 600), builds ./transcribe,
and optionally installs it to ~/.local/bin so it works from any directory.
Go users can skip all that: go install github.com/emlazzarin/transcribe@latest
(Go 1.24+), then provide the key via the environment or ~/.config/transcribe/env.
Manual alternative: go build -o transcribe . and put ELEVENLABS_API_KEY=... in
.env, the environment, or ~/.config/transcribe/env.
Tagged releases build prebuilt binaries for macOS/Linux/Windows (amd64 + arm64) via
GitHub Actions + GoReleaser — see the Releases page if you don't want a Go toolchain.
On Windows, set the key in the environment (or %USERPROFILE%\.config\transcribe\env)
and make sure ffmpeg is on PATH for video inputs.
How it works
- Extract — ffmpeg stream-copies the audio track out of the container (no
re-encode) and pipes it directly into the upload, so extraction and upload
overlap with no temp files. MP3/M4A/FLAC/OGG inputs upload as-is; uncompressed
audio is losslessly FLAC-encoded on the fly. URL inputs (YouTube, TikTok, or
any hosted media) skip all of this — ElevenLabs fetches them server-side.
- Transcribe — ElevenLabs Scribe v2
with speaker diarization, word-level timestamps, server-side disfluency removal
(no "ums", false starts), and keyterm biasing for proper nouns.
- Name & correct (optional) — a small LLM pass reads the transcript and returns
only a tiny JSON payload: a speaker-id → real-name map (only when the evidence is
clear) and high-confidence proper-noun corrections. It's applied deterministically,
so the transcript itself is never LLM-rewritten (fast, and no hallucinated edits).
Backends, in order of preference:
ANTHROPIC_API_KEY → Anthropic API,
GEMINI_API_KEY → Gemini API, otherwise the claude CLI if installed. With no
backend available (or --no-llm), you still get the full transcript — speakers
are just labeled Speaker 1, Speaker 2, …
A 57-minute podcast transcribes in ~2–4 minutes end to end.
Flags
| flag |
|
-c, --context |
Context prompt: named entities, topic, who's speaking. Capitalized terms are mined as recognition keyterms and the full text guides speaker naming. @file.txt reads from a file. |
-o, --output |
Output path (default: input name with .txt). A directory when passing multiple files. |
--keyterms |
Comma-separated extra bias terms. |
--language |
ISO language hint (default: auto-detect). |
--speakers |
Max speaker count hint (1–32). |
--srt, --vtt |
Also write subtitle files (speaker-labeled, ≤2-line cues). |
--verbatim |
Keep filler words / false starts. |
--no-llm |
Skip the speaker-naming/correction pass. |
--llm-model |
Override the naming-pass model. |
--raw <path> |
Also save the raw Scribe JSON response to this path. |
-q, --quiet |
Only print the output path. |
--version |
Print version. |
Notes
- Costs: ElevenLabs bills transcription per audio-hour on your plan. Keyterm
biasing adds a 20% surcharge and is only sent when you provide
--context or
--keyterms. The naming pass makes one (billable) LLM call per file unless it
uses your local claude CLI or you pass --no-llm.
- Speakers that can't be confidently named stay
Speaker 1, Speaker 2, … — the
tool never guesses names.
- Long monologues are split into paragraphs (~2 min) at sentence boundaries, each
with a fresh timestamp.
- Multiple inputs are transcribed in parallel (4 at a time), each line of progress
prefixed with the file name. Every correction the LLM pass applies is logged, so
silent edits are always visible.
- API key lookup order: environment →
./.env → input file's directory .env →
~/.config/transcribe/env.
License
MIT