Install

bun add -g @crafter/trx

Setup

Run trx init to install dependencies and download a Whisper model:

trx init

This will:

  1. Check and install whisper-cli, yt-dlp, and ffmpeg
  2. Let you choose a Whisper model size
  3. Optionally install the Claude Code agent skill

Transcribe

Paste a URL or path to a local file:

# YouTube video
trx "https://youtube.com/watch?v=dQw4w9WgXcQ"

# Local file
trx recording.mp4

# With language override
trx podcast.mp3 --language es

Output: .txt (plain text) and .srt (subtitles with timestamps).

OpenAI API (optional)

For faster transcription without local models:

export OPENAI_API_KEY="sk-..."
trx init --backend openai
trx recording.mp4 -b openai

Vercel AI Gateway (optional)

One API key for any provider’s transcription model, addressed as creator/model-name:

export AI_GATEWAY_API_KEY="..."
trx init --backend vercel
trx recording.mp4 -b vercel -m openai/whisper-1

trx init --backend elevenlabs
trx interview.m4a -b elevenlabs --speakers 2

trx transcribe

Transcribe audio/video from a URL or local file.

trx transcribe <input> [flags]

The transcribe subcommand is optional — trx <input> works the same way.

Flags

FlagDescriptionDefault
-b, --backendTranscription backend (local, openai, vercel, or elevenlabs)from config
-l, --languageISO 639-1 language code (elevenlabs also accepts ISO 639-3)auto
-m, --modelOverride model sizefrom config
-w, --wordsWord-level timestamps in SRTfalse
--presetverbatim keeps fillers and false starts; needs --languagenone
--promptInitial prompt in the spoken language; beats --presetnone
--output-dirDirectory for output files, created if missing.
--fieldsLimit output: text,srt,metadata,filesall
--dry-runShow execution plan without runningfalse
--no-downloadSkip yt-dlp (input must be local)false
--no-cleanSkip ffmpeg audio cleaningfalse
--diarizeLabel each cue with its speaker (elevenlabs only)false
--speakersExpected speaker count, 1-32; implies --diarize (elevenlabs only)none
--no-chunkDisable automatic chunking for oversized cloud uploadsfalse
--jsonRaw JSON payload for agents
-o, --outputOutput format: json, table, autoauto

Models

Local (whisper-cli):

ModelSizeSpeedAccuracy
tiny~75 MBFastestLowest
base~142 MBFastDecent
small~466 MBBalancedGood (recommended)
medium~1.5 GBSlowHigh
large~3 GBSlowestBest
large-v3-turbo~1.6 GBFastNear-large

OpenAI API:

ModelCostNotes
gpt-4o-transcribe$2.50/hrBest accuracy
gpt-4o-mini-transcribe$0.60/hrFastest, cheapest
whisper-1$0.36/hrLegacy, segment timestamps

Vercel AI Gateway:

Any transcription model on the gateway, addressed as creator/model-name (default openai/whisper-1). One AI_GATEWAY_API_KEY covers all providers. This is Vercel’s AI Gateway, not Cloudflare’s product of the same name. Run trx models to see what is available.

ElevenLabs Scribe:

ModelNotes
scribe_v2Latest, speaker diarization and word timestamps (default)
scribe_v1Previous generation

The only backend that separates speakers. Requires ELEVENLABS_API_KEY; on macOS trx also reads the elevenlabs entry from your login Keychain, so a key stored there needs no export.

Speaker diarization

--diarize asks Scribe who is speaking and labels every cue with the result:

1
00:00:01,900 --> 00:00:03,400
[speaker_0] Hola, que tal? Escuchas?

2
00:00:04,520 --> 00:00:05,900
[speaker_1] Si, te escucho bien.

Scribe timestamps every word, so cues are grouped for reading: a pause of 0.6s or more starts a new cue, a cue is capped at 84 characters, and a change of speaker always starts a new one so no cue attributes two people to one line. The .txt becomes a conversation, one paragraph per turn.

Pass --speakers <n> when you know how many people are in the room (1-32); it implies --diarize. Both flags are rejected on any other backend rather than being silently ignored, because an undiarized transcript would otherwise look like the request succeeded.

Big files

Cloud backends have upload limits (OpenAI 25 MB, gateway 100 MB). The ElevenLabs limit is 5 GB, so that backend never chunks. Files over the limit split automatically with ffmpeg, transcribe chunk by chunk, and stitch back into one continuous transcript and SRT with correct timestamps. Use --no-chunk to disable and fail fast instead.

Examples

# Transcribe YouTube video
trx "https://youtube.com/watch?v=abc"

# Spanish podcast with word timestamps
trx podcast.mp3 -l es -w

# OpenAI API with specific model
trx meeting.m4a -b openai -m gpt-4o-mini-transcribe

# Vercel AI Gateway with any provider's model
trx meeting.m4a -b vercel -m openai/whisper-1

# ElevenLabs Scribe, two speakers separated
trx interview.m4a -b elevenlabs --speakers 2 -l spa

# JSON output for piping
trx video.mp4 --output json --fields text

# Dry run to preview
trx video.mp4 --dry-run --output json

Reading the result

"metadata": {
  "language": "es",
  "model": "large-v3-turbo",
  "inputDurationMs": 90538,
  "transcribedDurationMs": 90539,
  "lastCueEndMs": 89120
}

Three durations, no verdict. The gaps say different things:

  • inputDurationMs against transcribedDurationMs is what the cleaning stage changed. They should be within a millisecond of each other. A large gap means the timeline was rewritten and the timestamps do not describe the file you passed in.
  • transcribedDurationMs against lastCueEndMs is audio that produced no words: trailing silence, or a transcription that stopped early.

A short transcript reads the same whether the recording is mostly silence, the model stopped early, or the file handed in was not the one intended. These separate those cases.

Verbatim transcripts

A transcriber cleans by default, dropping hesitations and false starts as noise. That is right for captions and wrong when the transcript drives an edit, because those spans are exactly the ones worth cutting.

trx transcribe video.mp4 --words --language es --preset verbatim

Measured on one recording: the preset recovers Ok. and Eh, where the unprompted run drops both. The prompt has to be written in the language being spoken, so the preset needs --language and covers de, en, es, fr, it, pt. Any other language is an error naming what is available, because a prompt in the wrong language steers the model worse than none. --prompt "<text>" writes your own.


trx models

List available transcription models per backend.

trx models [--backend local|openai|vercel|elevenlabs] [--output json]

Local, OpenAI and ElevenLabs lists are static. The vercel backend queries the gateway live (requires AI_GATEWAY_API_KEY), so you always see what is actually available instead of guessing model slugs.

# All backends grouped
trx models

# Only gateway models, as JSON for agents
trx models --backend vercel --output json

trx init

Install dependencies and configure the transcription backend.

trx init [flags]

Flags

FlagDescriptionDefault
-b, --backendBackend: local, openai, vercel, or elevenlabslocal
-m, --modelModel to download/configuresmall
-l, --languageDefault languageauto

What it does

Local backend:

  1. Installs whisper-cli, yt-dlp, ffmpeg via your OS package manager
  2. Downloads the selected Whisper model from Hugging Face
  3. Saves config to ~/.trx/config.json

OpenAI backend:

  1. Validates OPENAI_API_KEY is set
  2. Installs yt-dlp and ffmpeg (still needed for download/clean)
  3. Saves config with selected OpenAI model

Vercel backend:

  1. Validates AI_GATEWAY_API_KEY is set
  2. Installs yt-dlp and ffmpeg (still needed for download/clean)
  3. Saves config with the selected gateway model (creator/model-name)

trx doctor

Health check for all dependencies and configuration.

trx doctor [--output json]

Shows: installed dependencies, versions, config path, model status, backend, API key.


trx schema

Runtime introspection for agents. Returns the JSON schema of any command.

trx schema transcribe
trx schema init

Agents use this to discover available flags and their types without reading docs.

What is the agent skill?

trx ships with a SKILL.md that teaches Claude Code how to use the CLI and post-process transcription results. When installed, agents can:

  • Transcribe URLs and files autonomously
  • Fix common Whisper mistakes (proper nouns, technical terms)
  • Extract structured data from transcripts
  • Generate summaries, translations, and subtitles

Install

npx skills add crafter-station/trx -g

Or during trx init, accept the skill installation prompt.

How it works

  1. Agent calls trx schema transcribe to discover available flags
  2. Agent runs trx <input> --output json to get structured output
  3. Agent reads the .txt file and applies corrections
  4. Agent can chain with other tools (translation, summarization)

Example agent workflow

User: "Transcribe this video and fix any technical terms"

Agent:
1. trx schema transcribe          # discover flags
2. trx "https://..." --output json # transcribe
3. Read output .txt file           # get raw text
4. Fix "reakt" → "React", etc.    # post-process
5. Write corrected file            # save result

Self-correction patterns

The skill teaches agents to watch for:

  • Proper nouns: Brand names, people, places
  • Technical terms: Programming languages, frameworks, APIs
  • Homophones: “their/there/they’re”, “your/you’re”
  • Filler removal: “um”, “uh”, “like” (optional)

Config file

trx stores configuration at ~/.trx/config.json. Created automatically by trx init.

{
  "backend": "local",
  "modelPath": "~/.trx/models/ggml-small.bin",
  "modelSize": "small",
  "language": "auto",
  "threads": 8,
  "wordTimestamps": false,
  "openai": {
    "model": "gpt-4o-transcribe"
  },
  "elevenlabs": {
    "model": "scribe_v2",
    "diarize": false
  },
  "vercel": {
    "model": "openai/whisper-1"
  },
  "whisperFlags": {
    "suppressNst": true,
    "noFallback": true,
    "entropyThold": 2.8,
    "logprobThold": -1.0,
    "maxContext": 0
  }
}

Fields

FieldTypeDescription
backend"local" | "openai" | "vercel" | "elevenlabs"Active transcription backend
modelPathstringPath to the local Whisper model file
modelSizestringModel size identifier
languagestringDefault language ("auto" for detection)
threadsnumberCPU threads for local transcription
wordTimestampsbooleanEnable word-level SRT by default
openai.modelstringDefault OpenAI model
vercel.modelstringDefault gateway model (creator/model-name)
elevenlabs.model"scribe_v2" | "scribe_v1"Default Scribe model
elevenlabs.diarizebooleanSeparate speakers by default
whisperFlagsobjectAdvanced whisper-cli flags

Environment variables

VariableRequiredDescription
OPENAI_API_KEYFor OpenAI backendYour OpenAI API key
AI_GATEWAY_API_KEYFor Vercel backendYour Vercel AI Gateway API key
ELEVENLABS_API_KEYFor ElevenLabs backendYour ElevenLabs API key. On macOS trx falls back to the elevenlabs entry in your login Keychain

Models directory

Downloaded models are stored at ~/.trx/models/. Each model is a .bin file downloaded from Hugging Face.

Override per-command

Any config value can be overridden via CLI flags:

# Override backend
trx video.mp4 --backend openai

# Override model
trx video.mp4 --model large-v3-turbo

# Override language
trx video.mp4 --language es